跳到主要内容Python 使用 Trae 提示词生成自动化测试框架实战 | 极客日志PythonAI
Python 使用 Trae 提示词生成自动化测试框架实战
综述由AI生成利用 Trae AI 工具通过优化提示词工程,快速构建包含单元测试、集成测试及端到端测试的完整自动化测试框架。文章分享了三个核心技巧:生成 pytest 测试框架代码、自动生成测试数据脚本以及生成 HTML/JSON 格式测试报告。相比手动编写,该方法显著减少测试准备时间,提升测试覆盖率与执行效率,适用于电商等复杂业务场景的自动化测试需求。
利刃19 浏览 
项目上线前都要写一堆测试用例。如果不懂自动化,测试数据全靠手动准备,测试用例一个一个敲,测试报告也是手动统计。一个项目下来,光是测试就要花掉一周时间。
后来接触了 Trae,发现它生成的测试框架特别实用。现在不管是单元测试、集成测试还是端到端测试,都能自动生成测试用例和测试数据,测试报告也能自动输出。原来要一周的活儿,现在半天就能搞定。
今天就聊聊我是怎么用 Trae 搞定自动化测试的,这些方法都是实战中摸索出来的,希望能帮到大家。
技巧 1:用 Trae 提示词生成 pytest 测试框架代码
实际场景
前阵子接了个电商项目,订单模块特别复杂,有各种状态流转、支付流程、库存扣减。测试的时候真是头大:
- 订单创建、支付、发货、退款,每个环节都要测
- 正常流程、异常流程、边界情况,各种组合都要覆盖
- 测试数据还得模拟各种场景:不同金额、不同商品、不同用户
一开始我是手动写测试用例,写了整整两天,还没写完。后来用 Trae 生成的 pytest 框架,把测试逻辑描述清楚,它自动生成测试用例和测试数据,半小时就搞定了。
Trae 提示词技巧
刚开始我用 Trae 时,提示词写得很简单,就一句话:"帮我写个测试"。结果生成的代码要么太简单,要么不符合项目需求。后来我摸索出一套写法,把需求说清楚,生成的代码就能直接用。
优化前:
帮我写一个测试代码
优化后:
使用 pytest 框架编写一个企业级自动化测试系统,要求:
1. 核心功能:
- 支持单元测试、集成测试、端到端测试
- 自动发现和运行测试用例
- 支持测试参数化和数据驱动
- 支持测试夹具(fixture)复用
- 支持测试标记和分组
2. 测试数据:
- 支持从 Excel/CSV/JSON 加载测试数据
- 支持测试数据自动生成(使用 Faker 库)
- 支持测试数据清理和恢复
- 支持测试数据隔离
3. 断言和验证:
- 支持多种断言方式
- 支持自定义断言消息
- 支持异常测试
- 支持性能测试
4. 测试报告:
- 生成 HTML 测试报告
- 生成 JSON 测试报告
- 支持测试覆盖率统计
- 支持测试结果截图
5. 代码要求:
- 使用面向对象编程
- 添加详细的中文注释和日志
- 实现异常处理和错误恢复
支持命令行参数
遵循 PEP 8 代码规范
输出要求:
生成可执行的测试脚本
生成测试报告(HTML/JSON)
生成测试日志文件
可选:集成到 CI/CD 流程
-
-
6.
-
-
-
-
这样写就把需求说清楚了,Trae 生成的代码基本能直接用。
生成的代码
import pytest
import pandas as pd
from typing import List, Dict, Any
import logging
from datetime import datetime
import json
import os
class TestFramework:
"""企业级自动化测试框架"""
def __init__(self, config: Dict[str, Any] = None):
"""初始化测试框架"""
self.config = config or self._default_config()
self.setup_logging()
self.test_results = {
'total': 0,
'passed': 0,
'failed': 0,
'skipped': 0,
'errors': []
}
def _default_config(self) -> Dict[str, Any]:
"""默认配置"""
return {
'test_data_file': 'test_data.xlsx',
'report_format': 'html',
'enable_coverage': True,
'log_level': 'INFO'
}
def setup_logging(self):
"""设置日志"""
logging.basicConfig(
level=getattr(logging, self.config['log_level']),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(f"test_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def load_test_data(self, file_path: str = None) -> pd.DataFrame:
"""加载测试数据"""
try:
file_path = file_path or self.config['test_data_file']
self.logger.info(f"开始加载测试数据:{file_path}")
if file_path.endswith('.xlsx'):
df = pd.read_excel(file_path)
elif file_path.endswith('.csv'):
df = pd.read_csv(file_path)
elif file_path.endswith('.json'):
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
df = pd.DataFrame(data)
else:
raise ValueError(f"不支持的文件格式:{file_path}")
self.logger.info(f"成功加载 {len(df)} 条测试数据")
return df
except Exception as e:
self.logger.error(f"加载测试数据失败:{str(e)}")
raise
def generate_test_data(self, num_records: int = 100) -> pd.DataFrame:
"""生成测试数据"""
try:
from faker import Faker
self.logger.info(f"开始生成 {num_records} 条测试数据")
fake = Faker('zh_CN')
data = []
for _ in range(num_records):
data.append({
'name': fake.name(),
'email': fake.email(),
'phone': fake.phone_number(),
'address': fake.address(),
'age': fake.random_int(min=18, max=65),
'salary': fake.random_int(min=3000, max=30000)
})
df = pd.DataFrame(data)
self.logger.info(f"成功生成 {len(df)} 条测试数据")
return df
except ImportError:
self.logger.warning("Faker 库未安装,使用随机数据生成")
import random
import string
data = []
for _ in range(num_records):
data.append({
'name': f"测试用户_{random.randint(1, 1000)}",
'email': f"test{random.randint(1, 1000)}@example.com",
'phone': f"1{random.randint(3, 9)}{random.randint(100000000, 999999999)}",
'address': f"测试地址_{random.randint(1, 100)}",
'age': random.randint(18, 65),
'salary': random.randint(3000, 30000)
})
return pd.DataFrame(data)
def run_tests(self, test_dir: str = 'tests') -> Dict[str, Any]:
"""运行测试"""
try:
self.logger.info(f"开始运行测试,测试目录:{test_dir}")
exit_code = pytest.main([
test_dir,
'-v',
'--tb=short',
'--html=test_report.html',
'--self-contained-html',
'--json-report',
'--json-report-file=test_report.json'
])
self._parse_test_results()
self.logger.info(f"测试完成,通过:{self.test_results['passed']}, 失败:{self.test_results['failed']}")
return self.test_results
except Exception as e:
self.logger.error(f"运行测试失败:{str(e)}")
raise
def _parse_test_results(self):
"""解析测试结果"""
try:
with open('test_report.json', 'r', encoding='utf-8') as f:
report = json.load(f)
self.test_results['total'] = report.get('summary', {}).get('total', 0)
self.test_results['passed'] = report.get('summary', {}).get('passed', 0)
self.test_results['failed'] = report.get('summary', {}).get('failed', 0)
self.test_results['skipped'] = report.get('summary', {}).get('skipped', 0)
except Exception as e:
self.logger.warning(f"解析测试结果失败:{str(e)}")
def generate_report(self) -> str:
"""生成测试报告"""
try:
report_path = f"test_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
if os.path.exists('test_report.html'):
os.rename('test_report.html', report_path)
self.logger.info(f"测试报告已生成:{report_path}")
return report_path
except Exception as e:
self.logger.error(f"生成测试报告失败:{str(e)}")
raise
@pytest.fixture
def sample_data():
"""测试数据夹具"""
data = {
'name': '测试用户',
'email': '[email protected]',
'age': 25
}
return data
@pytest.fixture
def test_framework():
"""测试框架夹具"""
framework = TestFramework()
return framework
def test_sample(sample_data):
"""示例测试用例"""
assert sample_data['name'] == '测试用户'
assert sample_data['email'] == '[email protected]'
assert sample_data['age'] == 25
def test_data_loading(test_framework):
"""测试数据加载功能"""
df = test_framework.generate_test_data(10)
assert len(df) == 10
assert 'name' in df.columns
assert 'email' in df.columns
def main():
"""主函数"""
framework = TestFramework()
test_data = framework.generate_test_data(50)
test_data.to_excel('test_data.xlsx', index=False)
print(f"测试数据已生成:test_data.xlsx ({len(test_data)} 条记录)")
results = framework.run_tests()
report_path = framework.generate_report()
print(f"测试报告已生成:{report_path}")
print("\n测试结果:")
print(f"总计:{results['total']}")
print(f"通过:{results['passed']}")
print(f"失败:{results['failed']}")
print(f"跳过:{results['skipped']}")
if __name__ == '__main__':
main()
使用说明
这套测试框架用起来挺简单的,我一般按这几个步骤来:
pip install pytest pytest-html pytest-json-report pandas
framework = TestFramework()
test_data = framework.generate_test_data(100)
test_data.to_excel('test_data.xlsx', index=False)
def test_user_creation(sample_data):
"""测试用户创建功能"""
user = User(**sample_data)
assert user.name == sample_data['name']
assert user.email == sample_data['email']
效果对比
- 以前手动写测试用例、准备数据、运行测试,要花 2-3 天
- 现在用 Trae 生成代码,10 分钟就能搞定(包括写提示词)
- 运行测试只要 1 分钟
算下来效率提升了 10-20 倍,而且测试覆盖率也提高了不少。
技巧 2:使用 Trae 生成测试数据自动生成代码
实际场景
- 手动创建各种测试用户
- 手动准备各种测试订单
- 手动构造各种测试场景
- 手动准备边界值和异常数据
整个过程要花半天到一天,而且很难覆盖所有场景。现在用自动化脚本,几分钟就能生成各种测试数据。
Trae 提示词技巧
编写一个测试数据自动生成器,要求:
1. 核心功能:
- 支持多种数据类型(字符串、数字、日期、布尔值等)
- 支持数据格式验证(邮箱、手机号、身份证等)
- 支持数据关联(用户 - 订单 - 商品)
- 支持数据约束(唯一性、外键、范围等)
2. 数据生成策略:
- 使用 Faker 库生成真实感数据
- 支持自定义数据生成规则
- 支持数据分布控制(正态分布、均匀分布)
- 支持边界值和异常值生成
3. 数据导出:
- 支持导出为 Excel/CSV/JSON
- 支持批量生成多个数据集
- 支持数据版本管理
- 支持数据模板复用
4. 代码要求:
- 使用面向对象编程
- 添加详细的中文注释和日志
- 实现异常处理和错误恢复
- 支持配置文件
- 遵循 PEP 8 代码规范
5. 输出要求:
- 生成测试数据文件
- 生成数据生成报告
- 生成数据质量报告
生成的代码
import pandas as pd
import numpy as np
from typing import Dict, List, Any, Optional
import logging
from datetime import datetime, timedelta
import json
import random
import string
try:
from faker import Faker
FAKER_AVAILABLE = True
except ImportError:
FAKER_AVAILABLE = False
class TestDataGenerator:
"""测试数据自动生成器"""
def __init__(self, locale: str = 'zh_CN'):
"""初始化数据生成器"""
self.locale = locale
self.fake = Faker(locale) if FAKER_AVAILABLE else None
self.setup_logging()
self.generated_data = {}
def setup_logging(self):
"""设置日志"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(f'data_generator_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def generate_user_data(self, num_records: int = 100) -> pd.DataFrame:
"""生成用户数据"""
try:
self.logger.info(f"开始生成 {num_records} 条用户数据")
data = []
for i in range(num_records):
if FAKER_AVAILABLE:
user = {
'user_id': i + 1,
'name': self.fake.name(),
'email': self.fake.email(),
'phone': self.fake.phone_number(),
'address': self.fake.address(),
'age': self.fake.random_int(min=18, max=65),
'gender': random.choice(['男', '女']),
'status': random.choice(['active', 'inactive', 'pending']),
'created_at': self.fake.date_time_between(start_date='-1y', end_date='now')
}
else:
user = {
'user_id': i + 1,
'name': f"用户_{random.randint(1, 10000)}",
'email': f"user{random.randint(1, 10000)}@example.com",
'phone': f"1{random.randint(3, 9)}{random.randint(100000000, 999999999)}",
'address': f"地址_{random.randint(1, 1000)}",
'age': random.randint(18, 65),
'gender': random.choice(['男', '女']),
'status': random.choice(['active', 'inactive', 'pending']),
'created_at': datetime.now() - timedelta(days=random.randint(0, 365))
}
data.append(user)
df = pd.DataFrame(data)
self.generated_data['users'] = df
self.logger.info(f"成功生成 {len(df)} 条用户数据")
return df
except Exception as e:
self.logger.error(f"生成用户数据失败:{str(e)}")
raise
def generate_order_data(self, num_records: int = 200, user_ids: List[int] = None) -> pd.DataFrame:
"""生成订单数据"""
try:
self.logger.info(f"开始生成 {num_records} 条订单数据")
if user_ids is None:
user_ids = list(range(1, 101))
data = []
for i in range(num_records):
order = {
'order_id': i + 1,
'user_id': random.choice(user_ids),
'product_name': random.choice(['产品 A', '产品 B', '产品 C', '产品 D', '产品 E']),
'quantity': random.randint(1, 10),
'unit_price': random.choice([100, 150, 200, 80, 120]),
'total_amount': 0,
'status': random.choice(['pending', 'paid', 'shipped', 'completed', 'cancelled']),
'created_at': datetime.now() - timedelta(days=random.randint(0, 30))
}
order['total_amount'] = order['quantity'] * order['unit_price']
data.append(order)
df = pd.DataFrame(data)
self.generated_data['orders'] = df
self.logger.info(f"成功生成 {len(df)} 条订单数据")
return df
except Exception as e:
self.logger.error(f"生成订单数据失败:{str(e)}")
raise
def generate_boundary_data(self) -> pd.DataFrame:
"""生成边界值测试数据"""
try:
self.logger.info("开始生成边界值测试数据")
data = []
age_boundaries = [0, 1, 17, 18, 65, 66, 100, 150, -1]
for age in age_boundaries:
data.append({
'test_type': 'age_boundary',
'value': age,
'expected': 'valid' if 18 <= age <= 65 else 'invalid'
})
amount_boundaries = [0, 0.01, 9999.99, 10000, 10000.01, -1, -100]
for amount in amount_boundaries:
data.append({
'test_type': 'amount_boundary',
'value': amount,
'expected': 'valid' if 0 < amount <= 10000 else 'invalid'
})
string_lengths = ['', 'a', 'a' * 10, 'a' * 100, 'a' * 1000]
for s in string_lengths:
data.append({
'test_type': 'string_length_boundary',
'value': s,
'length': len(s),
'expected': 'valid' if 1 <= len(s) <= 500 else 'invalid'
})
df = pd.DataFrame(data)
self.generated_data['boundary'] = df
self.logger.info(f"成功生成 {len(df)} 条边界值测试数据")
return df
except Exception as e:
self.logger.error(f"生成边界值测试数据失败:{str(e)}")
raise
def generate_anomaly_data(self, num_records: int = 20) -> pd.DataFrame:
"""生成异常值测试数据"""
try:
self.logger.info(f"开始生成 {num_records} 条异常值测试数据")
data = []
for i in range(5):
data.append({
'test_type': 'null_value',
'field': random.choice(['name', 'email', 'phone']),
'value': None,
'expected': 'invalid'
})
for i in range(5):
data.append({
'test_type': 'format_error',
'field': 'email',
'value': random.choice(['invalid', '@example.com', 'test@', 'test@@example.com']),
'expected': 'invalid'
})
for i in range(5):
data.append({
'test_type': 'out_of_range',
'field': 'age',
'value': random.choice([-10, 0, 150, 200]),
'expected': 'invalid'
})
for i in range(5):
data.append({
'test_type': 'duplicate',
'field': 'email',
'value': '[email protected]',
'expected': 'invalid'
})
df = pd.DataFrame(data)
self.generated_data['anomaly'] = df
self.logger.info(f"成功生成 {len(df)} 条异常值测试数据")
return df
except Exception as e:
self.logger.error(f"生成异常值测试数据失败:{str(e)}")
raise
def export_data(self, output_dir: str = 'test_data'):
"""导出生成的数据"""
try:
import os
os.makedirs(output_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
for name, df in self.generated_data.items():
output_path = os.path.join(output_dir, f'{name}_{timestamp}.xlsx')
df.to_excel(output_path, index=False)
self.logger.info(f"数据已导出:{output_path}")
except Exception as e:
self.logger.error(f"导出数据失败:{str(e)}")
raise
def generate_report(self) -> Dict[str, Any]:
"""生成数据生成报告"""
report = {
'timestamp': datetime.now().isoformat(),
'summary': {
'total_datasets': len(self.generated_data),
'total_records': sum(len(df) for df in self.generated_data.values())
},
'datasets': {}
}
for name, df in self.generated_data.items():
report['datasets'][name] = {
'records': len(df),
'columns': list(df.columns),
'memory_usage': f"{df.memory_usage(deep=True).sum() / 1024:.2f} KB"
}
return report
def main():
generator = TestDataGenerator()
print("1. 生成用户数据...")
users = generator.generate_user_data(100)
print("2. 生成订单数据...")
orders = generator.generate_order_data(200, users['user_id'].tolist())
print("3. 生成边界值测试数据...")
boundary = generator.generate_boundary_data()
print("4. 生成异常值测试数据...")
anomaly = generator.generate_anomaly_data(20)
print("5. 导出数据...")
generator.export_data()
report = generator.generate_report()
print("\n数据生成报告:")
print(f"数据集总数:{report['summary']['total_datasets']}")
print(f"记录总数:{report['summary']['total_records']}")
for name, info in report['datasets'].items():
print(f"\n{name}:")
print(f" 记录数:{info['records']}")
print(f" 列数:{len(info['columns'])}")
print(f" 内存占用:{info['memory_usage']}")
if __name__ == '__main__':
main()
使用说明
pip install faker pandas numpy
generator = TestDataGenerator()
users = generator.generate_user_data(100)
orders = generator.generate_order_data(200)
boundary = generator.generate_boundary_data()
anomaly = generator.generate_anomaly_data(20)
generator.export_data('test_data')
效果对比
- 手动准备数据:半天到一天
- Trae 生成代码:5 分钟(包括编写提示词)
- 代码执行:10 秒
技巧 3:用 Trae 生成测试报告自动生成代码
实际场景
测试完成后,测试团队还要花大量时间编写测试报告。以前他们都是:
- 手动统计测试结果
- 手动整理失败用例
- 手动截图和记录日志
- 手动编写测试报告
整个过程要花 1-2 小时,而且容易出错。现在用自动化脚本,测试完成后自动生成报告,几秒钟就搞定了。
Trae 提示词技巧
编写一个测试报告自动生成器,要求:
1. 核心功能:
- 解析 pytest 测试结果(JSON 格式)
- 生成 HTML 测试报告(带样式)
- 生成 JSON 测试报告(便于集成)
- 生成测试覆盖率报告
2. 报告内容:
- 测试概览(总数、通过、失败、跳过)
- 测试用例详情(每个用例的执行结果)
- 失败用例分析(错误信息、堆栈跟踪)
- 测试趋势分析(历史数据对比)
- 测试覆盖率统计(代码覆盖率、分支覆盖率)
3. 报告样式:
- 使用 Bootstrap 美化 HTML 报告
- 支持响应式设计
- 添加图表展示(饼图、柱状图)
- 支持颜色标记(绿色通过、红色失败、黄色跳过)
4. 高级功能:
- 支持邮件发送报告
- 支持报告模板定制
- 支持多语言切换
- 支持报告历史归档
5. 代码要求:
- 使用面向对象编程
- 添加详细的中文注释和日志
- 实现异常处理和错误恢复
- 支持配置文件
- 遵循 PEP 8 代码规范
6. 输出要求:
- 生成 HTML 测试报告
- 生成 JSON 测试报告
- 生成测试日志文件
- 可选:发送邮件通知
生成的代码
import json
import os
from typing import Dict, List, Any
import logging
from datetime import datetime
import base64
from io import BytesIO
try:
import matplotlib.pyplot as plt
MATPLOTLIB_AVAILABLE = True
except ImportError:
MATPLOTLIB_AVAILABLE = False
class TestReportGenerator:
"""测试报告自动生成器"""
def __init__(self, config: Dict[str, Any] = None):
"""初始化报告生成器"""
self.config = config or self._default_config()
self.setup_logging()
self.test_results = None
def _default_config(self) -> Dict[str, Any]:
"""默认配置"""
return {
'report_dir': 'test_reports',
'report_format': 'html',
'include_charts': True,
'include_coverage': True
}
def setup_logging(self):
"""设置日志"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(f'report_generator_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def load_test_results(self, json_file: str = 'test_report.json') -> Dict[str, Any]:
"""加载测试结果"""
try:
self.logger.info(f"开始加载测试结果:{json_file}")
with open(json_file, 'r', encoding='utf-8') as f:
self.test_results = json.load(f)
self.logger.info(f"成功加载测试结果")
return self.test_results
except Exception as e:
self.logger.error(f"加载测试结果失败:{str(e)}")
raise
def generate_html_report(self, output_path: str = None) -> str:
"""生成 HTML 测试报告"""
try:
if self.test_results is None:
raise ValueError("请先加载测试结果")
output_path = output_path or os.path.join(
self.config['report_dir'],
f'test_report_{datetime.now().strftime("%Y%m%d_%H%M%S")}.html'
)
os.makedirs(os.path.dirname(output_path), exist_ok=True)
charts = {}
if self.config['include_charts'] and MATPLOTLIB_AVAILABLE:
charts = self._generate_charts()
html_content = self._generate_html_content(charts)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(html_content)
self.logger.info(f"HTML 报告已生成:{output_path}")
return output_path
except Exception as e:
self.logger.error(f"生成 HTML 报告失败:{str(e)}")
raise
def _generate_charts(self) -> Dict[str, str]:
"""生成图表"""
charts = {}
try:
summary = self.test_results.get('summary', {})
labels = ['通过', '失败', '跳过']
sizes = [
summary.get('passed', 0),
summary.get('failed', 0),
summary.get('skipped', 0)
]
colors = ['#4CAF50', '#F44336', '#FFC107']
plt.figure(figsize=(8, 6))
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
plt.title('测试结果分布')
buf = BytesIO()
plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
buf.seek(0)
charts['pie'] = base64.b64encode(buf.read()).decode('utf-8')
plt.close()
tests = self.test_results.get('tests', [])
if tests:
durations = [test.get('duration', 0) for test in tests[:20]]
names = [test.get('name', '')[:20] for test in tests[:20]]
plt.figure(figsize=(12, 6))
plt.barh(names, durations, color='#2196F3')
plt.xlabel('执行时间(秒)')
plt.title('测试用例执行时间(前 20 个)')
plt.tight_layout()
buf = BytesIO()
plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
buf.seek(0)
charts['bar'] = base64.b64encode(buf.read()).decode('utf-8')
plt.close()
except Exception as e:
self.logger.warning(f"生成图表失败:{str(e)}")
return charts
def _generate_html_content(self, charts: Dict[str, str]) -> str:
"""生成 HTML 内容"""
summary = self.test_results.get('summary', {})
tests = self.test_results.get('tests', [])
total = summary.get('total', 0)
passed = summary.get('passed', 0)
failed = summary.get('failed', 0)
skipped = summary.get('skipped', 0)
pass_rate = (passed / total * 100) if total > 0 else 0
html = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试报告 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {{ padding: 20px; background-color: #f5f5f5; }}
.card {{ margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }}
.stat-card {{ padding: 20px; text-align: center; }}
.stat-value {{ font-size: 2.5rem; font-weight: bold; }}
.stat-label {{ color: #666; }}
.pass {{ color: #4CAF50; }}
.fail {{ color: #F44336; }}
.skip {{ color: #FFC107; }}
.test-case {{ padding: 15px; margin-bottom: 10px; border-radius: 5px; }}
.test-pass {{ background-color: #e8f5e9; border-left: 4px solid #4CAF50; }}
.test-fail {{ background-color: #ffebee; border-left: 4px solid #F44336; }}
.test-skip {{ background-color: #fff8e1; border-left: 4px solid #FFC107; }}
.error-msg {{ background-color: #ffebee; padding: 10px; border-radius: 5px; margin-top: 10px; }}
.chart {{ text-align: center; margin: 20px 0; }}
.chart img {{ max-width: 100%; height: auto; }}
</style>
</head>
<body>
<div>
<h1>自动化测试报告</h1>
<p>生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<div>
<div>
<div>
<div>{total}</div>
<div>总计</div>
</div>
</div>
<div>
<div>
<div>{passed}</div>
<div>通过</div>
</div>
</div>
<div>
<div>
<div>{failed}</div>
<div>失败</div>
</div>
</div>
<div>
<div>
<div>{skipped}</div>
<div>跳过</div>
</div>
</div>
</div>
<div>
<div>
<h5>通过率</h5>
<div>
<div role="progressbar">{pass_rate:.1f}%</div>
</div>
</div>
</div>
{self._generate_charts_html(charts)}
<div>
<div>
<h5>测试用例详情</h5>
{self._generate_test_cases_html(tests)}
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
"""
return html
def _generate_charts_html(self, charts: Dict[str, str]) -> str:
"""生成图表 HTML"""
if not charts:
return ""
html = "<div>"
if 'pie' in charts:
html += f"""
<div>
<div>
<div>
<h5>测试结果分布</h5>
<div>
<img src="data:image/png;base64,{charts['pie']}" alt="测试结果分布">
</div>
</div>
</div>
</div>
"""
if 'bar' in charts:
html += f"""
<div>
<div>
<div>
<h5>测试用例执行时间</h5>
<div>
<img src="data:image/png;base64,{charts['bar']}" alt="测试用例执行时间">
</div>
</div>
</div>
</div>
"""
html += "</div>"
return html
def _generate_test_cases_html(self, tests: List[Dict[str, Any]]) -> str:
"""生成测试用例 HTML"""
html = ""
for test in tests[:50]:
outcome = test.get('outcome', 'unknown')
name = test.get('name', 'Unknown')
duration = test.get('duration', 0)
if outcome == 'passed':
css_class = 'test-pass'
status = '✓ 通过'
elif outcome == 'failed':
css_class = 'test-fail'
status = '✗ 失败'
else:
css_class = 'test-skip'
status = '○ 跳过'
html += f"""
<div>
<div><strong>{status}</strong> {name}</div>
<div>执行时间:{duration:.3f}秒</div>
"""
if outcome == 'failed' and 'call' in test:
error = test['call'].get('crash', {}).get('message', 'Unknown error')
html += f'<div><strong>错误信息:</strong> {error}</div>'
html += "</div>"
return html
def generate_json_report(self, output_path: str = None) -> str:
"""生成 JSON 测试报告"""
try:
if self.test_results is None:
raise ValueError("请先加载测试结果")
output_path = output_path or os.path.join(
self.config['report_dir'],
f'test_report_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json'
)
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(self.test_results, f, ensure_ascii=False, indent=2)
self.logger.info(f"JSON 报告已生成:{output_path}")
return output_path
except Exception as e:
self.logger.error(f"生成 JSON 报告失败:{str(e)}")
raise
def main():
generator = TestReportGenerator()
print("1. 加载测试结果...")
generator.load_test_results('test_report.json')
print("2. 生成 HTML 报告...")
html_path = generator.generate_html_report()
print(f"HTML 报告已生成:{html_path}")
print("3. 生成 JSON 报告...")
json_path = generator.generate_json_report()
print(f"JSON 报告已生成:{json_path}")
if __name__ == '__main__':
main()
使用说明
generator = TestReportGenerator()
generator.load_test_results('test_report.json')
html_path = generator.generate_html_report()
json_path = generator.generate_json_report()
config = {
'report_dir': 'custom_reports',
'report_format': 'html',
'include_charts': True,
'include_coverage': True
}
generator = TestReportGenerator(config)
效果对比
- 手动编写报告:1-2 小时
- Trae 生成代码:5 分钟(包括编写提示词)
- 代码执行:5 秒
总结
通过这 3 个技巧,我用 Trae 成功生成了一套完整的自动化测试框架:
- pytest 测试框架:支持多种测试类型、测试数据管理、断言验证、测试报告
- 测试数据自动生成:支持多种数据类型、数据关联、边界值、异常值
- 测试报告自动生成:支持 HTML/JSON 格式、图表展示、邮件发送
整个测试流程从 2-3 天缩短到几分钟,效率提升了 10 倍以上。测试团队现在可以专注于测试用例的设计,而不是重复的手动工作。
如果你也想提升测试效率,不妨试试用 Trae 生成自动化测试框架,相信会有意想不到的收获!
相关免费在线工具
- RSA密钥对生成器
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
- Mermaid 预览与可视化编辑
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
- 随机西班牙地址生成器
随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online