test-data-generator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Test Data Generator

测试数据生成器

Generate test data, fixtures, and mocks for testing.
为测试生成测试数据、夹具和模拟对象。

Quick Start

快速开始

Create a simple fixture:
javascript
const mockUser = {
  id: 1,
  name: 'Test User',
  email: 'test@example.com'
}
创建一个简单的测试夹具:
javascript
const mockUser = {
  id: 1,
  name: 'Test User',
  email: 'test@example.com'
}

Instructions

使用说明

Factory Functions

工厂函数

Create reusable data generators:
javascript
function createUser(overrides = {}) {
  return {
    id: Math.floor(Math.random() * 1000),
    name: 'Test User',
    email: 'test@example.com',
    role: 'user',
    createdAt: new Date().toISOString(),
    ...overrides
  }
}

// Usage
const admin = createUser({ role: 'admin', name: 'Admin User' })
const regularUser = createUser()
python
def create_user(**kwargs):
    defaults = {
        'id': random.randint(1, 1000),
        'name': 'Test User',
        'email': 'test@example.com',
        'role': 'user',
        'created_at': datetime.now()
    }
    return {**defaults, **kwargs}
创建可复用的数据生成器:
javascript
function createUser(overrides = {}) {
  return {
    id: Math.floor(Math.random() * 1000),
    name: 'Test User',
    email: 'test@example.com',
    role: 'user',
    createdAt: new Date().toISOString(),
    ...overrides
  }
}

// 用法
const admin = createUser({ role: 'admin', name: 'Admin User' })
const regularUser = createUser()
python
def create_user(**kwargs):
    defaults = {
        'id': random.randint(1, 1000),
        'name': 'Test User',
        'email': 'test@example.com',
        'role': 'user',
        'created_at': datetime.now()
    }
    return {**defaults, **kwargs}

Usage

用法

admin = create_user(role='admin', name='Admin User')
undefined
admin = create_user(role='admin', name='Admin User')
undefined

Builder Pattern

建造者模式

For complex objects:
javascript
class UserBuilder {
  constructor() {
    this.user = {
      id: 1,
      name: 'Test User',
      email: 'test@example.com',
      role: 'user',
      preferences: {}
    }
  }
  
  withId(id) {
    this.user.id = id
    return this
  }
  
  withName(name) {
    this.user.name = name
    return this
  }
  
  withRole(role) {
    this.user.role = role
    return this
  }
  
  withPreferences(preferences) {
    this.user.preferences = preferences
    return this
  }
  
  build() {
    return this.user
  }
}

// Usage
const user = new UserBuilder()
  .withId(123)
  .withName('John Doe')
  .withRole('admin')
  .withPreferences({ theme: 'dark' })
  .build()
用于生成复杂对象:
javascript
class UserBuilder {
  constructor() {
    this.user = {
      id: 1,
      name: 'Test User',
      email: 'test@example.com',
      role: 'user',
      preferences: {}
    }
  }
  
  withId(id) {
    this.user.id = id
    return this
  }
  
  withName(name) {
    this.user.name = name
    return this
  }
  
  withRole(role) {
    this.user.role = role
    return this
  }
  
  withPreferences(preferences) {
    this.user.preferences = preferences
    return this
  }
  
  build() {
    return this.user
  }
}

// 用法
const user = new UserBuilder()
  .withId(123)
  .withName('John Doe')
  .withRole('admin')
  .withPreferences({ theme: 'dark' })
  .build()

Test Fixtures

测试夹具

JavaScript/TypeScript:
javascript
// fixtures/users.js
export const users = {
  admin: {
    id: 1,
    name: 'Admin User',
    email: 'admin@example.com',
    role: 'admin'
  },
  regular: {
    id: 2,
    name: 'Regular User',
    email: 'user@example.com',
    role: 'user'
  }
}

// In tests
import { users } from './fixtures/users'

test('admin can delete posts', () => {
  expect(canDelete(users.admin)).toBe(true)
})
Python (pytest):
python
undefined
JavaScript/TypeScript:
javascript
// fixtures/users.js
export const users = {
  admin: {
    id: 1,
    name: 'Admin User',
    email: 'admin@example.com',
    role: 'admin'
  },
  regular: {
    id: 2,
    name: 'Regular User',
    email: 'user@example.com',
    role: 'user'
  }
}

// 在测试中
import { users } from './fixtures/users'

test('admin can delete posts', () => {
  expect(canDelete(users.admin)).toBe(true)
})
Python (pytest):
python
undefined

conftest.py

conftest.py

import pytest
@pytest.fixture def sample_user(): return { 'id': 1, 'name': 'Test User', 'email': 'test@example.com', 'role': 'user' }
@pytest.fixture def admin_user(): return { 'id': 2, 'name': 'Admin User', 'email': 'admin@example.com', 'role': 'admin' }
import pytest
@pytest.fixture def sample_user(): return { 'id': 1, 'name': 'Test User', 'email': 'test@example.com', 'role': 'user' }
@pytest.fixture def admin_user(): return { 'id': 2, 'name': 'Admin User', 'email': 'admin@example.com', 'role': 'admin' }
// 在测试中 def test_user_permissions(sample_user, admin_user): assert can_delete(admin_user) assert not can_delete(sample_user)
undefined

In tests

模拟数据

def test_user_permissions(sample_user, admin_user): assert can_delete(admin_user) assert not can_delete(sample_user)
undefined
API 响应:
javascript
const mockApiResponse = {
  data: {
    users: [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' }
    ]
  },
  status: 200,
  statusText: 'OK'
}

// 模拟 fetch
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve(mockApiResponse.data)
  })
)
数据库记录:
python
mock_db_records = [
    {'id': 1, 'name': 'Product A', 'price': 10.99},
    {'id': 2, 'name': 'Product B', 'price': 20.99},
    {'id': 3, 'name': 'Product C', 'price': 15.99}
]

@patch('app.database.query')
def test_get_products(mock_query):
    mock_query.return_value = mock_db_records
    products = get_products()
    assert len(products) == 3

Mock Data

随机数据生成

API Responses:
javascript
const mockApiResponse = {
  data: {
    users: [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' }
    ]
  },
  status: 200,
  statusText: 'OK'
}

// Mock fetch
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve(mockApiResponse.data)
  })
)
Database Records:
python
mock_db_records = [
    {'id': 1, 'name': 'Product A', 'price': 10.99},
    {'id': 2, 'name': 'Product B', 'price': 20.99},
    {'id': 3, 'name': 'Product C', 'price': 15.99}
]

@patch('app.database.query')
def test_get_products(mock_query):
    mock_query.return_value = mock_db_records
    products = get_products()
    assert len(products) == 3
使用 faker (JavaScript):
javascript
import { faker } from '@faker-js/faker'

function generateUser() {
  return {
    id: faker.string.uuid(),
    name: faker.person.fullName(),
    email: faker.internet.email(),
    avatar: faker.image.avatar(),
    address: {
      street: faker.location.streetAddress(),
      city: faker.location.city(),
      country: faker.location.country()
    }
  }
}

// 生成多个用户
const users = Array.from({ length: 10 }, generateUser)
使用 Faker (Python):
python
from faker import Faker

fake = Faker()

def generate_user():
    return {
        'id': fake.uuid4(),
        'name': fake.name(),
        'email': fake.email(),
        'phone': fake.phone_number(),
        'address': {
            'street': fake.street_address(),
            'city': fake.city(),
            'country': fake.country()
        }
    }

// 生成多个用户
users = [generate_user() for _ in range(10)]

Random Data Generation

带种子的随机数据

Using faker (JavaScript):
javascript
import { faker } from '@faker-js/faker'

function generateUser() {
  return {
    id: faker.string.uuid(),
    name: faker.person.fullName(),
    email: faker.internet.email(),
    avatar: faker.image.avatar(),
    address: {
      street: faker.location.streetAddress(),
      city: faker.location.city(),
      country: faker.location.country()
    }
  }
}

// Generate multiple users
const users = Array.from({ length: 10 }, generateUser)
Using Faker (Python):
python
from faker import Faker

fake = Faker()

def generate_user():
    return {
        'id': fake.uuid4(),
        'name': fake.name(),
        'email': fake.email(),
        'phone': fake.phone_number(),
        'address': {
            'street': fake.street_address(),
            'city': fake.city(),
            'country': fake.country()
        }
    }
用于可复现的测试:
javascript
import { faker } from '@faker-js/faker'

test('generates consistent data with seed', () => {
  faker.seed(123)
  const user1 = generateUser()
  
  faker.seed(123)
  const user2 = generateUser()
  
  expect(user1).toEqual(user2)
})
python
from faker import Faker

def test_consistent_data():
    fake = Faker()
    Faker.seed(123)
    user1 = generate_user(fake)
    
    Faker.seed(123)
    user2 = generate_user(fake)
    
    assert user1 == user2

Generate multiple users

模拟函数

users = [generate_user() for _ in range(10)]
undefined
Jest:
javascript
const mockCallback = jest.fn(x => x * 2)

test('calls callback for each item', () => {
  const items = [1, 2, 3]
  items.forEach(mockCallback)
  
  expect(mockCallback).toHaveBeenCalledTimes(3)
  expect(mockCallback).toHaveBeenCalledWith(1)
  expect(mockCallback).toHaveBeenCalledWith(2)
  expect(mockCallback).toHaveBeenCalledWith(3)
})
Python (unittest.mock):
python
from unittest.mock import Mock

def test_callback():
    mock_callback = Mock(return_value=42)
    
    result = process_data([1, 2, 3], mock_callback)
    
    assert mock_callback.call_count == 3
    mock_callback.assert_called_with(3)

Seeded Random Data

基于时间的数据

For reproducible tests:
javascript
import { faker } from '@faker-js/faker'

test('generates consistent data with seed', () => {
  faker.seed(123)
  const user1 = generateUser()
  
  faker.seed(123)
  const user2 = generateUser()
  
  expect(user1).toEqual(user2)
})
python
from faker import Faker

def test_consistent_data():
    fake = Faker()
    Faker.seed(123)
    user1 = generate_user(fake)
    
    Faker.seed(123)
    user2 = generate_user(fake)
    
    assert user1 == user2
冻结时间:
javascript
import { jest } from '@jest/globals'

test('creates timestamp', () => {
  const mockDate = new Date('2024-01-01T00:00:00Z')
  jest.useFakeTimers()
  jest.setSystemTime(mockDate)
  
  const record = createRecord()
  expect(record.createdAt).toBe('2024-01-01T00:00:00.000Z')
  
  jest.useRealTimers()
})
python
from freezegun import freeze_time

@freeze_time("2024-01-01 00:00:00")
def test_timestamp():
    record = create_record()
    assert record['created_at'] == datetime(2024, 1, 1, 0, 0, 0)

Mock Functions

常见模式

Jest:
javascript
const mockCallback = jest.fn(x => x * 2)

test('calls callback for each item', () => {
  const items = [1, 2, 3]
  items.forEach(mockCallback)
  
  expect(mockCallback).toHaveBeenCalledTimes(3)
  expect(mockCallback).toHaveBeenCalledWith(1)
  expect(mockCallback).toHaveBeenCalledWith(2)
  expect(mockCallback).toHaveBeenCalledWith(3)
})
Python (unittest.mock):
python
from unittest.mock import Mock

def test_callback():
    mock_callback = Mock(return_value=42)
    
    result = process_data([1, 2, 3], mock_callback)
    
    assert mock_callback.call_count == 3
    mock_callback.assert_called_with(3)
模式:测试用例数组:
javascript
const testCases = [
  { input: 'hello', expected: 'HELLO' },
  { input: 'world', expected: 'WORLD' },
  { input: '', expected: '' }
]

testCases.forEach(({ input, expected }) => {
  test(`converts "${input}" to "${expected}"`, () => {
    expect(toUpperCase(input)).toBe(expected)
  })
})
模式:共享设置:
javascript
describe('UserService', () => {
  let service
  let mockDb
  
  beforeEach(() => {
    mockDb = {
      query: jest.fn(),
      insert: jest.fn()
    }
    service = new UserService(mockDb)
  })
  
  test('fetches users', async () => {
    mockDb.query.mockResolvedValue([{ id: 1 }])
    const users = await service.getUsers()
    expect(users).toHaveLength(1)
  })
})
模式:测试数据文件:
javascript
// testData/users.json
[
  {
    "id": 1,
    "name": "Alice",
    "email": "alice@example.com"
  },
  {
    "id": 2,
    "name": "Bob",
    "email": "bob@example.com"
  }
]

// 在测试中
import users from './testData/users.json'

test('processes user data', () => {
  const result = processUsers(users)
  expect(result).toHaveLength(2)
})

Time-based Data

进阶内容

Freeze time:
javascript
import { jest } from '@jest/globals'

test('creates timestamp', () => {
  const mockDate = new Date('2024-01-01T00:00:00Z')
  jest.useFakeTimers()
  jest.setSystemTime(mockDate)
  
  const record = createRecord()
  expect(record.createdAt).toBe('2024-01-01T00:00:00.000Z')
  
  jest.useRealTimers()
})
python
from freezegun import freeze_time

@freeze_time("2024-01-01 00:00:00")
def test_timestamp():
    record = create_record()
    assert record['created_at'] == datetime(2024, 1, 1, 0, 0, 0)
针对复杂场景:
  • 使用工厂类库(factory-bot、fishery、rosie)
  • 生成 GraphQL 模拟数据
  • 创建数据库种子数据
  • 构建测试数据流水线

Common Patterns

Pattern: Array of test cases:
javascript
const testCases = [
  { input: 'hello', expected: 'HELLO' },
  { input: 'world', expected: 'WORLD' },
  { input: '', expected: '' }
]

testCases.forEach(({ input, expected }) => {
  test(`converts "${input}" to "${expected}"`, () => {
    expect(toUpperCase(input)).toBe(expected)
  })
})
Pattern: Shared setup:
javascript
describe('UserService', () => {
  let service
  let mockDb
  
  beforeEach(() => {
    mockDb = {
      query: jest.fn(),
      insert: jest.fn()
    }
    service = new UserService(mockDb)
  })
  
  test('fetches users', async () => {
    mockDb.query.mockResolvedValue([{ id: 1 }])
    const users = await service.getUsers()
    expect(users).toHaveLength(1)
  })
})
Pattern: Test data files:
javascript
// testData/users.json
[
  {
    "id": 1,
    "name": "Alice",
    "email": "alice@example.com"
  },
  {
    "id": 2,
    "name": "Bob",
    "email": "bob@example.com"
  }
]

// In tests
import users from './testData/users.json'

test('processes user data', () => {
  const result = processUsers(users)
  expect(result).toHaveLength(2)
})

Advanced

For complex scenarios:
  • Use factory libraries (factory-bot, fishery, rosie)
  • Generate GraphQL mock data
  • Create database seeders
  • Build test data pipelines