Files
novalon-website/e2e-tests/scripts/ci_test.py
T
张翔 f14002559e feat(e2e-tests): 添加端到端测试框架及测试用例
refactor(components): 调整头部和页脚布局样式
style(hero-section): 更新徽章动画效果

docs: 添加测试框架README文档
test: 实现首页、导航和联系表单的测试用例
ci: 添加CI测试脚本和配置
2026-02-02 19:36:33 +08:00

282 lines
8.2 KiB
Python

#!/usr/bin/env python3
"""
CI/CD 测试脚本
用于持续集成环境中的测试执行
"""
import os
import sys
import json
import time
from pathlib import Path
from datetime import datetime
# 添加项目路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
from config.settings import get_settings
from utils.logger import get_logger
class CITestRunner:
"""CI测试运行器"""
def __init__(self):
self.logger = get_logger()
self.settings = get_settings()
self.results = {
"timestamp": datetime.now().isoformat(),
"environment": os.environ.get("ENVIRONMENT", "development"),
"browser": os.environ.get("PLAYWRIGHT_BROWSER", "chromium"),
"tests": [],
"summary": {
"total": 0,
"passed": 0,
"failed": 0,
"skipped": 0,
"error": 0,
"duration": 0
}
}
def run_smoke_tests(self) -> bool:
"""运行冒烟测试"""
self.logger.section("运行冒烟测试")
from playwright.sync_api import sync_playwright
import pytest
pytest_args = [
"-c", str(project_root / "pytest.ini"),
"-m", "smoke",
"-v",
"--tb=short",
"--json-report",
"--json-report-file=reports/smoke_test_results.json",
"tests"
]
try:
exit_code = pytest.main(pytest_args)
return exit_code == 0
except Exception as e:
self.logger.error(f"冒烟测试失败: {e}")
return False
def run_regression_tests(self) -> bool:
"""运行回归测试"""
self.logger.section("运行回归测试")
import pytest
pytest_args = [
"-c", str(project_root / "pytest.ini"),
"-m", "regression",
"-v",
"--tb=short",
"--json-report",
"--json-report-file=reports/regression_test_results.json",
"tests"
]
try:
exit_code = pytest.main(pytest_args)
return exit_code == 0
except Exception as e:
self.logger.error(f"回归测试失败: {e}")
return False
def run_performance_tests(self) -> bool:
"""运行性能测试"""
self.logger.section("运行性能测试")
import pytest
pytest_args = [
"-c", str(project_root / "pytest.ini"),
"-m", "performance",
"-v",
"--tb=short",
"--json-report",
"--json-report-file=reports/performance_test_results.json",
"tests"
]
try:
exit_code = pytest.main(pytest_args)
return exit_code == 0
except Exception as e:
self.logger.error(f"性能测试失败: {e}")
return False
def run_cross_browser_tests(self) -> dict:
"""运行跨浏览器测试"""
self.logger.section("运行跨浏览器测试")
import pytest
browsers = ["chromium", "firefox", "webkit"]
results = {}
for browser in browsers:
self.logger.info(f"测试浏览器: {browser}")
os.environ["PLAYWRIGHT_BROWSER"] = browser
pytest_args = [
"-c", str(project_root / "pytest.ini"),
"-m", "smoke",
"-v",
"--tb=short",
f"--json-report=reports/{browser}_test_results.json",
"tests"
]
try:
exit_code = pytest.main(pytest_args)
results[browser] = exit_code == 0
except Exception as e:
self.logger.error(f"{browser} 测试失败: {e}")
results[browser] = False
return results
def run_full_test_suite(self) -> bool:
"""运行完整测试套件"""
self.logger.section("运行完整测试套件")
import pytest
pytest_args = [
"-c", str(project_root / "pytest.ini"),
"-v",
"--tb=short",
"--json-report",
"--json-report-file=reports/full_test_results.json",
"--html=reports/full_test_report.html",
"--self-contained-html",
"tests"
]
try:
exit_code = pytest.main(pytest_args)
return exit_code == 0
except Exception as e:
self.logger.error(f"完整测试失败: {e}")
return False
def generate_ci_report(self, test_results: dict):
"""生成CI测试报告"""
report_path = Path("reports/ci_test_report.json")
report_path.parent.mkdir(parents=True, exist_ok=True)
with open(report_path, "w", encoding="utf-8") as f:
json.dump(test_results, f, indent=2, ensure_ascii=False)
self.logger.info(f"CI报告已生成: {report_path}")
def run_ci_tests(self, test_type: str = "full"):
"""运行CI测试"""
start_time = time.time()
self.logger.section("开始 CI 测试")
self.logger.info(f"环境: {self.results['environment']}")
self.logger.info(f"浏览器: {self.results['browser']}")
self.logger.info(f"测试类型: {test_type}")
success = False
if test_type == "smoke":
success = self.run_smoke_tests()
elif test_type == "regression":
success = self.run_regression_tests()
elif test_type == "performance":
success = self.run_performance_tests()
elif test_type == "cross_browser":
cross_results = self.run_cross_browser_tests()
success = all(cross_results.values())
self.results["cross_browser_results"] = cross_results
elif test_type == "full":
success = self.run_full_test_suite()
else:
self.logger.error(f"未知的测试类型: {test_type}")
return False
end_time = time.time()
self.results["summary"]["duration"] = end_time - start_time
self.results["success"] = success
self.logger.section("CI 测试完成")
self.logger.info(f"总耗时: {self.results['summary']['duration']:.2f}")
self.logger.info(f"测试结果: {'成功' if success else '失败'}")
# 生成报告
self.generate_ci_report(self.results)
return success
def parse_ci_arguments():
"""解析CI参数"""
parser = argparse.ArgumentParser(
description="Novalon Website CI 测试运行器"
)
parser.add_argument(
"--test-type",
default="full",
choices=["smoke", "regression", "performance", "cross_browser", "full"],
help="测试类型 (默认: full)"
)
parser.add_argument(
"--env",
default="development",
choices=["development", "staging", "production"],
help="测试环境 (默认: development)"
)
parser.add_argument(
"--browser",
default="chromium",
choices=["chromium", "firefox", "webkit", "all"],
help="浏览器 (默认: chromium)"
)
parser.add_argument(
"--report-dir",
default="reports",
help="报告目录 (默认: reports)"
)
return parser.parse_args()
def main():
"""CI主函数"""
args = parse_ci_arguments()
# 设置环境变量
os.environ["ENVIRONMENT"] = args.env
os.environ["PLAYWRIGHT_BROWSER"] = args.browser
os.environ["REPORT_DIR"] = args.report_dir
# 确保报告目录存在
Path(args.report_dir).mkdir(parents=True, exist_ok=True)
# 运行测试
runner = CITestRunner()
success = runner.run_ci_tests(args.test_type)
# 输出结果
if success:
print("\n✅ CI 测试通过")
sys.exit(0)
else:
print("\n❌ CI 测试失败")
sys.exit(1)
if __name__ == "__main__":
main()