feat(e2e-tests): 添加端到端测试框架及测试用例
refactor(components): 调整头部和页脚布局样式 style(hero-section): 更新徽章动画效果 docs: 添加测试框架README文档 test: 实现首页、导航和联系表单的测试用例 ci: 添加CI测试脚本和配置
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user