Pytest-Bdd-Playwright 系列教程(1):从零开始教你写自动化测试框架「喂饭教程」
- 前言
- 一、项目结构
- 二、安装依赖
- 三、BDD特性文件
- 四、页面对象
- 五、步骤定义
- 六、测试脚本
- 七、Pytest配置
- 八、运行测试
前言
- 最近收到一些小伙伴在后台的留言,能不能提供相应的自动化测试项目的源码参考下,那么今天就来开始新的一期喂饭教程专栏,教大家如何完整的搭建一个完善的自动化测试框架;
- 我们将逐步讲解从项目结构设计到测试执行的整个过程,帮助大家深入理解自动化测试框架的各个组成部分及其工作原理。
本文教程内容如下:
通过本文内容的学习,你将能够:
- 理解BDD在自动化测试中的应用;
- 掌握Page Object设计模式;
- 学会使用Pytest和Playwright进行Web自动化测试;
- 了解如何组织和管理自动化测试项目;
- 掌握测试报告生成和日志管理技巧。
一、项目结构
│
├── features/ # BDD特性文件
│ └── search.feature # 搜索功能的特性文件
│
├── pages/ # 页面对象
│ └── search_page.py # 搜索页面对象
│
├── steps/ # 步骤定义
│ └── search_steps.py # 搜索相关步骤定义
│
├── tests/ # 测试脚本
│ └── test_search.py
│
├── reports/ # 测试报告(自动生成)
│ ├── logs/ # 日志文件目录(自动生成)
│ │ └── test_log.log # 测试日志文件(自动生成)
│ └── test_report.html # HTML格式的测试报告(自动生成)
│
├── conftest.py # Pytest fixtures和全局配置
├── pytest.ini # Pytest配置文件
├── requirements.txt # 项目依赖
└── README.md # 项目说明文档
二、安装依赖
- 安装 Python
- 项目最低支持 Python 版本: 3.7
- 推荐 Python 版本: 3.8+(我自己安装的是3.11.9)
- 创建
requirements.txt
文件,包含以下依赖:
pytest==7.3.1
pytest-bdd==7.3.0
playwright==1.48.0
pytest-html==4.1.1
- 使用以下命令安装依赖:
pip install -r requirements.txt
- 下载Playwright浏览器驱动
playwright install
三、BDD特性文件
在features/search.feature
中编写BDD场景:
Feature: 百度搜索作为用户我想要能够在百度上搜索信息以便找到相关的信息Background:Given 我在百度搜索页面Scenario Outline: 成功搜索When 我输入搜索词 "<search_term>"And 点击搜索按钮Then 我应该看到搜索结果Examples:| search_term || python |Scenario: 失败搜索When 我输入空的搜索词And 点击搜索按钮Then 我应该看到搜索结果
BDD特性文件(Feature File)的写法说明如下:
BDD特性文件(Feature File):BDD特性文件使用Gherkin语言编写,用于描述系统的行为。
主要包含以下几个部分:
-
Feature(特性):每个.feature文件以Feature:关键字开头,后面跟特性名称,可以在Feature下添加描述;
-
Background(背景):用于定义在每个场景之前都需要执行的步骤;
-
Scenario(场景):用于描述具体的测试场景;
-
Scenario Outline(场景大纲):用于定义参数化的场景
-
步骤关键字:
Given: 描述前置条件
When: 描述用户的操作
Then: 描述预期结果
And: 用于连接同类型的步骤
But: 用于表示例外情况
使用说明如下:
文件命名: 特性文件以.feature为后缀,如search.feature
文件位置: 放在项目的features/目录下
语言: 可以使用自然语言编写,便于非技术人员理解
复用: 相同的步骤可以在不同的场景中重复使用
标签: 可以使用@标签来标记场景,如@smoke、@regression等
注释: 使用#添加注释
四、页面对象
页面对象模式是一种常用的设计模式,用于将页面元素和操作封装到单独的类中,以提高代码的可维护性和复用性。
在pages/search_page.py
中创建SearchPage
类:
import logging
from playwright.sync_api import Page, expectlogging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)class SearchPage:def __init__(self, page: Page):self.page = pageself.search_input = page.locator("#kw")self.search_button = page.locator("#su")self.search_results = page.locator("a.sc-link")def navigate(self, url: str):self.page.goto(url)log.info(f"跳转至 {url}")def search(self, input_value: str):self.search_input.fill(input_value)def click_search_button(self):self.search_button.click()def assert_search_results_visible(self):expect(self.search_results).to_be_visible()
五、步骤定义
使用这个步骤定义文件,pytest-bdd会自动将feature文件中的步骤与这里定义的函数关联起来。在运行测试时,会按照场景中的步骤顺序依次调用对应的函数。
在steps/search_steps.py
中实现步骤定义:
from pytest_bdd import given, when, then, parsers
from pytest_bdd.parsers import stringfrom pages.search_page import SearchPage
from pytest import fixture@fixture(scope="function")
def search_page(page):search_page = SearchPage(page)yield search_page@given('我在百度搜索页面')
def navigate_to_search_page(search_page):search_page.navigate("")@when(parsers.parse('我输入搜索词 "{search_term}"'))
def enter_search_term(search_page, search_term: string):search_page.search(search_term)@when('我输入空的搜索词')
def enter_empty_search_term(search_page):search_page.search("")@when('点击搜索按钮')
def click_search_button(search_page):search_page.click_search_button()@then('我应该看到搜索结果')
def see_search_results(search_page):search_page.assert_search_results_visible()
六、测试脚本
在tests/test_search.py
中编写测试脚本:
import pytest
from steps.search_steps import *
from pytest_bdd import scenario@pytest.mark.smoke
@scenario('search.feature', '成功搜索')
def test_successful_search():"""这里可以添加额外的测试逻辑,比如:- 添加详细的日志记录- 截图保存- 额外的断言检查- 测试数据清理等"""pass@pytest.mark.low
@scenario('search.feature', '失败搜索')
def test_failed_search():pass
通过这种方式,我们将BDD场景与实际的测试执行关联起来,让测试更加结构化和易于理解。同时,通过使用标记,我们可以灵活地组织和运行测试套件。
七、Pytest配置
在conftest.py
中配置Pytest和Playwright:
import pytest
import logging
from playwright.sync_api import sync_playwrightlog = logging.getLogger(__name__)@pytest.fixture(scope="function")
def playwright():with sync_playwright() as playwright:yield playwright@pytest.fixture(scope="function")
def browser_type(playwright):return playwright.chromium@pytest.fixture(scope="function")
def browser(browser_type):browser = browser_type.launch(headless=False)log.info("启动浏览器")yield browserbrowser.close()@pytest.fixture(scope="function")
def page(browser):page = browser.new_page()yield pagepage.close()log.info("页面关闭")
在pytest.ini
中配置Pytest:
[pytest]
# 指定BDD特性文件的基础目录
bdd_features_base_dir = features/# 添加命令行选项
addopts =# 生成HTML测试报告--html=reports/test_report.html# 定义自定义标记
markers =smoke: 'mark test cases for smoke'low: 'mark test cases for low'# 配置控制台日志
log_cli = true
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S# 配置文件日志
log_file = reports/logs/test_log.log
log_file_level = INFO
log_file_date_format = %Y-%m-%d %H:%M:%S
log_file_format = %(asctime)s %(levelname)s %(message)s
八、运行测试
# 运行所有测试
pytest
# 运行特定标记的测试
pytest -m smoke
运行结果如下:
- 生成HTML报告: 报告将自动生成在reports目录下;
- 查看详细日志: 控制台会显示INFO级别的日志,同时日志也会写入到指定的文件中。