关于 test-automation
test-automation 是将 SDD 文档转换为可执行测试并跟踪覆盖率的测试技能,面向需要把实现与需求、场景及契约对应起来的团队。它支持从 BDD、需求和契约等生成多类测试,并提供追溯与覆盖差距分析。
主要功能
- 01从 BDD 场景生成测试
- 02从需求生成单元测试
- 03生成集成与契约测试
- 04分析代码及需求覆盖率
- 05生成测试数据与覆盖报告
适用场景
- 01将 Given-When-Then 场景转为测试套件
- 02按需求文档创建单元测试
- 03验证 API 契约并检测破坏性变更
- 04定位未覆盖的需求、场景或代码路径
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ vladm3105/ aidoc-flow-framework --skill test-automation安装后在 Claude Code 中输入/test-automation确认已加载。
详细介绍
test-automation
描述:自动生成测试、执行 BDD、分析覆盖率和进行契约测试
类别:质量保证与测试
复杂度:高(多框架集成 + 覆盖率分析)
用途
将 SDD 工件(BDD 场景、需求、契约)转换为可执行的测试套件,并全面跟踪覆盖率。确保代码实现符合规范和契约。
功能
1. BDD 场景生成
- 解析 BDD 文档(Given-When-Then 格式)
- 生成 pytest-bdd 测试文件
- 将场景映射到测试函数
- 处理带有示例的场景大纲
- 根据 Given 子句生成测试固件
2. 单元测试生成
- 根据需求(REQ 文档)生成单元测试
- 根据 SPEC 文档创建测试模板
- 为依赖项生成模拟对象
- 生成参数化测试
- 根据需求识别边缘情况
3. 集成测试生成
- 根据 CTR 契约生成 API 集成测试
- 根据数据规范生成数据库集成测试
- 服务交互测试
- 根据 IMPL 文档生成端到端工作流测试
4. 契约测试
- 根据 CTR YAML 生成消费者驱动的契约测试
- 架构验证测试
- API 契约合规性验证
- 检测破坏性变更
- 根据契约生成模拟服务
5. 测试覆盖率分析
- 行覆盖率、分支覆盖率、路径覆盖率
- 需求覆盖率映射(REQ → 测试)
- 场景覆盖率跟踪(BDD → 测试)
- 契约覆盖率验证(CTR → 测试)
- 识别覆盖率缺口
6. 性能测试生成
- 根据性能需求生成负载测试场景
- 压力测试配置
- 生成基准测试
- SLA 验证测试
7. 测试数据生成
- 根据规范生成逼真的测试数据
- 生成边缘情况数据
- 边界值分析
- 为负向测试生成无效输入
测试生成工作流
graph TD
A[SDD Artifacts] --> B{Artifact Type}
B -->|BDD| C[Generate BDD Tests]
B -->|REQ| D[Generate Unit Tests]
B -->|CTR| E[Generate Contract Tests]
B -->|SPEC| F[Generate Integration Tests]
C --> G[pytest-bdd Test Suite]
D --> H[pytest Unit Test Suite]
E --> I[Contract Test Suite]
F --> J[Integration Test Suite]
G --> K[Execute Tests]
H --> K
I --> K
J --> K
K --> L[Coverage Analysis]
L --> M{Coverage Goals Met?}
M -->|No| N[Identify Gaps]
M -->|Yes| O[Generate Report]
N --> P[Generate Additional Tests]
P --> K
O --> Q[Update Traceability Matrix]
使用说明
根据 BDD 场景生成测试
# Input: BDD/authentication_scenarios.md
# Output: tests/bdd/test_authentication.py
test-automation generate-bdd \
--input BDD/authentication_scenarios.md \
--output tests/bdd/test_authentication.py \
--framework pytest-bdd
生成的测试结构:
import pytest
from pytest_bdd import scenarios, given, when, then, parsers
scenarios('{project_root}/BDD/authentication_scenarios.md')
@given('a user with valid credentials')
def user_with_valid_credentials(context):
context.user = create_test_user(
username='testuser',
password='ValidP@ssw0rd'
)
@when('the user attempts to login')
def user_attempts_login(context):
context.response = login_api(
username=context.user.username,
password=context.user.password
)
@then('the login should succeed')
def login_succeeds(context):
assert context.response.status_code == 200
assert 'access_token' in context.response.json()
根据需求生成单元测试
# Input: reqs/requirements.md (REQ-AUTH-01)
# Output: tests/unit/test_auth_requirements.py
test-automation generate-unit \
--input reqs/requirements.md \
--filter REQ-AUTH-* \
--output tests/unit/test_auth_requirements.py
生成的测试结构:
import pytest
from auth.service import AuthService
class TestREQ_AUTH_001:
"""Test REQ-AUTH-01: Password must be 8-20 characters"""
def test_password_minimum_length(self):
"""Verify password < 8 characters is rejected"""
result = AuthService.validate_password('Short1!')
assert not result.valid
assert 'minimum 8 characters' in result.error
def test_password_maximum_length(self):
"""Verify password > 20 characters is rejected"""
result = AuthService.validate_password('VeryLongPassword123456789!')
assert not result.valid
assert 'maximum 20 characters' in result.error
def test_password_valid_length(self):
"""Verify password 8-20 characters is accepted"""
result = AuthService.validate_password('ValidP@ss1')
assert result.valid
生成契约测试
# Input: ctrs/CTR-USER-V1.yaml
# Output: tests/contract/test_user_contract.py
test-automation generate-contract \
--input ctrs/CTR-USER-V1.yaml \
--output tests/contract/test_user_contract.py \
--provider user-service
生成的测试结构:
import pytest
from pact import Consumer, Provider, Like, EachLike
@pytest.fixture
def pact():
return Consumer('user-client').has_pact_with(
Provider('user-service')
)
def test_create_user_contract(pact):
expected = {
'user_id': Like('123e4567-e89b-12d3-a456-426614174000'),
'username': Like('testuser'),
'email': Like('[email protected]'),
'created_at': Like('2025-01-01T00:00:00Z')
}
(pact
.given('user database is empty')
.upon_receiving('a request to create a user')
.with_request('POST', '/api/users')
.will_respond_with(201, body=expected))
with pact:
result = user_api.create_user({
'username': 'testuser',
'email': '[email protected]',
'password': 'SecureP@ss123'
})
assert result.status_code == 201
执行测试套件并统计覆盖率
# Run all tests with coverage
test-automation run \
--coverage \
--coverage-report html \
--traceability
# Run specific test category
test-automation run --category bdd
test-automation run --category unit
test-automation run --category contract
# Run tests for specific requirement
test-automation run --requirement REQ-AUTH-01
生成覆盖率报告
test-automation coverage-report \
--format html \
--output reports/coverage \
--include-traceability
生成的报告包括:
- 总体覆盖率百分比
- 按需求统计的覆盖率(REQ → 测试映射)
- 按 BDD 场景统计的覆盖率
- 按契约端点统计的覆盖率
- 未测试的代码路径
- 可追溯性矩阵
测试模板
BDD 测试模板(pytest-bdd)
"""
BDD Tests for {feature_name}
Generated from: {bdd_document_path}
Traceability: {requirement_ids}
"""
import pytest
from pytest_bdd import scenarios, given, when, then, parsers
# Load all scenarios from BDD document
scenarios('{bdd_document_path}')
# Fixtures
@pytest.fixture
def context():
"""Test context for sharing state between steps"""
return {}
# Given steps
@given(parsers.parse('{step_description}'))
def step_given(context, {parameters}):
# Setup preconditions
pass
# When steps
@when(parsers.parse('{step_description}'))
def step_when(context, {parameters}):
# Execute action
pass
# Then steps
@then(parsers.parse('{step_description}'))
def step_then(context, {parameters}):
# Verify outcome
pass
单元测试模板(pytest)
"""
Unit Tests for {requirement_id}
Requirement: {requirement_description}
Source: {requirement_document}
"""
import pytest
from {module} import {class_or_function}
class Test_{requirement_id}:
"""Test suite for {requirement_id}"""
@pytest.fixture
def setup(self):
"""Setup test fixtures"""
return {class_or_function}()
def test_positive_case(self, setup):
"""Test expected behavior"""
result = setup.method({valid_input})
assert result == {expected_output}
def test_boundary_case_min(self, setup):
"""Test minimum boundary value"""
result = setup.method({min_value})
assert {assertion}
def test_boundary_case_max(self, setup):
"""Test maximum boundary value"""
result = setup.method({max_value})
assert {assertion}
def test_invalid_input(self, setup):
"""Test error handling"""
with pytest.raises({expected_exception}):
setup.method({invalid_input})
集成测试模板
"""
Integration Tests for {component_name}
Specification: {spec_document}
Contracts: {contract_ids}
"""
import pytest
from {test_client} import TestClient
from {app} import app
@pytest.fixture
def client():
"""Test client for API integration tests"""
return TestClient(app)
class Test_{component_name}_Integration:
"""Integration test suite for {component_name}"""
def test_api_endpoint_{operation}(self, client):
"""Test {operation} operation"""
# Arrange
test_data = {test_payload}
# Act
response = client.{http_method}(
'{endpoint_path}',
json=test_data
)
# Assert
assert response.status_code == {expected_status}
assert response.json() == {expected_response}
契约测试模板(Pact)
"""
Contract Tests for {service_name}
Contract: {contract_id}
Provider: {provider_service}
Consumer: {consumer_service}
"""
import pytest
from pact import Consumer, Provider, Like, EachLike, Term
@pytest.fixture
def pact():
return Consumer('{consumer_service}').has_pact_with(
Provider('{provider_service}'),
host_name='localhost',
port=1234
)
class Test_{contract_id}:
"""Contract test suite for {contract_id}"""
def test_{operation}_contract(self, pact):
"""Test {operation} contract"""
# Define expected interaction
expected = {expected_schema}
# Setup pact
(pact
.given('{provider_state}')
.upon_receiving('{interaction_description}')
.with_request('{method}', '{path}')
.will_respond_with({status}, body=expected))
# Execute and verify
with pact:
result = {client_call}
assert result == expected
覆盖率分析
需求覆盖率
# Map requirements to tests
REQ-AUTH-01 → [
test_password_minimum_length,
test_password_maximum_length,
test_password_valid_length
] (100% covered)
REQ-AUTH-002 → [
test_password_uppercase_required,
test_password_lowercase_required
] (50% covered - missing number requirement test)
BDD 场景覆盖率
# Map BDD scenarios to test execution
BDD-LOGIN-001: User Login Success → PASS (covered)
BDD-LOGIN-002: User Login Failure → PASS (covered)
BDD-LOGIN-003: Account Lockout → NOT TESTED (0% covered)
契约覆盖率
# Map contract endpoints to tests
POST /api/users → test_create_user_contract (100% covered)
GET /api/users/{id} → test_get_user_contract (100% covered)
PUT /api/users/{id} → NOT TESTED (0% covered)
DELETE /api/users/{id} → NOT TESTED (0% covered)
覆盖率目标
- 单元测试覆盖率:行覆盖率 ≥90%,分支覆盖率 ≥80%
- 需求覆盖率:100% 的 MUST 需求均已测试
- BDD 场景覆盖率:100% 的场景均已执行
- 契约覆盖率:100% 的契约操作均已测试
- 集成覆盖率:≥85% 的集成路径均已测试
测试数据生成
根据需求生成
# REQ-USER-001: Username must be 3-20 alphanumeric characters
test_data = {
'valid': ['abc', 'user123', 'JohnDoe2025', 'a'.repeat(20)],
'boundary_min': 'ab', # Too short
'boundary_max': 'a'.repeat(21), # Too long
'invalid': ['ab', 'user@123', 'John Doe', '123', ''],
'edge_cases': ['aaa', 'zzz', '000', '999']
}
根据契约生成
# CTR-USER-V1: User schema
test_data = {
'valid_user': {
'username': 'testuser',
'email': '[email protected]',
'age': 25
},
'missing_required_field': {
'username': 'testuser'
# Missing email
},
'invalid_type': {
'username': 123, # Should be string
'email': '[email protected]',
'age': 'twenty-five' # Should be integer
}
}
工具访问
所需工具:
Read:读取 SDD 工件(BDD、REQ、CTR、SPEC)Write:生成测试文件Edit:更新现有测试Bash:执行测试框架(pytest、pact)Glob:查找测试文件和工件Grep:搜索需求和场景
所需库:
- pytest
- pytest-bdd
- pytest-cov
- pact-python(用于契约测试)
- hypothesis(用于基于属性的测试)
- faker(用于生成测试数据)
集成点
与 doc-flow 集成
- 创建 BDD/REQ 文档时自动生成测试
- 规范变更时更新测试
- 验证测试的可追溯性
与 code-review 配合
- 验证测试覆盖率是否达到最低阈值
- 找出未测试的代码路径
- 为新代码建议测试用例
与 contract-tester 配合
- 执行契约验证测试
- 验证 API 是否符合 CTR 文档
- 检测破坏性变更
与 doc-validator 配合
- 验证测试可追溯性引用
- 确保所有需求都有对应测试
- 检查测试文档质量
错误处理
BDD 场景解析错误
ACTION: Validate Given-When-Then format
SUGGEST: Correct scenario syntax
VERIFY: Scenario parseable by pytest-bdd
UPDATE: BDD document if needed
测试生成失败
ACTION: Identify missing dependencies or invalid specifications
SUGGEST: Fix specification or install required libraries
VERIFY: Generated test is syntactically correct
UPDATE: Test template if needed
检测到覆盖率缺口
ACTION: Identify untested requirements/scenarios
SUGGEST: Generate additional test cases
VERIFY: New tests increase coverage
UPDATE: Traceability matrix
契约测试失败
ACTION: Compare expected vs actual contract
SUGGEST: Update implementation or contract
VERIFY: Provider and consumer agree on contract
UPDATE: Contract version if breaking change
最佳实践
- 在实现之前生成测试(TDD 方法)
- 在需求与测试之间保持 1:1 映射
- 使用描述性测试名称,引用需求 ID
- 参数化测试,覆盖多种输入场景
- 在单元测试中模拟外部依赖
- 在集成测试中使用真实集成
- 保持测试相互独立(不共享状态)
- 在每次提交时于 CI/CD 中运行测试
- 长期跟踪覆盖率趋势
- 在规格变更时更新测试
限制
- 无法为未定义的需求生成测试
- 测试质量取决于规格的清晰度
- 生成的测试需要人工审查
- 性能测试的负载配置文件需要手动调整
- 复杂的业务逻辑可能需要自定义测试逻辑
- 契约测试需要服务提供方配合
未来增强
- 从自然语言生成测试用例的 AI 驱动功能
- 用于评估测试有效性的变异测试
- 可视化测试结果仪表板
- 自动修复测试(在代码变更时更新测试)
- 预测性覆盖率分析
- 根据风险确定测试优先级
- 持续优化测试
成功标准
- 单元测试覆盖率 ≥90%
- 需求测试覆盖率(MUST 要求)达到 100%
- BDD 场景执行率达到 100%
- 契约操作覆盖率达到 100%
- 集成测试覆盖率 ≥85%
- 关键路径无遗漏测试
- 测试执行时间 < 10 分钟
- 所有测试文档和可追溯性矩阵均包含文档控制部分,其中包括:
- 项目元数据(名称、版本、日期、所有者、编制者、状态)
- 用于跟踪测试计划变更的文档修订历史表
备注
- 生成的测试需要人工审查和完善
- 测试数据应按测试隔离(不共享测试固件)
- 契约测试需要与服务提供方协调
- 覆盖率报告保存在
reports/coverage/ - 测试执行日志保存在
logs/test-runs/ - 每次测试运行后更新可追溯性矩阵
评论
支持 Markdown