test-data-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<objective>
Create, maintain, and clean up test data that is deterministic, isolated, realistic, and safe. Good test data is the foundation of reliable tests -- without it, tests are either flaky (shared mutable state), unrealistic (hardcoded nonsense values), or dangerous (production PII in test environments). This skill delivers factories, fixtures, idempotent seeds, anonymization pipelines, and cleanup strategies that survive parallel execution.
</objective>
<objective>
创建、维护和清理具有确定性、隔离性、真实性和安全性的测试数据。优质的测试数据是可靠测试的基础——没有它,测试要么不稳定(共享可变状态),要么不真实(硬编码的无意义值),要么存在风险(测试环境中包含生产环境的个人可识别信息PII)。本技能提供可支持并行执行的工厂、夹具、幂等种子数据、匿名化流水线和清理策略。
</objective>
Quick Route
快速指南
| Situation | Go to |
|---|---|
| Need fresh entity data with per-test overrides | Factory Patterns → |
| Mocking an API response or golden file | Fixture Strategies → |
| Copying production data anywhere non-prod | Data Anonymization |
| Populating a test DB / reference data idempotently | Database Seeding → |
| Cleaning up after tests / parallel isolation | Cleanup Strategies → |
| Generating edge cases and boundary values | Synthetic Data → |
| 场景 | 查看内容 |
|---|---|
| 需要可按测试覆盖的全新实体数据 | 工厂模式 → |
| 模拟API响应或基准文件 | 夹具策略 → |
| 将生产数据复制到非生产环境 | 数据匿名化 |
| 幂等填充测试数据库/参考数据 | 数据库种子数据 → |
| 测试后清理/并行隔离 | 清理策略 → |
| 生成边缘案例和边界值 | 合成数据 → |
Discovery Questions
探索问题
Before designing a test data strategy, understand the current state. Check first -- if it exists, use it as the foundation and skip questions already answered there.
.agents/qa-project-context.md在设计测试数据策略之前,先了解当前状态。首先查看——如果存在,以此为基础并跳过已回答的问题。
.agents/qa-project-context.mdCurrent Data Practices
当前数据实践
- How is test data created today? (manually, scripts, copy of production, none)
- Do tests share data or does each test create its own?
- How is test data cleaned up? (truncate, rollback, manual, never)
- Are there seed scripts? Are they idempotent?
- 目前如何创建测试数据?(手动、脚本、生产数据副本、无)
- 测试是共享数据还是每个测试创建自己的数据?
- 如何清理测试数据?(截断、回滚、手动、从不清理)
- 是否有种子脚本?它们是否具有幂等性?
Privacy and Compliance
隐私与合规
- Does the product handle PII? (names, emails, addresses, phone numbers, SSNs)
- Are there GDPR, HIPAA, PCI-DSS, or other data protection requirements?
- Is production data ever used in test environments?
- 产品是否处理个人可识别信息(PII)?(姓名、邮箱、地址、电话号码、社保号)
- 是否有GDPR、HIPAA、PCI-DSS或其他数据保护要求?
- 测试环境中是否曾使用生产数据?
Scale and Complexity
规模与复杂度
- How large are the test datasets? (dozens of records, thousands, millions)
- How complex are the data relationships? (simple CRUD, deep nested hierarchies, polymorphic)
- Are there cross-service data dependencies? (microservices sharing data)
- 测试数据集有多大?(数十条记录、数千条、数百万条)
- 数据关系有多复杂?(简单CRUD、深度嵌套层级、多态)
- 是否存在跨服务数据依赖?(微服务共享数据)
Core Principles
核心原则
1. Each Test Owns Its Data
1. 每个测试独立拥有其数据
Tests that rely on pre-existing shared data are fragile. When Test A modifies shared data, Test B breaks. Every test should create exactly the data it needs, verify against that data, and clean up after itself. This enables parallel execution and eliminates ordering dependencies.
依赖预先存在的共享数据的测试很脆弱。当测试A修改共享数据时,测试B会失败。每个测试都应创建其恰好需要的数据,针对该数据进行验证,并在自身执行完毕后清理数据。这支持并行执行并消除顺序依赖。
2. Factories Over Fixtures for Dynamic Data
2. 动态数据优先使用工厂而非夹具
Static fixtures (JSON/YAML files) are appropriate for reference data that does not change (country codes, currency lists). For entity data that tests create and manipulate (users, orders, products), use factory functions that generate fresh instances with sensible defaults and allow per-test overrides.
静态夹具(JSON/YAML文件)适用于不会更改的参考数据(国家代码、货币列表)。对于测试创建和操作的实体数据(用户、订单、产品),请使用工厂函数生成具有合理默认值的新实例,并允许按测试覆盖默认值。
3. Anonymize Production Data Before Use
3. 使用前先匿名化生产数据
Production databases contain the most realistic data, but they also contain real user information. Never copy production data to test environments without anonymization. Replace PII with synthetic equivalents while preserving data distributions and relationships.
生产数据库包含最真实的数据,但也包含真实用户信息。未经匿名化,切勿将生产数据复制到测试环境。用合成数据替换PII,同时保留数据分布和关系。
4. Deterministic Data Enables Reproducible Tests
4. 确定性数据实现可复现测试
Tests should produce the same results regardless of when or where they run. Avoid , , or auto-increment IDs in assertions. Use seeded random generators (), fixed timestamps, factory sequences, and -- when an ID must be a UUID you assert on -- a seeded so it stays stable across runs.
Math.random()Date.now()faker.seed(n)faker.string.uuid()无论何时何地运行,测试都应产生相同结果。在断言中避免使用、或自增ID。使用种子随机生成器()、固定时间戳、工厂序列——当必须在断言中使用UUID时,使用种子化的以确保在多次运行中保持稳定。
Math.random()Date.now()faker.seed(n)faker.string.uuid()5. Minimize Data, Maximize Signal
5. 最小化数据,最大化信号
Create only the data each test needs. A test for user search does not need a complete user profile with billing address, payment method, and order history. Over-specified test data obscures the intent of the test and increases maintenance burden.
仅创建每个测试所需的数据。用户搜索测试不需要包含账单地址、支付方式和订单历史的完整用户资料。过度指定的测试数据会掩盖测试意图并增加维护负担。
Factory Patterns
工厂模式
Factories are functions that produce test data with sensible defaults, allowing individual tests to override only what matters for their scenario. Fishery (2.4.0) is the default for TypeScript, FactoryBot (6.6.0) for Ruby, factory-boy (3.3.3) for Python; all pair with faker (v10.4.0) for realistic field values.
See for the full Fishery (with associations and deterministic UUIDs), FactoryBot (User + Product / traits), Factory Boy ( + ), and Playwright fixture implementations. The shape every factory follows:
references/factories.mdout_of_stockdiscountedclass ParamsTrait- Defaults + overrides — produces sensible defaults; tests pass overrides for the one field they care about (
Factory.define).userFactory.build({ role: 'admin' }) - Sequences for unique fields — (Fishery),
sequence(FactoryBot),sequence(:email)(Factory Boy) — never hardcode IDs or emails.factory.Sequence - Traits for variants — name common states (,
:admin,:inactive,out_of_stock) instead of spawning a fixture file per combination.discounted - Associations — one factory builds another (an order builds its user), keeping referential structure without manual wiring.
工厂是生成具有合理默认值的测试数据的函数,允许单个测试仅覆盖其场景所需的内容。Fishery(2.4.0)是TypeScript的默认选择,FactoryBot(6.6.0)适用于Ruby,factory-boy(3.3.3)适用于Python;它们都与faker(v10.4.0)配合使用以生成真实的字段值。
查看获取完整的Fishery(含关联关系和确定性UUID)、FactoryBot(用户 + 产品/特征)、Factory Boy( + )以及Playwright夹具实现。每个工厂遵循的结构:
references/factories.mdout_of_stockdiscountedclass ParamsTrait- 默认值 + 覆盖 —— 生成合理默认值;测试传递其关心的单个字段的覆盖值(
Factory.define)。userFactory.build({ role: 'admin' }) - 唯一字段的序列 —— (Fishery)、
sequence(FactoryBot)、sequence(:email)(Factory Boy)——切勿硬编码ID或邮箱。factory.Sequence - 变体特征 —— 为常见状态命名(、
:admin、:inactive、out_of_stock),而非为每种组合创建一个夹具文件。discounted - 关联关系 —— 一个工厂构建另一个工厂的实例(订单构建其关联的用户),无需手动关联即可保持引用结构。
When to Use Factories vs Fixtures
工厂与夹具的使用场景对比
| Scenario | Factories | Static Fixtures |
|---|---|---|
| Entity data that tests create/modify | Yes | No |
| Reference data (countries, currencies, configs) | No | Yes |
| Data with many variations per test | Yes | No -- file explosion |
| Data with complex relationships | Yes -- associations | No -- hard to maintain |
| API response mocks | No | Yes -- JSON fixtures |
| Snapshot/golden file comparisons | No | Yes |
Decision rule: If the data has a lifecycle (created, modified, deleted during tests), use a factory. If the data is read-only reference material, use a fixture file.
| 场景 | 使用工厂 | 使用静态夹具 |
|---|---|---|
| 测试创建/修改的实体数据 | 是 | 否 |
| 参考数据(国家、货币、配置) | 否 | 是 |
| 每个测试有多种变体的数据 | 是 | 否——会导致文件爆炸 |
| 具有复杂关系的数据 | 是——支持关联 | 否——难以维护 |
| API响应模拟 | 否 | 是——JSON夹具 |
| 快照/基准文件对比 | 否 | 是 |
决策规则:如果数据有生命周期(测试期间创建、修改、删除),请使用工厂。如果数据是只读参考资料,请使用夹具文件。
Fixture Strategies
夹具策略
Three fixture shapes, all in :
references/factories.md- Static fixtures (JSON/YAML) — best for API response mocks (+
page.route), config data, and golden file comparisons.route.fulfill - Dynamic fixtures (Playwright) — creates data via API before the test and deletes it after
test.extend. The standard per-test setup/teardown.await use(...) - Fixture composition — combine factory-built data (,
userFactory.build()) inside a singleorderFactory.buildList(3)that seeds and cleans up in one step.test.extend
三种夹具形式,均在中:
references/factories.md- 静态夹具(JSON/YAML) —— 最适合API响应模拟(+
page.route)、配置数据和基准文件对比。route.fulfill - 动态夹具(Playwright) —— 在测试前通过API创建数据,并在
test.extend后删除数据。这是标准的每测试前置/后置操作。await use(...) - 夹具组合 —— 在单个中组合工厂生成的数据(
test.extend、userFactory.build()),一步完成种子数据填充和清理。orderFactory.buildList(3)
Data Anonymization
数据匿名化
When production data is needed for realistic testing, anonymize it before use.
当需要生产数据进行真实测试时,请在使用前匿名化。
PII Masking Rules
PII掩码规则
| Data Type | Anonymization Method | Example |
|---|---|---|
| Faker email with original domain pattern | | |
| Full name | Faker name | |
| Phone number | Faker phone, preserve format | |
| Address | Faker address, preserve country/region | |
| SSN/National ID | Test pattern | |
| Credit card | Test card numbers | |
| Date of birth | Shift by fixed offset | |
The anonymization pipeline -- seeded Faker for determinism, an in-memory lookup table, parent-records-first ordering, and a wrapping transaction -- is in (Anonymization with Faker.js, Referential Integrity During Anonymization). Anonymizing a user's email must also update that email everywhere it is referenced (orders, comments, audit logs); process parents first, children second, using the same lookup, all inside one transaction.
references/seeding-and-synthetic.md| 数据类型 | 匿名化方法 | 示例 |
|---|---|---|
| 邮箱 | 使用Faker生成符合原始域名模式的邮箱 | |
| 全名 | 使用Faker生成姓名 | |
| 电话号码 | 使用Faker生成电话号码,保留格式 | |
| 地址 | 使用Faker生成地址,保留国家/地区 | |
| 社保号/国家ID | 使用测试模式 | |
| 信用卡 | 使用测试卡号 | |
| 出生日期 | 偏移固定时长 | |
匿名化流水线——用于确定性的种子化Faker、内存查找表、父记录优先排序以及事务包装——位于(使用Faker.js进行匿名化、匿名化期间的引用完整性)。匿名化用户邮箱时,还必须更新所有引用该邮箱的位置(订单、评论、审计日志);先处理父记录,再处理子记录,使用相同的查找表,所有操作在一个事务内完成。
references/seeding-and-synthetic.mdGDPR Compliance Checklist
GDPR合规检查清单
- No real PII exists in any non-production environment
- Anonymization is irreversible (no lookup table mapping back to originals is stored)
- Anonymization preserves data distributions (age ranges, geographic spread) for realistic testing
- Anonymized data cannot be re-identified through combination of quasi-identifiers
- Data retention policies apply to test environments (auto-delete after N days)
- The anonymization pipeline runs automatically, not manually (eliminates human error)
- 任何非生产环境中均不存在真实PII
- 匿名化是不可逆的(不存储映射回原始数据的查找表)
- 匿名化保留数据分布(年龄范围、地理分布)以实现真实测试
- 匿名化数据无法通过准标识符的组合重新识别
- 数据保留策略适用于测试环境(N天后自动删除)
- 匿名化流水线自动运行,无需手动操作(消除人为错误)
Database Seeding
数据库种子数据
Idempotent Seed Scripts
幂等种子脚本
Seed scripts must be safe to run multiple times without duplicating data. Use upsert -- -- keyed on a stable natural key, not the primary key. A -then- "reset" is not idempotent: it breaks foreign keys and reassigns serial IDs. See (Idempotent Seed Scripts) for the full countries/currencies example and the reasoning.
INSERT ... ON CONFLICT (natural_key) DO UPDATE SET ...DELETEINSERTreferences/seeding-and-synthetic.mdINSERT ... ON CONFLICT (code) DO UPDATE种子脚本必须可安全多次运行而不会重复数据。使用upsert————基于稳定的自然键而非主键。后的「重置」方式不具有幂等性:它会破坏外键并重新分配序列ID。查看(幂等种子脚本)获取完整的国家/货币示例及原理说明。
INSERT ... ON CONFLICT (natural_key) DO UPDATE SET ...DELETEINSERTreferences/seeding-and-synthetic.mdINSERT ... ON CONFLICT (code) DO UPDATEDatabase Branching (DB-as-a-Service)
数据库分支(数据库即服务)
If your prod DB lives on Neon, Supabase, or PlanetScale, branching can give a PR its own database instead of seeding from scratch -- but the providers differ on whether the branch carries data:
- Neon Branching — copy-on-write Postgres branches in seconds, with data; ideal for ephemeral preview envs. The strongest "PR gets a real DB copy" story.
- Supabase Branching — clones schema and (optionally, from a backup) data; preview env points at the branch URL.
supabase branches create pr-123 - PlanetScale Branching — MySQL branches are schema-only by default (no data), so you still seed the branch. Note: PlanetScale removed its free Hobby tier (April 2024); MySQL now starts at ~$39/mo, Postgres ~$5/mo.
Pair with the Preview Environments pattern in .
test-environmentsAvoid: Snaplet (hosted) — shut down 31 Aug 2024; the team joined Supabase.lives on as@snaplet/seed(community-maintained, last meaningful release v0.98.0, July 2024, no feature work since). For new projects, prefer the DB-branching providers above plus factory-generated seeds.supabase-community/seed
如果你的生产数据库部署在Neon、Supabase或PlanetScale,分支功能可为PR提供独立数据库,无需从头填充种子数据——但各提供商的分支是否包含数据有所不同:
- Neon分支 —— 秒级创建写时复制的Postgres分支,包含数据;非常适合临时预览环境。是「PR获得真实数据库副本」的最佳方案。
- Supabase分支 —— 克隆架构和(可选,从备份)数据;预览环境指向分支URL。
supabase branches create pr-123 - PlanetScale分支 —— MySQL分支默认仅包含架构(无数据),因此仍需为分支填充种子数据。注意:PlanetScale已取消免费Hobby套餐(2024年4月);MySQL现在起价约39美元/月,Postgres约5美元/月。
配合中的预览环境模式使用。
test-environments注意:避免使用Snaplet(托管服务) —— 已于2024年8月31日关闭;团队加入了Supabase。作为@snaplet/seed继续存在(社区维护,最后一次有意义的版本是v0.98.0, 2024年7月,此后无功能更新)。对于新项目,优先选择上述数据库分支提供商加工厂生成的种子数据。supabase-community/seed
Per-Test vs Per-Suite Data
每测试 vs 每套件数据
| Strategy | When to Use | Pros | Cons |
|---|---|---|---|
| Per-test setup/teardown | Tests that modify data | Full isolation, parallel-safe | Slower, more setup code |
| Per-suite seed | Read-only reference data | Fast, simple | Cannot be modified by tests |
| Per-worker seed | Playwright parallel workers | Balances speed and isolation | Requires worker-scoped fixtures |
| Global seed | Environment bootstrap | Runs once, sets up baseline | Must be idempotent, shared state risk |
For the worker-scoped fixture ( with ) that powers per-worker seeding, see (Worker-Scoped Seeding).
test.extend{ scope: 'worker' }references/factories.md| 策略 | 使用场景 | 优点 | 缺点 |
|---|---|---|---|
| 每测试前置/后置操作 | 修改数据的测试 | 完全隔离,支持并行 | 速度较慢,设置代码较多 |
| 每套件种子数据 | 只读参考数据 | 快速、简单 | 测试无法修改数据 |
| 每Worker种子数据 | Playwright并行Worker | 平衡速度与隔离性 | 需要Worker作用域的夹具 |
| 全局种子数据 | 环境初始化 | 仅运行一次,建立基线 | 必须具有幂等性,存在共享状态风险 |
关于支持每Worker种子数据的Worker作用域夹具(搭配),请查看(Worker作用域种子数据填充)。
test.extend{ scope: 'worker' }references/factories.mdCleanup Strategies
清理策略
| Strategy | When to use | Speed |
|---|---|---|
| Transaction rollback | Unit/integration tests with direct DB access | Fastest |
Truncation ( | Resetting tables between suites | Medium |
| API-based cleanup | E2E tests with no direct DB access | Slowest |
Transaction rollback cannot clean up E2E tests -- the app opens its own DB connections, so a test-side transaction can't undo the app's writes; use API-based cleanup (delete in reverse creation order) there. All three implementations are in (Cleanup Strategies).
references/seeding-and-synthetic.md| 策略 | 使用场景 | 速度 |
|---|---|---|
| 事务回滚 | 直接访问数据库的单元/集成测试 | 最快 |
截断 ( | 套件间重置表 | 中等 |
| 基于API的清理 | 无直接数据库访问的端到端测试 | 最慢 |
事务回滚无法清理端到端测试——应用会打开自己的数据库连接,因此测试端的事务无法撤销应用的写入;此时需使用基于API的清理(按创建逆序删除)。三种实现均位于(清理策略)。
references/seeding-and-synthetic.mdSynthetic Data Generation
合成数据生成
Factories should make it easy to generate edge cases and boundary values without hand-writing them per test. The reusable arrays and helpers -- (empty, whitespace, very long, XSS, SQL injection, null/control chars, RTL override), , and driving a -- are in (Synthetic Data Generation).
edgeCaseStringsedgeCaseDatesboundaryValues(min, max)test.eachreferences/seeding-and-synthetic.md工厂应便于生成边缘案例和边界值,无需为每个测试手动编写。可复用的数组和助手——(空值、空白字符、超长字符串、XSS、SQL注入、空/控制字符、RTL覆盖)、和驱动——位于(合成数据生成)。
edgeCaseStringsedgeCaseDatesboundaryValues(min, max)test.eachreferences/seeding-and-synthetic.mdAnti-Patterns
反模式
Shared Mutable Test Data
共享可变测试数据
Multiple tests reading and writing the same database rows. Test A creates a user, Test B modifies it, Test C asserts on the original state and fails. Fix by having each test create its own data through factories.
多个测试读写同一数据库行。测试A创建用户,测试B修改该用户,测试C断言原始状态并失败。修复方法是让每个测试通过工厂创建自己的数据。
Production Data Without Anonymization
未匿名化的生产数据
Copying the production database to staging for "realistic testing." This violates GDPR, risks data breaches in less-secured environments, and creates compliance liability. Always anonymize before use, or generate synthetic data that matches production distributions.
将生产数据库复制到预发布环境进行「真实测试」。这违反GDPR,在安全性较低的环境中存在数据泄露风险,并产生合规责任。使用前务必匿名化,或生成匹配生产数据分布的合成数据。
Non-Deterministic Data
非确定性数据
Using or in test data creation without seeding. Tests pass on Monday and fail on Tuesday because the random name generated happens to exceed a field length limit. Use seeded Faker instances and fixed timestamps.
Math.random()Date.now()在测试数据创建中使用或而不设置种子。周一测试通过,周二测试失败,因为生成的随机姓名恰好超过字段长度限制。使用种子化Faker实例和固定时间戳。
Math.random()Date.now()No Cleanup Strategy
无清理策略
Tests that create data and never clean it up. The test database grows until it affects performance, or stale data causes false positives in other tests. Every data creation must have a corresponding cleanup.
创建数据后从不清理的测试。测试数据库不断增长直至影响性能,或陈旧数据导致其他测试出现误报。每次数据创建都必须有对应的清理操作。
Fixture File Explosion
夹具文件爆炸
Creating a separate JSON fixture file for every test variation. Instead of , , , use a factory with traits. Fixtures should be reserved for static reference data and API response mocks.
user-admin.jsonuser-inactive.jsonuser-admin-inactive.json为每个测试变体创建单独的JSON夹具文件。不要创建、、,而是使用带特征的工厂。夹具应仅用于静态参考数据和API响应模拟。
user-admin.jsonuser-inactive.jsonuser-admin-inactive.jsonOver-Specified Test Data
过度指定测试数据
Creating a complete user object with 30 fields when the test only cares about . This obscures intent and makes tests brittle. Factories with sensible defaults solve this: override only what the test cares about.
role当测试仅关心字段时,创建包含30个字段的完整用户对象。这会掩盖测试意图并使测试变得脆弱。具有合理默认值的工厂可解决此问题:仅覆盖测试关心的内容。
roleHard-Coded IDs
硬编码ID
Using in tests. This couples tests to database state and breaks when running in parallel (ID collision) or against a database with existing data. Use factory sequences or seeded UUIDs (see Core Principle 4).
userId: '1'在测试中使用。这会将测试与数据库状态耦合,在并行运行(ID冲突)或针对已有数据的数据库运行时会失败。使用工厂序列或种子化UUID(参见核心原则4)。
userId: '1'Verification
验证
Prove the data layer is deterministic, isolated, and PII-free, smallest check first:
- Seeds are idempotent — run the seed twice back-to-back and diff the row counts: returns the same number both times and exits 0. A growing count means a missing
psql -c "SELECT count(*) FROM countries" && <seed> && psql -c "SELECT count(*) FROM countries".ON CONFLICT - No shared mutable state — run the suite under parallelism and randomized order: (or
npx playwright test --workers=4) stays green. A failure that only appears here is an ordering or shared-data dependency.pytest -n auto -p randomly - Determinism holds — run the same data-generating test twice; with set, generated names/IDs/UUIDs match across runs. If they drift, an unseeded Faker call or
faker.seed(n)/Date.now()leaked in.crypto.randomUUID() - No real PII — returns nothing (real-looking emails and SSNs). Anything it finds is an anonymization gap.
grep -rE '@(gmail|outlook|yahoo)\.com|[0-9]{3}-[0-9]{2}-[0-9]{4}' tests/ fixtures/ - Cleanup returns to baseline — snapshot row counts before the suite, run it, snapshot again: the test DB is back to baseline with no orphaned records.
证明数据层具有确定性、隔离性且无PII,从最小检查开始:
- 种子数据具有幂等性 —— 连续运行两次种子脚本并对比行数:两次返回相同数字且退出码为0。行数增加意味着缺少
psql -c "SELECT count(*) FROM countries" && <seed> && psql -c "SELECT count(*) FROM countries"。ON CONFLICT - 无共享可变状态 —— 在并行和随机顺序下运行套件:(或
npx playwright test --workers=4)保持通过。仅在此场景下出现的失败是顺序或共享数据依赖问题。pytest -n auto -p randomly - 确定性保持 —— 运行两次相同的数据生成测试;设置后,生成的姓名/ID/UUID在多次运行中一致。如果出现偏差,说明存在未设置种子的Faker调用或
faker.seed(n)/Date.now()泄露。crypto.randomUUID() - 无真实PII —— 无返回结果(真实邮箱和社保号)。任何匹配结果都是匿名化漏洞。
grep -rE '@(gmail|outlook|yahoo)\.com|[0-9]{3}-[0-9]{2}-[0-9]{4}' tests/ fixtures/ - 清理后恢复基线 —— 套件运行前快照行数,运行后再次快照:测试数据库恢复到基线状态,无孤立记录。
Done When
完成标准
- Every entity type the suite creates has a factory or fixture (no inline ad-hoc object literals in tests for shared entities -- grep the test dir for hand-built fixtures and confirm none remain).
- Test data is isolated per test -- the suite passes with parallelism on (/
--workers=N) and under randomized order (pytest -n auto/--shuffle), proving no shared mutable state or ordering dependency.-p randomly - Seed scripts are idempotent -- running the seed twice in a row produces the same row count and exits 0; the CI job runs them with no manual intervention.
- No real PII used in test fixtures -- all sensitive data anonymized or synthetic (grep for production domains / real-looking SSNs returns nothing).
- Data cleanup verified -- row counts in the test DB return to baseline after the suite (no orphaned records accumulate across runs).
- 套件创建的每个实体类型都有工厂或夹具(测试目录中没有用于共享实体的内联临时对象字面量——搜索测试目录中的手动构建夹具并确认不存在)。
- 测试数据按测试隔离——套件在并行模式开启(/
--workers=N)且随机顺序(pytest -n auto/--shuffle)下通过,证明无共享可变状态或顺序依赖。-p randomly - 种子脚本具有幂等性——连续运行两次产生相同行数且退出码为0;CI作业自动运行它们,无需手动干预。
- 测试夹具中无真实PII——所有敏感数据均已匿名化或为合成数据(搜索生产域名/真实社保号无结果)。
- 数据清理已验证——套件运行后测试数据库行数恢复到基线(无孤立记录累积)。
Reference Files (in references/
)
references/参考文件(位于references/
)
references/- factories.md — Full Fishery (associations, deterministic UUIDs), FactoryBot (User + Product traits), Factory Boy (/
Params), static/dynamic/composed Playwright fixtures, and the worker-scoped seeding fixture.Trait - seeding-and-synthetic.md — Idempotent seed script, Faker.js anonymization + referential-integrity pipeline, cleanup strategies (rollback / truncate / API), and synthetic edge-case + boundary-value generators.
ON CONFLICT
- factories.md —— 完整的Fishery(关联关系、确定性UUID)、FactoryBot(用户 + 产品特征)、Factory Boy(/
Params)、静态/动态/组合Playwright夹具,以及Worker作用域种子数据填充夹具。Trait - seeding-and-synthetic.md —— 幂等种子脚本、Faker.js匿名化 + 引用完整性流水线、清理策略(回滚 / 截断 / API),以及合成边缘案例 + 边界值生成器。
ON CONFLICT
Related Skills
相关技能
- unit-testing -- Unit tests are the primary consumer of factory-generated data; this skill provides the data layer.
- api-testing -- API tests use both factories (for request bodies) and fixtures (for mocked responses).
- playwright-automation -- E2E tests need test data seeded via API or fixtures before browser interaction.
- test-reliability -- Deterministic test data eliminates a major source of test flakiness.
- test-environments -- Owns environment provisioning and database-branching strategy (Neon, Supabase, PlanetScale) for preview envs; this skill owns the data that fills them.
- database-testing -- Migration testing, data-integrity assertions, and Testcontainers for the database layer specifically -- go there to test the DB, come here to populate it.
- ci-cd-integration -- Database seeding and cleanup must be integrated into CI pipeline stages.
- unit-testing —— 单元测试是工厂生成数据的主要使用者;本技能提供数据层支持。
- api-testing —— API测试同时使用工厂(用于请求体)和夹具(用于模拟响应)。
- playwright-automation —— 端到端测试需要在浏览器交互前通过API或夹具填充测试数据。
- test-reliability —— 确定性测试数据消除了测试不稳定的主要来源之一。
- test-environments —— 负责预览环境的环境配置和数据库分支策略(Neon、Supabase、PlanetScale);本技能负责填充环境中的数据。
- database-testing —— 迁移测试、数据完整性断言以及针对数据库层的Testcontainers——测试数据库请前往该技能,填充数据请使用本技能。
- ci-cd-integration —— 数据库种子数据填充和清理必须集成到CI流水线阶段。