ExMachina เป็น library ที่ช่วยให้เราจัดเตรียมข้อมูลสำหรับทดสอบให้แยกออกมาอยู่ที่เดียวกัน ทำให้โค้ดที่เขาเขียนเทสจริงๆไม่รกและเราเอาสิ่งที่แยกมาไปใช้ได้ในหลายๆเทสเคสได้
การจะใช้งาน ExMachina ขั้นแรกเราเพิ่ม dependency ให้กับ mix.exs
ของเราก่อนแบบนี้
{:ex_machina, "~> 2.5.0"}
เราสามารถเขียนโค้ดของ module ที่เป็น Factory module ในการจัดเตรียม test data ไว้ที่ไหนก็ได้ แต่จาก document ของ ExMachina เนี่ยแนะนำว่าให้เอาไว้ที่ test/support
directory
แต่ว่าพอเอาไว้ในนี้ต้องไม่ลืมเพิ่ม elixir_paths ให้กับ application config ของ mix.exs
ด้วยไม่งั้น compiler มันจะไม่ compile โค้ดในนี้ เรา config แบบนี้
def project do
[
app: :ecto_sample,
version: "0.1.0",
elixir: "~> 1.11",
start_permanent: Mix.env() == :prod,
deps: deps(),
# ตรงนี้ให้ไปเรียก `elixir_paths` เพื่อ config ขึ้นอยู่กับแต่ละ Mix.env
elixirc_paths: elixirc_paths(Mix.env()), ()
aliases: aliases()
]
end
# ถ้าเป็น :test env ก็ให้ compile ของใน `test/support` ด้วย
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
ส่วนวิธีการเขียนโค้ด factory module นั้นก็ง่ายๆคือให้สร้าง module แล้ว use ExMachina
หรือ ExMachina.Ecto
ถ้าเราใช้เตรียมข้อมูลให้กับ Ecto Schema โดยต้อง config repo module ให้ด้วย
จากนั้นก็สร้าง function ที่ลงท้ายด้วย _factory
ซึ่งจะเป็นฟังก์ชันที่เราไปใช้กับ build
, insert
method ของ ExMachina ได้ ตัวอย่างเช่น
defmodule EctoSample.Factory do
use ExMachina.Ecto, repo: EctoSample.Repo
def post_factory do
%EctoSample.Post{
title: "Sample use ExMachina",
body: "Example to prepare fixture data for testing"
}
end
end
ผมก็เขียนฟังก์ชัน post_factory
ซึ่งก็แค่เตรียมข้อมูลของ EctoSample.Post
schema เอาไว้ ทีนี้ตอนใช้งานใน test case สิ่งที่เราทำก็คือใช้ ExMachina ฟังก์ชันอย่าง build
เพื่อสร้างค่าตาม factory function หรือใช้ insert
เพื่อ insert ค่าลง DB ตาม factory function ตัวอย่างเช่น
defmodule EctoSampleTest do
use ExUnit.Case
# ต้อง import factory module ที่ต้องการใช้เข้ามาก่อน
import EctoSample.Factory
test "build post by ExMachina Factory" do
post = build(:post)
{:ok, post} = EctoSample.Repo.insert(post)
assert post.title == "Sample use ExMachina"
assert post.body == "Example to prepare fixture data for testing"
end
test "insert post by ExMachina Factory" do
post = insert(:post)
assert post.title == "Sample use ExMachina"
assert post.body == "Example to prepare fixture data for testing"
end
end
ซึ่งค่าที่ส่งให้ build
กับ insert
ก็คือชื่อของ factory ชื่อของฟังก์ชันที่อยู่ก่อนคำว่า _factory
นั่นเอง
ทีนี้ถ้าเทสเคสของเรามีข้อมูลที่ต้องการปรับจากค่าที่เตรียมไว้ใน factory ทั้ง insert
และ build
สามารถรับค่า key: value เพิ่มไปได้เพื่อเปลี่ยนแค่บาง field เช่นอ
test "insert post by ExMachina Factory with title Hello ExMachina" do
post = insert(:post, title: "Hello ExMachina")
assert post.title == "Hello ExMachina"
assert post.body == "Example to prepare fixture data for testing"
end
สรุป ExMachina ช่วยทำให้การจัดเตรียมข้อมูลสำหรับเทสนั้นเป็นสัดส่วนและดูแลง่าย และทำให้โค้ดในส่วนการเทสจริงๆไม่รกเต็มไปด้วยโค้ดในการเตรียมข้อมูลที่ซ้ำซ้อนเวลาเปลี่ยนทีก็ยากแบบก่อนที่จะใช้ ExMachina ช่วยนั่นเอง
Top comments (0)