pnpm fixture ๋ช
๋ น์ด๋ ํ
์คํธ์ ์ฌ์ฉํ ์ผ๊ด๋ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ๋ฐ์ดํฐ๋ฅผ ํ
์คํธ ํ๊ฒฝ์ผ๋ก ๋ณต์ฌํ์ฌ, ์์ ์ ์ด๊ณ ๋ฐ๋ณต ๊ฐ๋ฅํ ํ
์คํธ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ ๊ฐ๋
Fixture๋ ํ
์คํธ์ฉ ๊ณ ์ ๋ ๋ฐ์ดํฐ ์ธํธ์
๋๋ค:
- ์ผ๊ด์ฑ: ๋ชจ๋ ํ
์คํธ๊ฐ ๊ฐ์ ์ด๊ธฐ ๋ฐ์ดํฐ๋ก ์์
- ๊ฒฉ๋ฆฌ: ํ
์คํธ DB์ ๊ฐ๋ฐ DB ๋ถ๋ฆฌ
- ์ฌํ์ฑ: ๊ฐ์ ์กฐ๊ฑด์์ ๋ฐ๋ณต ํ
์คํธ ๊ฐ๋ฅ
- ๊ด๊ณ ๋ณด์กด: ์ธ๋ํค ๊ด๊ณ๊ฐ ์ ์ง๋จ
๋ช
๋ น์ด
init - ํ
์คํธ DB ์ด๊ธฐํ
๊ฐ๋ฐ DB์ ์คํค๋ง๋ฅผ ํ
์คํธ DB๋ก ๋ณต์ฌํฉ๋๋ค.
์คํ ๊ณผ์ :
DUMP...
โ Schema dumped from development_master
SYNC to (REMOTE) Fixture DB...
โ Database myapp_fixture created
โ Schema applied
SYNC to (LOCAL) Testing DB...
โ Database myapp_test created
โ Schema applied
Fixture initialization completed!
์์ฑ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค:
- Fixture DB (์๊ฒฉ): ๊ณต์ fixture ์ ์ฅ์
- Test DB (๋ก์ปฌ): ๋ก์ปฌ ํ
์คํธ์ฉ DB
init์ ์คํค๋ง๋ง ๋ณต์ฌํฉ๋๋ค. ๋ฐ์ดํฐ๋ ํฌํจ๋์ง ์์ต๋๋ค.
import - ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
๊ฐ๋ฐ DB์์ ํน์ ๋ ์ฝ๋๋ฅผ fixture๋ก ์ ์ฅํฉ๋๋ค.
๋ํํ ํ๋กฌํํธ๊ฐ ํ์๋ฉ๋๋ค:
? Please select entity: (Use arrow keys)
โฏ User
Post
Comment
? Enter record IDs (comma-separated): 1,2,3
Importing fixtures...
โ Imported User #1
โ Imported User #2
โ Imported User #3
โ Imported related records (5 dependencies)
Fixture import completed!
์๋์ผ๋ก ํฌํจ๋๋ ๊ด๋ จ ๋ฐ์ดํฐ:
- ์ธ๋ํค๋ก ์ฐธ์กฐ๋๋ ๋ ์ฝ๋
- ๊ด๊ณ ํ
์ด๋ธ์ ๋ ์ฝ๋
- ์ญ์ฐธ์กฐ ๋ ์ฝ๋ (์ ํ ๊ฐ๋ฅ)
sync - ๋๊ธฐํ
์ ์ฅ๋ fixture๋ฅผ ํ
์คํธ DB์ ์ ์ฉํฉ๋๋ค.
์คํ ๊ณผ์ :
Syncing fixtures...
Clearing test database...
โ Cleared all tables
Applying fixtures...
โ Applied 3 users
โ Applied 7 posts
โ Applied 12 comments
โ Applied 5 categories
Fixture sync completed!
ํ
์คํธ ์คํ ์ ์ sync๋ฅผ ํธ์ถํ๋ฉด ํญ์ ๊นจ๋ํ ์ํ์์ ์์ํ ์ ์์ต๋๋ค.
gen - ์๋ Fixture ์์ฑ
Entity์ cone ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ์ฌ ์๋์ผ๋ก Fixture๋ฅผ ์์ฑํฉ๋๋ค. ์ค์ ๋ฐ์ดํฐ๊ฐ ์๊ฑฐ๋ ๊ฐ์์ ํ
์คํธ ๋ฐ์ดํฐ๊ฐ ํ์ํ ๋ ์ ์ฉํฉ๋๋ค.
๋ํํ ๋ชจ๋:
? Fixture๋ฅผ ์์ฑํ Entity๋ฅผ ์ ํํ์ธ์: (Use arrow keys)
โฏ โฏ User
โฏ Post
โฏ Comment
? ๊ฐ Entity๋ณ ์์ฑ ๊ฐ์: 5
? ์ ์ฅ ๋ฐฉ์: (Use arrow keys)
โฏ Fixture DB์ ์ ์ฅ
ํ์ผ๋ก ์ ์ฅ (์๋ ํ์ผ๋ช
)
ํ์ผ๋ก ์ ์ฅ (ํ์ผ๋ช
์ง์ )
์ ์ฅ ์ ํจ (์ถ๋ ฅ๋ง)
? LLM์ผ๋ก ๋ ํ์ค์ ์ธ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ๊น์? (fixtureHint ๊ธฐ๋ฐ, ANTHROPIC_API_KEY ํ์) No
CLI ์ต์
:
| ์ต์
| ์ค๋ช
| ์์ |
|---|
--all | ๋ชจ๋ Entity์ ๋ํด ์์ฑ | pnpm fixture gen --all |
--include | ํน์ Entity๋ง ํฌํจ | pnpm fixture gen --include User,Post |
--exclude | ํน์ Entity ์ ์ธ (โall๊ณผ ํจ๊ป ์ฌ์ฉ) | pnpm fixture gen --all --exclude Comment |
--count | ์์ฑํ ๋ ์ฝ๋ ์ | pnpm fixture gen --include User --count 10 |
--save-to | ์ ์ฅ ๋ฐฉ์ ์ง์ | pnpm fixture gen --save-to db |
--use-llm | LLM์ผ๋ก ํ์ค์ ์ธ ๋ฐ์ดํฐ ์์ฑ (fixtureHint ๊ธฐ๋ฐ, ANTHROPIC_API_KEY ํ์) | pnpm fixture gen --use-llm |
--no-cache | LLM ์บ์ ๋นํ์ฑํ (--use-llm๊ณผ ํจ๊ป ์ฌ์ฉ) | pnpm fixture gen --use-llm --no-cache |
์ ์ฅ ๋ฐฉ์:
db: Fixture DB์ ์ง์ ์ ์ฅ (๊ธฐ๋ณธ๊ฐ)
file: test/fixtures/{entity_table}.json ํ์ผ๋ก ์ ์ฅ
file:{filename}: ์ง์ ๋ ํ์ผ๋ช
์ผ๋ก ์ ์ฅ
none: ์ ์ฅํ์ง ์๊ณ ์ฝ์์ ์ถ๋ ฅ๋ง
# ์์: User, Post ๊ฐ 10๊ฐ์ฉ ์์ฑํ์ฌ DB์ ์ ์ฅ
pnpm fixture gen --include User,Post --count 10 --save-to db
fetch - ์ด์ DB์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
์ค์ ์ด์ DB(๋๋ ๊ฐ๋ฐ DB)์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ Fixture DB์ ์ ์ฅํฉ๋๋ค. ํ์ค์ ์ธ ํ
์คํธ ๋ฐ์ดํฐ๊ฐ ํ์ํ ๋ ์ฌ์ฉํฉ๋๋ค.
๋ํํ ๋ชจ๋:
? Importํ Entity๋ฅผ ์ ํํ์ธ์: (Use arrow keys)
โฏ โฏ User
โฏ Post
โฏ Comment
User, Post import ์ค...
โ User: 10๊ฐ import ์๋ฃ
โ Post: 10๊ฐ import ์๋ฃ
CLI ์ต์
:
| ์ต์
| ์ค๋ช
| ์์ |
|---|
--all | ๋ชจ๋ Entity์์ ๊ฐ์ ธ์ค๊ธฐ | pnpm fixture fetch --all |
--include | ํน์ Entity๋ง ํฌํจ | pnpm fixture fetch --include User,Post |
--exclude | ํน์ Entity ์ ์ธ | pnpm fixture fetch --all --exclude Log |
--strategy | ๋ฐ์ดํฐ ์ ํ ์ ๋ต | pnpm fixture fetch --strategy recent |
--limit | ๊ฐ์ ธ์ฌ ๋ ์ฝ๋ ์ | pnpm fixture fetch --limit 20 |
๋ฐ์ดํฐ ์ ํ ์ ๋ต:
recent (๊ธฐ๋ณธ๊ฐ): ์ต๊ทผ ๋ฐ์ดํฐ๋ถํฐ ๊ฐ์ ธ์ด
sample: ๋ฌด์์ ์ํ๋ง
# ์์: User์ ์ต๊ทผ 20๊ฐ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
pnpm fixture fetch --include User --strategy recent --limit 20
ํน์ง:
- ๊ด๊ณ๋ ๋ฐ์ดํฐ๋ ํจ๊ป ์๋์ผ๋ก ๊ฐ์ ธ์ด (๊น์ด 2 ๋ ๋ฒจ๊น์ง)
- ์ธ๋ํค ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ ์ ์ง
explore - DB ๋ฐ์ดํฐ ์กฐํ
DB์ ๋ฐ์ดํฐ๋ฅผ ์กฐํ๋ง ํฉ๋๋ค. ์ ์ฅํ์ง ์๊ณ ๋น ๋ฅด๊ฒ ๋ฐ์ดํฐ๋ฅผ ํ์ธํ ๋ ์ ์ฉํฉ๋๋ค.
๋ํํ ๋ชจ๋:
? ํ์ํ Entity: User
User 10๊ฐ ์กฐํ ์๋ฃ:
โโโโโโโโโโโฌโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโ
โ (index) โ id โ email โ name โ
โโโโโโโโโโโผโโโโโผโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโค
โ 0 โ 1 โ 'user1@example.com'โ 'ํ๊ธธ๋' โ
โ 1 โ 2 โ 'user2@example.com'โ '๊น์ฒ ์' โ
โ ... โ... โ ... โ ... โ
โโโโโโโโโโโดโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโ
CLI ์ต์
:
| ์ต์
| ์ค๋ช
| ์์ |
|---|
--include | ํ์ํ Entity | pnpm fixture explore --include User |
--strategy | ๋ฐ์ดํฐ ์ ํ ์ ๋ต | pnpm fixture explore --strategy sample |
--limit | ์กฐํํ ๋ ์ฝ๋ ์ | pnpm fixture explore --limit 5 |
๋ฐ์ดํฐ ์ ํ ์ ๋ต:
sample (๊ธฐ๋ณธ๊ฐ): ๋ฌด์์ ์ํ
recent: ์ต๊ทผ ๋ฐ์ดํฐ
random: ์์ ๋ฌด์์
ids: ํน์ ID ์ง์
query: ์ปค์คํ
์ฟผ๋ฆฌ
# ์์: User ํ
์ด๋ธ์์ ์ต๊ทผ 5๊ฐ ์กฐํ
pnpm fixture explore --include User --strategy recent --limit 5
์ฌ์ฉ ์ํฌํ๋ก์ฐ
1. ์ด๊ธฐ ์ค์
ํ๋ก์ ํธ ์์ ์ ํ ๋ฒ๋ง ์คํํฉ๋๋ค.
# ํ
์คํธ DB ์์ฑ ๋ฐ ์คํค๋ง ๋ณต์ฌ
pnpm fixture init
2. ํ์ํ ๋ฐ์ดํฐ ์ ํ
ํ
์คํธ์ ํ์ํ ์ค์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
# User #1, #2, #3 ๊ฐ์ ธ์ค๊ธฐ
pnpm fixture import
# Entity: User
# IDs: 1,2,3
3. ํ
์คํธ ์์ฑ
import { FixtureManager } from "sonamu/test";
beforeAll(async () => {
// Fixture ๋๊ธฐํ
await FixtureManager.sync();
});
test("User๋ฅผ ์ด๋ฉ์ผ๋ก ์ฐพ๊ธฐ", async () => {
// Fixture์ User #1 ์ฌ์ฉ
const user = await UserModel.findByEmail("user1@example.com");
expect(user).toBeDefined();
expect(user.id).toBe(1);
});
4. ํ
์คํธ ์คํ
ํ
์คํธ๊ฐ ์คํ๋ ๋๋ง๋ค fixture๊ฐ ์๋์ผ๋ก ๋๊ธฐํ๋ฉ๋๋ค.
Fixture ํ์ผ
์ ์ฅ ์์น
๐src/
๐fixtures/
๐JSONusers.json - User fixture
๐JSONposts.json - Post fixture
๐JSONcomments.json - Comment fixture
ํ์ผ ํ์
[
{
"id": 1,
"email": "user1@example.com",
"name": "ํ๊ธธ๋",
"created_at": "2024-01-15T00:00:00.000Z"
},
{
"id": 2,
"email": "user2@example.com",
"name": "๊น์ฒ ์",
"created_at": "2024-01-16T00:00:00.000Z"
}
]
ํน์ง:
- JSON ํ์
- Entity๋ณ๋ก ํ์ผ ๋ถ๋ฆฌ
- ๊ด๊ณ ๋ฐ์ดํฐ ์๋ ํฌํจ
- Git์ผ๋ก ๋ฒ์ ๊ด๋ฆฌ
๊ด๊ณ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
์ธ๋ํค ์๋ ํฌํจ
Post๋ฅผ importํ๋ฉด ์ฐ๊ฒฐ๋ User๋ ์๋์ผ๋ก ํฌํจ๋ฉ๋๋ค.
pnpm fixture import
# Entity: Post
# IDs: 1
# ์๋์ผ๋ก ํฌํจ๋จ:
# โ Post #1
# โ User #5 (author)
# โ Category #2 (category)
N:M ๊ด๊ณ ์ฒ๋ฆฌ
๋ค๋๋ค ๊ด๊ณ ํ
์ด๋ธ๋ ์๋์ผ๋ก ํฌํจ๋ฉ๋๋ค.
pnpm fixture import
# Entity: Post
# IDs: 1
# ์๋์ผ๋ก ํฌํจ๋จ:
# โ Post #1
# โ post_tags (์ค๊ฐ ํ
์ด๋ธ)
# โ Tag #1, #2, #3 (์ฐ๊ฒฐ๋ ํ๊ทธ๋ค)
ํ
์คํธ ๊ฒฉ๋ฆฌ
๊ฐ ํ
์คํธ๋ง๋ค ์ด๊ธฐํ
describe("User CRUD", () => {
beforeEach(async () => {
// ๊ฐ ํ
์คํธ ์ ์ fixture ์ฌ์ ์ฉ
await FixtureManager.sync();
});
test("์ฌ์ฉ์ ์์ฑ", async () => {
const user = await UserModel.create({
email: "new@example.com",
name: "์ ๊ท์ฌ์ฉ์",
});
expect(user.id).toBeDefined();
});
test("์ฌ์ฉ์ ์ญ์ ", async () => {
await UserModel.deleteById(1);
const user = await UserModel.findById(1);
expect(user).toBeNull();
});
});
๊ฒฉ๋ฆฌ ํจ๊ณผ:
- ๊ฐ ํ
์คํธ๊ฐ ๋
๋ฆฝ์
- ํ
์คํธ ์์ ๋ฌด๊ด
- ๋ณ๋ ฌ ์คํ ๊ฐ๋ฅ
ํธ๋์ญ์
๊ฒฉ๋ฆฌ
import { Sonamu } from "sonamu";
test("ํธ๋์ญ์
ํ
์คํธ", async () => {
await Sonamu.runScript(async () => {
// ํธ๋์ญ์
๋ด์์ ์คํ
const user = await UserModel.create({...});
const post = await PostModel.create({...});
// ํ
์คํธ ์๋ฃ ํ ์๋ ๋กค๋ฐฑ
});
});
์ค์ ์์
๋ณต์กํ ๊ด๊ณ ํ
์คํธ
describe("Post with Comments", () => {
beforeAll(async () => {
// Post #1 (+ User #1, Comments)
await FixtureManager.sync();
});
test("๋๊ธ์ด ์๋ Post ์กฐํ", async () => {
const post = await PostModel.findById(1, {
include: ["comments"],
});
expect(post.comments).toHaveLength(3);
expect(post.comments[0].author_id).toBe(2);
});
});
ํน์ ์๋๋ฆฌ์ค ๋ฐ์ดํฐ
describe("Premium User Features", () => {
beforeAll(async () => {
// Premium user๋ง import
await FixtureManager.importFixture("User", [10, 11, 12]);
await FixtureManager.sync();
});
test("ํ๋ฆฌ๋ฏธ์ ๊ธฐ๋ฅ ์ ๊ทผ", async () => {
const user = await UserModel.findById(10);
expect(user.isPremium).toBe(true);
expect(await user.canAccessFeature("advanced")).toBe(true);
});
});
๋ฌธ์ ํด๊ฒฐ
Fixture DB ์ฐ๊ฒฐ ์คํจ
๋ฌธ์ : ์๊ฒฉ fixture DB์ ์ ๊ทผ ๋ถ๊ฐ
Error: connect ECONNREFUSED
ํด๊ฒฐ:
export default {
database: {
fixture: {
client: "pg",
connection: {
host: "fixture-db.example.com", // ์ฌ๋ฐ๋ฅธ ํธ์คํธ
database: "myapp_fixture",
user: "postgres",
password: process.env.FIXTURE_DB_PASSWORD,
},
},
},
};
๊ด๊ณ ๋ฐ์ดํฐ ๋๋ฝ
๋ฌธ์ : ์ธ๋ํค ์๋ฌ ๋ฐ์
Error: Foreign key constraint violation
ํด๊ฒฐ:
# ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ import
pnpm fixture import
# Entity: User
# IDs: 1,2,3
pnpm fixture import
# Entity: Post
# IDs: 1,2,3 # User 1,2,3์ ์ฐธ์กฐ
Fixture ์ถฉ๋
๋ฌธ์ : ID ์ค๋ณต
Error: Duplicate entry '1' for key 'PRIMARY'
ํด๊ฒฐ:
# Test DB ์ด๊ธฐํ
pnpm fixture init
# Fixture ์ฌ๋๊ธฐํ
pnpm fixture sync
๋ฒ ์คํธ ํ๋ํฐ์ค
1. ์ต์ํ์ ๋ฐ์ดํฐ
# โ ๋ชจ๋ ๋ฐ์ดํฐ import
pnpm fixture import
# IDs: 1-1000
# โ
ํ์ํ ๋ฐ์ดํฐ๋ง
pnpm fixture import
# IDs: 1,2,3 # ๋ํ ์ผ์ด์ค๋ง
2. ์๋ฏธ์๋ ๋ฐ์ดํฐ
// โ
ํ
์คํธ ๋ชฉ์ ์ด ๋ช
ํํ ๋ฐ์ดํฐ
{
"id": 1,
"email": "admin@example.com",
"role": "admin",
"name": "๊ด๋ฆฌ์"
}
{
"id": 2,
"email": "user@example.com",
"role": "user",
"name": "์ผ๋ฐ์ฌ์ฉ์"
}
3. ๋ฒ์ ๊ด๋ฆฌ
# Fixture ํ์ผ์ Git์ ํฌํจ
git add src/fixtures/
git commit -m "Update test fixtures"
4. CI/CD ํตํฉ
.github/workflows/test.yml
jobs:
test:
steps:
- name: Setup Database
run: |
pnpm fixture init
pnpm fixture sync
- name: Run Tests
run: pnpm test
๋ค์ ๋จ๊ณ