# AutoTestProjects **Repository Path**: two-liang-rice/auto-test-projects ## Basic Information - **Project Name**: AutoTestProjects - **Description**: 自动化测试框架 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-31 - **Last Updated**: 2026-01-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 基于 Pytest 与 Allure 的自动化测试全栈实践 ## 一、核心框架简介 **1. Pytest:** - 优势:语法简洁,支持 fixture(夹具)实现灵活的测试前置后置条件、参数化测试、丰富的插件生态。 - 角色:测试用例的组织、调度和执行引擎。它是我们整个自动化测试体系的基石。 **2. Allure:** - 优势:生成极其美观、交互性强的测试报告,支持步骤(Step)、严重等级(Severity)、附件(Attachment)等特性,能清晰展示测试执行细节和失败原因。 - 角色:测试结果的“可视化仪表盘”,让非技术人员也能轻松理解测试状态。 ## 二、环境搭建与基础配置 **安装必要的库:** ```bash # 核心测试框架 pip install pytest # 测试报告框架 pip install allure-pytest # 接口测试库 pip install requests # UI自动化测试库 (选择其一或全部) pip install selenium pip install pytest-playwright # 安装Playwright浏览器驱动 playwright install ``` **配置Allure:** 从 [Allure 官网](https://github.com/allure-framework/allure2/releases)下载命令行工具,并配置其路径到系统环境变量 PATH中。 ## 三、接口自动化测试:使用 Requests 基于 pytest + Requests + Allure 的接口自动化测试框架。 **核心组件:** - pytest: 测试框架主体 - Requests: HTTP 请求库 - Allure: 测试报告生成 - MySQL: 数据库操作 - Excel: 测试用例管理 **核心功能详解** 1. 环境配置管理 ```python # conftest.py def pytest_addoption(parser): parser.addoption("--env", action="store", default="dev", help="测试环境: dev/test/prod") parser.addoption("--url", action="store", default=None, help="API 基础 URL") ``` 2. HTTPClient 封装 ```python # conftest.py @pytest.fixture def http_client(env_config) -> HTTPClient: """提供 HTTPClient 实例的 fixture""" with HTTPClient( base_url=env_config.get("base_url"), timeout=10, max_retries=2 ) as client: yield client ``` HTTPClient 核心功能(基于 Requests 封装): - 自动重试机制 - 超时控制 - 会话管理 - 认证处理 3. 测试用例示例 ```python @allure.feature('TestCase类') class TestCase01: @pytest.fixture(autouse=True) def setup_teardown_method(self,http_client:HTTPClient, db_connection:DBConnection): # 创建API客户端实例 self.api_client = ApiV1(http_client) self.db = db_connection @allure.story('用户管理测试') @allure.title('测试获取当前用户信息') @pytest.mark.testcase("2-1") def test_get_current_user_info(self): """测试获取当前用户信息 - 验证认证后能正确获取用户信息""" with allure.step("admin登录"): self.api_client.login(username="admin", password="111111") with allure.step("获取当前用户信息"): user_info = self.api_client.get_current_user_info() # 验证返回数据结构 assert user_info is not None assert "data" in user_info assert "username" in user_info["data"] assert "email" in user_info["data"] ``` 4. 数据库操作集成 ```python # conftest.py @pytest.fixture(scope="session") def db_connection(env_config) -> Generator[DBConnection, None, None]: """数据库连接fixture,自动管理连接和事务""" db_config = env_config.get("db", {}) with DBConnection(**db_config) as db: try: yield db finally: # 测试完成后清理user表数据 _cleanup_user_table(db) def _cleanup_user_table(db: DBConnection) -> None: """清理user表数据的辅助函数""" try: # 根据实际表结构调整清理逻辑 # 示例1: 删除所有测试数据(根据特定条件) db.execute("DELETE FROM users WHERE email LIKE '%test%' OR username LIKE 'test%'") print("User表数据清理完成") except Exception as e: print(f"清理user表数据时发生错误: {e}") # 可以根据需要决定是否抛出异常 raise ``` 6. 测试报告\ 测试用例过滤 ```python # 根据测试单过滤用例 pytest --filter-testcase # 用例标记关联 @pytest.mark.testcase("2-1") # 关联用例编号 ``` Allure报告定制: ```python # conftest.py def allure_report_with_excel(report,item)->None: """在allure报告中添加excel用例ID""" if report.when != "call": return # 获取testcase标记 testcase_marker = item.get_closest_marker("testcase") if testcase_marker: # 获取测试用例ID testcase_ids = testcase_marker.args if testcase_ids: report.testcase_ids = list(testcase_ids) for case_id in list(testcase_ids): # 添加到allure报告 allure.dynamic.id(case_id) allure.dynamic.tag(f"测试用例:{case_id}") ``` 7. 将测试执行结果同步到excel测试用例文档结果 ```bash python report_cli.py excel --allure ./allure-results --file "自动化测试-全部用例.xlsx" --sheet "测试用例" ``` ## 四、UI 自动化测试:Selenium 与 Playwright 的选择 ### 1. 使用 Selenium Selenium 是 UI 自动化的老牌标准,支持多种浏览器和语言。 **核心组件:** ```python # 浏览器管理 from utils.browser.selenium_util import SeleniumBrowserFactoryExtend # 页面对象模型 (Page Object Model) from tests2.pages.stock_page import StockPage from tests2.pages.profile_page import ProfilePage # 测试框架集成 import pytest import allure ``` **Selenium 浏览器管理** 浏览器初始化 ```python @pytest.fixture(scope="session") def browser(pytestconfig): """初始化浏览器 - 会话级别fixture""" with SeleniumBrowserFactoryExtend( base_dir=pytestconfig.option.root_dir, cfg=pytestconfig.option.selenium ) as driver: yield driver driver.quit() # 测试结束后自动关闭 ``` 特点:\ 上下文管理: 使用 with语句确保资源正确释放\ 配置化: 通过配置文件管理浏览器参数(无头模式、窗口大小等) 浏览器配置示例 ```python # 支持的命令行参数 pytest --headless # 无头模式 pytest --env=test # 测试环境 ``` **页面对象模型 (Page Object)** 示例 ```python class BasePage: def __init__(self, webdriver: SeleniumBrowserFactoryExtend, timeout: int = 30, base_url: str = ""): self._webdriver = webdriver self._timeout = timeout self._base_url = base_url.rstrip("/") @property def webdriver(self): return self._webdriver def get_webdriver(self): return self._webdriver def open(self, url: str=""): url = url.lstrip("/") self._webdriver.open(f"{self._base_url}/{url}") return self def get_title(self): return self._webdriver.get_title() def login(self, username: str, password: str, path:Optional[str]=None): if path: self.open(path) else: self.open("") logging.info("打开页面: %s, title:%s", self._webdriver.get_current_url(), self.get_title()) if self.get_title() != "登录": self.open("/accounts/logout/") self._webdriver.input_text((By.NAME, "username"), username) self._webdriver.input_text((By.ID, "password"),password) ``` **测试用例设计** 基本测试结构 ```python @allure.story("证券基本资料默认加载页面") @allure.title("基本搜索功能") @pytest.mark.testcase(5) # 关联禅道用例ID @screenshot_on_failure("stock_page") # 失败自动截图 def test_stock_search(self): """测试基本搜索功能""" with allure.step("点击菜单证券->证券基本资料"): self.stock_page.navigate_to_menu(["证券","证券基本资料"]) assert self.stock_page.get_title() == "证券基本资料" ``` 参数化测试 ```python @pytest.mark.parametrize("search_params,expected_count,description", [ ({"code": "sh.600000"}, 1, "精确查询"), ({"stype": "股票"}, 50, "按类型查询"), ]) def test_stock_full_code_search_parametrized(self, search_params, expected_count, description): """测试不同条件组合的查询功能""" ``` **测试报告** 测试用例过滤 ```python # 根据禅道测试单过滤用例 pytest --filter-testcase # 用例标记关联 @pytest.mark.testcase(5) # 关联禅道用例ID ``` Allure报告定制: ```python def allure_report_with_zentao(report,item)->None: """在allure报告和html报告中添加禅道链接""" if report.when != "call": return # 通过 item.config 访问zentao配置 zentao_config = item.config.option.zentao zentao_url = str(zentao_config.get("url")).rstrip("/") zentao_testtask = zentao_config.get("testtask") # 获取testcase标记 testcase_marker = item.get_closest_marker("testcase") if testcase_marker: # 获取测试用例ID testcase_ids = testcase_marker.args if testcase_ids: # 生成禅道信息加入report中,同时添加allure报告中 for case_id in list(testcase_ids): case_link = f"{zentao_url}/testcase-view-{case_id}-0-testtask-{zentao_testtask}.html" report.testcase_links.append(case_link) # 添加case_id到allure中 allure.dynamic.id(case_id) # 在allure链接中显示禅道测试用例链接 allure.dynamic.testcase(case_link, name=f"测试用例") # 添加标签 allure.dynamic.tag(f"测试用例:{case_id}", f"测试单:{zentao_testtask}") ``` Allure测试报告   **与禅道平台集成** ```bash # 执行命令将测试结果同步到禅道测试单 python report_cli.py zentao --allure ./allure-results ``` ### 2. 使用 Playwright Playwright 由微软开发,以其速度快、可靠性高、自动等待机制强大而著称。 **核心组件:** ```python # 浏览器管理 from utils.browser.playwright_util import SyncPlaywrightBrowserManager, SyncBrowserContextHandler, SyncPageOperator # 页面对象模型 (Page Object Model) from tests3.pages.stock_page import StockPage from tests3.pages.profile_page import ProfilePage # 测试框架集成 import pytest import allure ``` **Playwright 浏览器管理** 浏览器初始化 ```python @pytest.fixture(scope="session") def playwright()->Playwright: """Playwright实例fixture""" with sync_playwright() as playwright: yield playwright @pytest.fixture(scope="session") def browser(playwright: Playwright, pytestconfig)->SyncPlaywrightBrowserManager: """浏览器实例fixture""" with SyncPlaywrightBrowserManager(playwright, **pytestconfig.option.browser_opt) as browser: expect.set_options(timeout=30_000) yield browser @pytest.fixture(scope="class") def context(browser:SyncPlaywrightBrowserManager)->"SyncBrowserContextHandler": with SyncBrowserContextHandler(browser) as context: yield context ``` **页面对象模型 (Page Object)** StockPage 示例 ```python class BasePage: def __init__(self, page_op: SyncPageOperator): self._page_op = page_op def open(self, url: str): self._page_op.goto(url) def get_title(self): return self._page_op.get_title() def get_url(self): return self._page_op.get_url() def get_page(self) -> Page: return self._page_op.page def login(self, username: str, password: str): expect(self._page_op.get_by_role("heading", name="登录")).to_be_visible() self._page_op.get_by_role("textbox", name="用户名").fill(username) self._page_op.get_by_role("textbox", name="密码").fill(password) self._page_op.get_by_role("button", name="登录").click() return self ``` **测试用例设计** 基本测试结构 ```python @allure.title("修改用户个人资料") @allure.severity(allure.severity_level.NORMAL) @pytest.mark.testcase(8) @screenshot_on_failure("profile_page") def test_edit_profile_page(self): with allure.step("打开用户信息下拉菜单"): is_open_user_dropdown = self.profile_page.open_user_dropdown() assert is_open_user_dropdown, "打开用户下拉菜单失败" with allure.step("导航到个人中心"): success = self.profile_page.go_to_profile(is_open_user_dropdown) assert success, "导航到个人中心失败" with allure.step("点击个人中心页面左侧栏的编辑资料按钮"): self.profile_page.get_card_user_profile_sidebar_edit() with allure.step("修改用户个人资料信息"): with pytest.raises(Error) as exc_info: result = self.profile_page.submit_card_right_content_area( first_name="张", last_name="三丰", birth_date=date(2011, 4, 15), phone="+9112345678", website="www.example.com", bio="dsgdsgdsgfdgdsgfdf" ) allure.attach(f"提交结果: {result}", name="提交结果") assert "提交成功" in result if "验证消息" in str(exc_info.value): self.profile_page.submit_card_right_content_area_error_click() with allure.step("获取修改后的个人中心右侧内容区域的信息"): updated_right_info = self.profile_page.get_card_right_content_area() assert updated_right_info is not None, "获取更新后的右侧内容区域信息失败" allure.attach(f"更新后的右侧内容区域信息: {updated_right_info}", name="更新后的右侧内容区域信息") ``` **测试报告** 同Selenium ### Selenium vs. Playwright 简单对比: - 安装配置:Playwright 通过 playwright install一键安装浏览器驱动,比 Selenium 手动管理驱动更简单。 - 执行速度:Playwright 通常更快,通信效率更高。 - 自动等待:Playwright 的自动等待机制更智能,减少了编写显式等待(如 WebDriverWait)的需要。 - 生态系统:Selenium 更成熟,社区和资料更庞大;Playwright 是后起之秀,发展迅速,现代特性更多。 ## 五、CI/CD(基于Jenkins) Jenkins必备插件:Allure、git、Pipeline allure全局配置 在Manage Jenkins->全局工具配置,【Allure Commandline 安装】配置allure 创建任务: ```groovy // windows pipeline { agent any // 定义触发器 //triggers {} environment { JAVA_TOOL_OPTIONS = '-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8' CONDA_ENV = "pytest-allure-py310" CONDA_ACTIVATE = "D:\\ProgramData\\Miniconda3\\Scripts\\activate.bat" PROJECT_DIR = "${env.WORKSPACE}" } stages { stage('拉取代码') { steps { git branch: 'main', credentialsId: 'your-git-credentials-id', url: 'https://github.com/your-username/your-repo.git' script { echo "代码拉取完成,当前分支: ${env.GIT_BRANCH}" echo "最新提交: ${env.GIT_COMMIT}" } } } stage('安装依赖') { steps { bat """ call "${CONDA_ACTIVATE}" ${CONDA_ENV} cd "${PROJECT_DIR}" echo "正在安装依赖包..." pip install -r requirements.txt """ } } stage('执行接口测试') { steps { bat """ call "${CONDA_ACTIVATE}" ${CONDA_ENV} cd "${PROJECT_DIR}" echo "开始执行接口测试..." pytest tests/test_suites_api/ -s -q -l --env=dev --alluredir "./allure-results" --clean-alluredir """ } post { failure { echo "接口测试阶段发现失败用例,但将继续生成报告。" } } } } post { always { allure includeProperties: false, jdk: '', results: [[path: 'allure-results']], report: 'allure-report' script { // 获取当前时间并格式化为 yyyyMMddHHmm 格式 def timestamp = new Date().format('yyyyMMddHHmm') def reportFileName = "report_${timestamp}.xlsx" // 将测试结果填入到测试用例中 bat """ call "${CONDA_ACTIVATE}" ${CONDA_ENV} cd "${PROJECT_DIR}" python report_cli.py excel --allure ./allure-results --file "testcase_01.xlsx" --sheet "testcase_01" --report=${reportFileName} """ // 发送邮件 emailext( subject: "构建通知: ${env.JOB_NAME} - Build #${env.BUILD_NUMBER} - ${currentBuild.currentResult}", body: """
构建状态: ${currentBuild.currentResult}
构建编号: ${env.BUILD_NUMBER}
构建日志: 查看详情
在线报告: 浏览报告
报告文件: ${reportFileName} (请见邮件附件)
""", to: 'username@email', mimeType: 'text/html', attachmentsPattern: "${reportFileName}" ) } } success { echo "流水线执行成功!" } failure { echo "流水线执行失败!" } unstable { echo "流水线状态为不稳定。" } } } ``` ```groovy // linux pipeline { agent any // 定义触发器 //triggers {} environment { CONDA_ENV = "pytest-allure-py310" CONDA_PATH = "/opt/miniconda3" PROJECT_DIR = "${env.WORKSPACE}" } stages { stage('拉取代码') { steps { git branch: 'main', credentialsId: 'your-git-credentials-id', url: 'https://github.com/your-username/your-repo.git' script { echo "代码拉取完成,当前分支: ${env.GIT_BRANCH}" echo "最新提交: ${env.GIT_COMMIT}" } } } stage('设置环境') { steps { sh """ source activate ${CONDA_ENV} cd ${PROJECT_DIR} echo "正在安装依赖包..." pip install -r requirements.txt """ } } stage('执行测试') { steps { sh """ source activate ${CONDA_ENV} cd ${PROJECT_DIR} pytest tests/test_suites_api/ -v --env=dev --alluredir="./allure-results" --clean-alluredir """ } } } post { always { allure includeProperties: false, jdk: '', results: [[path: 'allure-results']], report: 'allure-report' script { // 获取当前时间并格式化为 yyyyMMddHHmm 格式 def timestamp = new Date().format('yyyyMMddHHmm') def reportFileName = "report_${timestamp}.xlsx" bat """ call "${CONDA_ACTIVATE}" ${CONDA_ENV} cd "${PROJECT_DIR}" python report_cli.py excel --allure ./allure-results --file "testcase_01.xlsx" --sheet "testcase_01" --report=${reportFileName} """ // 发送邮件 emailext( subject: "构建通知: ${env.JOB_NAME} - Build #${env.BUILD_NUMBER} - ${currentBuild.currentResult}", body: """构建状态: ${currentBuild.currentResult}
构建编号: ${env.BUILD_NUMBER}
构建日志: 查看详情
在线报告: 浏览报告
报告文件: ${reportFileName} (请见邮件附件)
""", to: 'username@email', mimeType: 'text/html', attachmentsPattern: "${reportFileName}" ) } } success { echo "流水线执行成功!" } failure { echo "流水线执行失败!" } unstable { echo "流水线状态为不稳定。" } } } ```