Django Filter Benchmark
saleor/saleor
Benchmarks Django ORM filters in Saleor by generating bulk data, extracting the SQL and running EXPLAIN ANALYZE to check index usage.
Schema-driven test data factory generator. An agent skill from LeoYeAI/openclaw-master-skills.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-test-data-factory --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/phy-test-data-factory .claude/skills/phy-test-data-factory && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "phy-test-data-factory" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factory into .claude/skills/phy-test-data-factory/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-test-data-factory", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factoryType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-test-data-factory --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/phy-test-data-factory .agents/skills/phy-test-data-factory && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "phy-test-data-factory" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factory into .agents/skills/phy-test-data-factory/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-test-data-factory", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-test-data-factory --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/phy-test-data-factory .cursor/skills/phy-test-data-factory && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "phy-test-data-factory" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factory into .cursor/skills/phy-test-data-factory/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-test-data-factory", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LeoYeAI/openclaw-master-skills.git --path skills/phy-test-data-factory--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-test-data-factory --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/phy-test-data-factory .gemini/skills/phy-test-data-factory && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "phy-test-data-factory" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factory into .gemini/skills/phy-test-data-factory/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-test-data-factory", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LeoYeAI/openclaw-master-skills phy-test-data-factoryInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/phy-test-data-factory .github/skills/phy-test-data-factory && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "phy-test-data-factory" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factory into .github/skills/phy-test-data-factory/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-test-data-factory", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-test-data-factory --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/phy-test-data-factory .opencode/skills/phy-test-data-factory && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "phy-test-data-factory" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-test-data-factory into .opencode/skills/phy-test-data-factory/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-test-data-factory", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
phy-test-data-factorySchema-driven test data factory generator. An agent skill from LeoYeAI/openclaw-master-skills.
Phy Test Data Factory is an agent skill from LeoYeAI/openclaw-master-skills. Schema-driven test data factory generator. Reads your database schema or model definitions — Prisma schema, SQLAlchemy models, Django models, TypeORM entities, Zod schemas, Pydantic models, or raw SQL DDL — and generates ready-to-use factory functions with realistic fake data. Outputs TypeScript factory files using Faker.js, Python conftest.py using factoryboy + Faker, or raw SQL INSERT seed scripts. Respects foreign key relationships (seeds parents before children), handles enums, nullable fields, unique…
Its SKILL.md is about 5.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `_meta.json`).
It sits in Testing & QA, covering Test data and fixtures. It works with SQL, Prisma, Python and TypeScript. The repository describes itself as: 🧠 Curated collection of 1209+ best OpenClaw skills — weekly updated by MyClaw.ai. The licence is Apache-2.0.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e5199b5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pipnpmnodepython3From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use pip and npm, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Phy Test Data Factory loads about 5.5k tokens when it runs. Until then it costs about 208 tokens; SKILL.md has 186 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LeoYeAI/openclaw-master-skills at commit e5199b5, republished under its Apache-2.0 licence (© LeoYeAI). 186 words, ~5,538 tokens.
.claude/skills/phy-test-data-factory/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Writing test setup is slower than writing the test itself. You have a User model with 12 fields, a Post model that requires a User, and an Order model that requires both. Every test file re-invents the same createTestUser() boilerplate — with slightly different hardcoded values that don't cover edge cases.
Paste your schema and get a complete factory module: realistic Faker-powered defaults for every field, relationship-aware ordering, and one-line overrides for specific test scenarios.
Reads any schema format. Outputs TypeScript, Python, or SQL. Zero external APIs.
# Option 1: Prisma schema
/test-data-factory schema.prisma
/test-data-factory prisma/schema.prisma
# Option 2: SQLAlchemy / Django models file
/test-data-factory models.py
/test-data-factory app/models.py
# Option 3: TypeORM entities directory
/test-data-factory src/entities/
# Option 4: Zod schemas file
/test-data-factory src/schemas/user.schema.ts
# Option 5: Raw SQL DDL
/test-data-factory --sql migrations/001_initial.sql
# Option 6: Output format override
/test-data-factory schema.prisma --output typescript
/test-data-factory models.py --output python
/test-data-factory schema.prisma --output sql
# Option 7: Include edge-case variants
/test-data-factory schema.prisma --edge-cases
# Option 8: Specific count
/test-data-factory schema.prisma --count 50import re
from dataclasses import dataclass, field
from typing import Any
@dataclass
class PrismaField:
name: str
type: str
is_optional: bool = False
is_list: bool = False
is_id: bool = False
is_unique: bool = False
is_auto: bool = False
default: Any = None
relation: str | None = None
enum_values: list[str] = field(default_factory=list)
def parse_prisma_schema(schema_text: str) -> dict:
"""Parse Prisma schema into model definitions."""
models = {}
enums = {}
# Parse enums first
for enum_match in re.finditer(r'enum\s+(\w+)\s*\{([^}]+)\}', schema_text, re.DOTALL):
enum_name = enum_match.group(1)
values = [v.strip() for v in enum_match.group(2).split('\n')
if v.strip() and not v.strip().startswith('//')]
enums[enum_name] = values
# Parse models
for model_match in re.finditer(r'model\s+(\w+)\s*\{([^}]+)\}', schema_text, re.DOTALL):
model_name = model_match.group(1)
body = model_match.group(2)
fields = []
for line in body.split('\n'):
line = line.strip()
if not line or line.startswith('//') or line.startswith('@@'):
continue
# Parse field: name type? modifiers
parts = line.split()
if len(parts) < 2:
continue
fname = parts[0]
ftype_raw = parts[1]
is_optional = ftype_raw.endswith('?')
is_list = ftype_raw.endswith('[]')
ftype = ftype_raw.rstrip('?').rstrip('[]')
is_id = '@id' in line
is_unique = '@unique' in line
is_auto = '@default(autoincrement())' in line or '@default(auto())' in line or '@default(uuid())' in line or '@default(cuid())' in line
is_relation = '@relation' in line
default_match = re.search(r'@default\((.+?)\)', line)
default_val = default_match.group(1) if default_match else None
fields.append(PrismaField(
name=fname,
type=ftype,
is_optional=is_optional,
is_list=is_list,
is_id=is_id,
is_unique=is_unique,
is_auto=is_auto,
default=default_val,
relation=ftype if is_relation and ftype[0].isupper() else None,
enum_values=enums.get(ftype, []),
))
models[model_name] = fields
return {'models': models, 'enums': enums}def parse_sql_ddl(sql_text: str) -> dict:
"""Parse CREATE TABLE statements."""
models = {}
for table_match in re.finditer(
r'CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"]?(\w+)[`"]?\s*\(([^;]+)\)',
sql_text, re.IGNORECASE | re.DOTALL
):
table_name = table_match.group(1)
columns_text = table_match.group(2)
fields = []
for col_line in columns_text.split(','):
col_line = col_line.strip()
if not col_line or col_line.upper().startswith(('PRIMARY', 'FOREIGN', 'UNIQUE', 'INDEX', 'KEY', 'CONSTRAINT')):
continue
col_match = re.match(r'[`"]?(\w+)[`"]?\s+(\w+)(\(\d+\))?(.*)$', col_line, re.IGNORECASE)
if not col_match:
continue
fname = col_match.group(1)
ftype = col_match.group(2).upper()
rest = col_match.group(4).upper()
is_nullable = 'NOT NULL' not in rest
is_auto = 'AUTO_INCREMENT' in rest or 'SERIAL' in ftype
is_unique = 'UNIQUE' in rest
fields.append(PrismaField(
name=fname,
type=ftype,
is_optional=is_nullable,
is_auto=is_auto,
is_unique=is_unique,
))
models[table_name] = fields
return {'models': models, 'enums': {}}# Prisma/TypeScript type → Faker.js function
FAKER_JS_MAP = {
# Primitives
'String': 'faker.lorem.words(3)',
'Int': 'faker.number.int({ min: 1, max: 10000 })',
'Float': 'faker.number.float({ min: 0, max: 1000, fractionDigits: 2 })',
'Boolean': 'faker.datatype.boolean()',
'DateTime': 'faker.date.recent({ days: 30 })',
'BigInt': 'BigInt(faker.number.int({ min: 1, max: 1000000 }))',
'Json': '{}',
'Bytes': 'Buffer.from(faker.string.alphanumeric(16))',
# Semantic overrides (based on field name)
'email': 'faker.internet.email()',
'name': 'faker.person.fullName()',
'firstName': 'faker.person.firstName()',
'lastName': 'faker.person.lastName()',
'username': 'faker.internet.username()',
'password': 'faker.internet.password({ length: 12 })',
'phone': 'faker.phone.number()',
'address': 'faker.location.streetAddress()',
'city': 'faker.location.city()',
'country': 'faker.location.country()',
'zipCode': 'faker.location.zipCode()',
'url': 'faker.internet.url()',
'imageUrl': 'faker.image.url()',
'avatar': 'faker.image.avatar()',
'bio': 'faker.lorem.paragraph()',
'description': 'faker.lorem.sentences(2)',
'title': 'faker.lorem.sentence()',
'slug': 'faker.helpers.slugify(faker.lorem.words(3))',
'color': 'faker.color.human()',
'uuid': 'faker.string.uuid()',
'ip': 'faker.internet.ip()',
'createdAt': 'faker.date.past({ years: 1 })',
'updatedAt': 'new Date()',
'deletedAt': 'null',
'publishedAt': 'faker.date.recent({ days: 90 })',
'price': 'faker.number.float({ min: 0.99, max: 999.99, fractionDigits: 2 })',
'amount': 'faker.number.int({ min: 1, max: 10000 })',
'quantity': 'faker.number.int({ min: 1, max: 100 })',
'score': 'faker.number.float({ min: 0, max: 5, fractionDigits: 1 })',
'rating': 'faker.number.int({ min: 1, max: 5 })',
'status': None, # replaced by enum values
'role': None, # replaced by enum values
'type': None, # replaced by enum values
}
# Same mapping for Python Faker
FAKER_PY_MAP = {
'String': "fake.sentence(nb_words=3)",
'str': "fake.sentence(nb_words=3)",
'Int': "fake.random_int(min=1, max=10000)",
'int': "fake.random_int(min=1, max=10000)",
'Float': "round(random.uniform(0, 1000), 2)",
'float': "round(random.uniform(0, 1000), 2)",
'bool': "fake.boolean()",
'datetime': "fake.date_time_this_year()",
'email': "fake.email()",
'name': "fake.name()",
'phone': "fake.phone_number()",
'url': "fake.url()",
'uuid': "str(uuid.uuid4())",
'price': "round(random.uniform(0.99, 999.99), 2)",
}
def get_faker_value(field_name: str, field_type: str, enum_values: list, lang: str = 'ts') -> str:
"""Get the Faker expression for a field."""
mapper = FAKER_JS_MAP if lang == 'ts' else FAKER_PY_MAP
prefix = 'faker.' if lang == 'ts' else 'fake.'
# Enum field: pick from enum values
if enum_values:
if lang == 'ts':
return f'faker.helpers.arrayElement([{", ".join(repr(v) for v in enum_values)}])'
else:
return f'random.choice([{", ".join(repr(v) for v in enum_values)}])'
# Check semantic field name first
for semantic_key, expr in mapper.items():
if field_name.lower().endswith(semantic_key.lower()) or field_name.lower() == semantic_key.lower():
if expr:
return expr
# Fall back to type mapping
return mapper.get(field_type, f'"TODO: {field_type}"')Topologically sort models so parents are created before children:
def topological_sort(models: dict) -> list[str]:
"""Return model names in dependency order (parents first)."""
from collections import defaultdict, deque
graph = defaultdict(list)
in_degree = {name: 0 for name in models}
for model_name, fields in models.items():
for field in fields:
if field.relation and field.relation in models and not field.is_optional:
# model_name depends on field.relation
graph[field.relation].append(model_name)
in_degree[model_name] += 1
queue = deque([m for m, d in in_degree.items() if d == 0])
order = []
while queue:
model = queue.popleft()
order.append(model)
for dependent in graph[model]:
in_degree[dependent] -= 1
if in_degree[dependent] == 0:
queue.append(dependent)
# Append any remaining (circular deps)
for m in models:
if m not in order:
order.append(m)
return order// Generated by phy-test-data-factory
// Install: npm install -D @faker-js/faker
import { faker } from '@faker-js/faker';
import { PrismaClient, UserRole, PostStatus } from '@prisma/client';
const prisma = new PrismaClient();
// ─── User Factory ────────────────────────────────────────────────────────────
export interface CreateUserOptions {
id?: string;
email?: string;
name?: string;
role?: UserRole;
createdAt?: Date;
}
export function buildUser(overrides: CreateUserOptions = {}) {
return {
id: faker.string.uuid(),
email: faker.internet.email(),
name: faker.person.fullName(),
username: faker.internet.username(),
password: faker.internet.password({ length: 12 }),
bio: faker.lorem.paragraph(),
avatarUrl: faker.image.avatar(),
role: faker.helpers.arrayElement(['USER', 'ADMIN', 'MODERATOR'] as UserRole[]),
isActive: true,
createdAt: faker.date.past({ years: 1 }),
updatedAt: new Date(),
...overrides,
};
}
export async function createUser(overrides: CreateUserOptions = {}) {
return prisma.user.create({ data: buildUser(overrides) });
}
// ─── Post Factory ─────────────────────────────────────────────────────────────
export interface CreatePostOptions {
id?: string;
title?: string;
content?: string;
authorId?: string; // Will create a User if not provided
status?: PostStatus;
}
export async function createPost(overrides: CreatePostOptions = {}) {
const authorId = overrides.authorId ?? (await createUser()).id;
return prisma.post.create({
data: {
id: faker.string.uuid(),
title: faker.lorem.sentence(),
slug: faker.helpers.slugify(faker.lorem.words(4)),
content: faker.lorem.paragraphs(3),
excerpt: faker.lorem.sentences(2),
status: faker.helpers.arrayElement(['DRAFT', 'PUBLISHED', 'ARCHIVED'] as PostStatus[]),
publishedAt: faker.date.recent({ days: 90 }),
authorId,
createdAt: faker.date.past({ years: 1 }),
updatedAt: new Date(),
...overrides,
},
});
}
// ─── Order Factory ────────────────────────────────────────────────────────────
export interface CreateOrderOptions {
id?: string;
userId?: string;
total?: number;
status?: 'PENDING' | 'CONFIRMED' | 'SHIPPED' | 'DELIVERED' | 'CANCELLED';
}
export async function createOrder(overrides: CreateOrderOptions = {}) {
const userId = overrides.userId ?? (await createUser()).id;
return prisma.order.create({
data: {
id: faker.string.uuid(),
userId,
total: faker.number.float({ min: 9.99, max: 999.99, fractionDigits: 2 }),
status: faker.helpers.arrayElement(['PENDING', 'CONFIRMED', 'SHIPPED', 'DELIVERED', 'CANCELLED']),
address: faker.location.streetAddress(),
city: faker.location.city(),
country: faker.location.country(),
createdAt: faker.date.past({ years: 1 }),
updatedAt: new Date(),
...overrides,
},
});
}
// ─── Bulk creation helpers ────────────────────────────────────────────────────
export async function createUsers(count: number, overrides: CreateUserOptions = {}) {
return Promise.all(Array.from({ length: count }, () => createUser(overrides)));
}
export async function createPosts(count: number, overrides: CreatePostOptions = {}) {
return Promise.all(Array.from({ length: count }, () => createPost(overrides)));
}
// ─── Teardown ─────────────────────────────────────────────────────────────────
export async function clearTestData() {
// Delete in reverse dependency order (children before parents)
await prisma.order.deleteMany();
await prisma.post.deleteMany();
await prisma.user.deleteMany();
}# Generated by phy-test-data-factory
# Install: pip install factory_boy faker
import uuid, random
from datetime import datetime
import factory
from factory import Faker, SubFactory, LazyFunction
from factory.django import DjangoModelFactory # or SQLAlchemyModelFactory
from myapp.models import User, Post, Order, UserRole, PostStatus
class UserFactory(DjangoModelFactory):
class Meta:
model = User
id = LazyFunction(lambda: str(uuid.uuid4()))
email = Faker('email')
name = Faker('name')
username = Faker('user_name')
bio = Faker('paragraph')
avatar_url = Faker('image_url')
role = factory.Iterator([r.value for r in UserRole])
is_active = True
created_at = Faker('date_time_this_year')
updated_at = LazyFunction(datetime.utcnow)
class PostFactory(DjangoModelFactory):
class Meta:
model = Post
id = LazyFunction(lambda: str(uuid.uuid4()))
title = Faker('sentence', nb_words=6)
slug = factory.LazyAttribute(lambda o: o.title.lower().replace(' ', '-').replace(',', ''))
content = Faker('paragraphs', nb=3, as_list=False)
excerpt = Faker('sentences', nb=2, as_list=False)
status = factory.Iterator([s.value for s in PostStatus])
author = SubFactory(UserFactory)
published_at = Faker('date_time_this_month')
created_at = Faker('date_time_this_year')
updated_at = LazyFunction(datetime.utcnow)
class OrderFactory(DjangoModelFactory):
class Meta:
model = Order
id = LazyFunction(lambda: str(uuid.uuid4()))
user = SubFactory(UserFactory)
total = LazyFunction(lambda: round(random.uniform(9.99, 999.99), 2))
status = factory.Iterator(['PENDING', 'CONFIRMED', 'SHIPPED', 'DELIVERED'])
address = Faker('street_address')
city = Faker('city')
country = Faker('country')
created_at = Faker('date_time_this_year')
updated_at = LazyFunction(datetime.utcnow)
# Usage in pytest conftest.py:
#
# @pytest.fixture
# def user(db):
# return UserFactory()
#
# @pytest.fixture
# def post_with_author(db):
# return PostFactory() # auto-creates a User via SubFactory
#
# @pytest.fixture
# def many_orders(db):
# return OrderFactory.create_batch(20)-- Generated by phy-test-data-factory
-- Seed data for: users, posts, orders
-- Insert in dependency order (parents first)
-- Users (10 rows)
INSERT INTO users (id, email, name, role, is_active, created_at) VALUES
('usr_001', 'alice@example.com', 'Alice Johnson', 'USER', true, '2026-01-15 09:30:00'),
('usr_002', 'bob@example.com', 'Bob Smith', 'ADMIN', true, '2026-01-20 14:00:00'),
('usr_003', 'carol@example.com', 'Carol Williams', 'USER', true, '2026-02-01 11:00:00'),
-- ... (7 more rows)
-- Posts (20 rows, requires users above)
INSERT INTO posts (id, title, slug, status, author_id, created_at) VALUES
('post_001', 'Getting Started with Testing', 'getting-started-testing', 'PUBLISHED', 'usr_001', '2026-02-10 10:00:00'),
('post_002', 'Advanced Patterns in TypeScript', 'advanced-typescript', 'DRAFT', 'usr_002', '2026-02-15 11:30:00'),
-- ... (18 more rows)## Test Data Factory — Generated
Schema: prisma/schema.prisma | Models: User, Post, Comment, Order, Tag
Output: src/test/factories/index.ts
---
### Models Processed (dependency order)
| Model | Fields | Relationships | Factory Type |
|-------|--------|--------------|-------------|
| User | 14 fields | — (root) | createUser() |
| Tag | 4 fields | — (root) | createTag() |
| Post | 11 fields | → User (author) | createPost() |
| Comment | 8 fields | → User, → Post | createComment() |
| Order | 9 fields | → User | createOrder() |
---
### Generated Files
- `src/test/factories/index.ts` — all factory functions
- `src/test/factories/builders.ts` — plain object builders (no DB write)
- `src/test/setup.ts` — jest/vitest beforeAll/afterAll with clearTestData()
---
### Auto-Detected Semantic Mappings
| Field | Detected As | Faker Function Used |
|-------|------------|---------------------|
| `email` | Email address | `faker.internet.email()` |
| `avatarUrl` | Image URL | `faker.image.avatar()` |
| `publishedAt` | Recent date | `faker.date.recent({ days: 90 })` |
| `role` | Enum (USER/ADMIN/MOD) | `faker.helpers.arrayElement([...])` |
| `slug` | URL slug | `faker.helpers.slugify(faker.lorem.words(3))` |
| `price` | Currency amount | `faker.number.float({ fractionDigits: 2 })` |
---
### Quick Usage
```typescript
import { createUser, createPost, createOrder, clearTestData } from './factories';
// Single record
const user = await createUser();
// With overrides
const adminUser = await createUser({ role: 'ADMIN', email: 'admin@test.com' });
// Relationships handled automatically
const post = await createPost(); // creates a User internally
const post2 = await createPost({ authorId: user.id }); // reuse existing User
// Batch creation
const orders = await createOrders(50);
// Teardown
afterAll(clearTestData);
---
## Edge Case Variants
With `--edge-cases`, generate additional factory variants for boundary testing:
```typescript
// Generated edge-case builders for User model:
export const edgeCaseUsers = {
withMinLengthFields: () => buildUser({
email: 'a@b.co',
name: 'A',
bio: '',
}),
withMaxLengthFields: () => buildUser({
email: 'a'.repeat(243) + '@b.co', // 255 chars total
name: 'A'.repeat(255),
bio: 'x'.repeat(5000),
}),
withNullableFieldsNull: () => buildUser({
bio: null,
avatarUrl: null,
phoneNumber: null,
}),
withSpecialCharacters: () => buildUser({
name: "O'Brien-Smith, Jr.",
bio: '<script>alert("xss")</script>', // for XSS testing
}),
withUnicodeContent: () => buildUser({
name: '张伟',
bio: '日本語テキスト with emoji 🎉',
}),
withPastDates: () => buildUser({
createdAt: new Date('2000-01-01'),
}),
withFutureDates: () => buildUser({
createdAt: new Date('2099-12-31'),
}),
};# TypeScript / JavaScript
npm install -D @faker-js/faker
# Python (Django)
pip install factory_boy faker
# Python (SQLAlchemy)
pip install factory_boy faker sqlalchemy
# Verify installation
node -e "const { faker } = require('@faker-js/faker'); console.log(faker.person.fullName())"
python3 -c "import factory; print('factory_boy ready')"© LeoYeAI, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in skills/phy-test-data-factory of LeoYeAI/openclaw-master-skills.
Open the folder on GitHubat commit e5199b5
Phy Test Data Factory next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Phy Test Data Factory this skillLeoYeAI/openclaw-master-skills | 2.2k | — | ~5.5k | Automated safety check: Pass | Apache-2.0 | |
| Django Filter Benchmarksaleor/saleor | 23k | — | ~2.3k | Automated safety check: Pass | BSD-3-Clause | |
| Fastapiericrisco/rsc-harness | 174 | — | ~5k | Automated safety check: Notes | MIT | |
| Pytestmathiasertl/django-ca | 158 | — | ~924 | Automated safety check: Pass | GPL-3.0 | |
| Dummy Dataset Generatorphuryn/pm-skills | 27k | — | ~983 | Automated safety check: Pass | MIT | |
| Dummy Datasetkillvxk/pm-skills-zh | 167 | — | ~595 | Automated safety check: Pass | MIT |
saleor/saleor
Benchmarks Django ORM filters in Saleor by generating bulk data, extracting the SQL and running EXPLAIN ANALYZE to check index usage.
ericrisco/rsc-harness
A skill your agent uses when building, reviewing, testing, securing or shipping a FastAPI / async Python service — routers, Pydantic v2 schemas, dependency injection, async SQLAlchemy 2.0…
mathiasertl/django-ca
Instructions for running, writing, and maintaining tests in this project
phuryn/pm-skills
Generates realistic test datasets with custom columns, row counts and business constraints, output as CSV, JSON, SQL inserts or a runnable Python script.
killvxk/pm-skills-zh
生成用于测试的逼真虚拟数据集,支持自定义列、约束条件及输出格式(CSV、JSON、SQL、Python 脚本)。适用于创建测试数据、构建模拟数据集,或为开发和演示生成示例数据。
ancoleman/ai-design-components
Strategic guidance for choosing and implementing testing approaches across the test pyramid.
LeoYeAI/openclaw-master-skills
Manages pipelines on a DevOps quality and efficiency platform through its OpenAPI: list workspaces and templates, create, update, run and cancel pipelines, and read run records.
LeoYeAI/openclaw-master-skills
Patches OpenClaw's Feishu extension so an edited document triggers an isolated agent session that reads the doc and replies inline, turning it into a live chat space.
LeoYeAI/openclaw-master-skills
Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation.
LeoYeAI/openclaw-master-skills
Runs a brand's AI-search visibility work end to end: diagnosing how AI platforms represent it, repositioning it, producing AI-optimized content and monitoring ongoing mentions.
LeoYeAI/openclaw-master-skills
Installs and authenticates the gws CLI, then automates Gmail, Drive, Sheets, Calendar, Docs, Chat and Tasks with ready-made recipes, persona bundles and security audits.
LeoYeAI/openclaw-master-skills
Runs four advisor roles, a fitness coach, nutritionist, data analyst and TCM practitioner, to build a health profile and track workouts, diet and wellness over time.
Categories
Schema-driven test data factory generator. An agent skill from LeoYeAI/openclaw-master-skills. Phy Test Data Factory is an agent skill from LeoYeAI/openclaw-master-skills. Schema-driven test data factory generator.
Phy Test Data Factory fits situations like: generate test data; factory functions; fake data from schema; /test-data-factory.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a claude-code`. Or copy the skill folder (skills/phy-test-data-factory in LeoYeAI/openclaw-master-skills) into .claude/skills/phy-test-data-factory in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a codex`. Or copy the skill folder (skills/phy-test-data-factory in LeoYeAI/openclaw-master-skills) into .agents/skills/phy-test-data-factory in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LeoYeAI/openclaw-master-skills --skill phy-test-data-factory -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/phy-test-data-factory, .gemini/skills/phy-test-data-factory, .github/skills/phy-test-data-factory and .opencode/skills/phy-test-data-factory in your project.
Going by SKILL.md and its folder, Phy Test Data Factory needs the command-line tools its instructions call (pip, npm, node and python3). Our summary lists: Python 3; Node.js.
SKILL.md contains no URLs. Its commands use pip and npm, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Phy Test Data Factory is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.5k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Phy Test Data Factory: Django Filter Benchmark (saleor/saleor, 23k stars), Fastapi (ericrisco/rsc-harness, 174 stars), Pytest (mathiasertl/django-ca, 158 stars) and Dummy Dataset Generator (phuryn/pm-skills, 27k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LeoYeAI (a GitHub user) maintains it in LeoYeAI/openclaw-master-skills, which has 2,160 GitHub stars. The repository holds 1,235 skills in this directory. The repository was last updated on July 20, 2026.
Source: LeoYeAI/openclaw-master-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.