Pytest-Bdd-Playwright 系列教程(3):支持测试用例并行执行

前言

  • 在串行的测试执行中,每个测试用例都会依次执行,这在测试用例数量较多或者单个测试用例执行时间较长时,会导致整体测试周期延长;
  • 测试用例的并行执行是一个提高测试效率的重要手段。通过并行执行,我们可以同时运行多个测试,从而减少整体的测试时间。

一、Pytest 的并行执行机制

Pytest 提供了 pytest-xdist 插件来实现测试用例的并行执行。这个插件的主要功能是将测试用例分发到多个 CPU 核心或通过网络跨多台机器运行测试,从而提升测试的运行效率。

二、在框架中集成 xdist 插件

通过以下命令安装:

pip install pytest-xdist

pytest-xdist 提供的多个命令行参数如下

-n--numprocesses:并发执行的进程数 / 线程数;
--dist:定义并发模式;(选项:loadscope、 loadfile、 loadclass、 loadmodule、each
--tx--executor:定义使用的执行器。(选项:thread、process、 forked、subprocess

三 、修改pytest.ini文件配置

pytest.ini 文件中,添加 pytest-xdist 的命令行参数。这里,我们用到了命令行参数 -n

[pytest]
# 指定BDD特性文件的基础目录
bdd_features_base_dir = features/

# 添加命令行选项
addopts =
    #2 是你希望使用的进程数
    -n 2
	# 生成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

注:在 -n 的后面可以是数字,也可以是字母 auto,后者表示 pytest 自动检测 CPU 的核心数并启动相应数量的进程。

为了解决并发执行时的文件访问冲突问题,我们先把日志记录到文件的相关配置项删除。为每条测试用例分别生成唯一的日志文件名的功能,在后续文章会有相应教学。)

四、修改 conftest.py 以支持并行执行

使用并行执行测试时,测试用例的执行顺序可能会与单线程执行时不同,因为测试用例是在不同的线程中并行执行的。
如果测试用例之间存在依赖关系,或者需要共享某些状态,那么并行执行可能会导致问题。这意味着每个进程,都需要能够独立地设置和清理测试环境。因此,需要修改 conftest.py 文件中的 fixture 来支持这种方式。
所以,我们需要确保每个fixture都是线程安全的,并且不会在不同的测试用例之间共享状态。
例如,我们可以为每个测试用例创建独立的浏览器实例

# conftest.py
import pytest
import logging

from pathlib import Path
from utils.config import Config
from playwright.sync_api import sync_playwright

log = logging.getLogger(__name__)
root_path = Path(__file__).resolve().parent

def pytest_addoption(parser):
    parser.addoption("--browser", action="store", default="chromium", help="要使用的浏览器: chromium, firefox, or webkit")
    parser.addoption("--headless", action="store_true", default=False, help="运行浏览器无头模式")
    parser.addoption("--env", action="store", default=Config.DEFAULT_ENV, help="要测试的环境: test, staging, or prod")

@pytest.fixture(scope="function")
def playwright():
    with sync_playwright() as playwright:
        yield playwright

@pytest.fixture(scope="function")
def browser_type(playwright, request):
    browser_name = request.config.getoption("--browser")
    if browser_name == "chromium":
        return playwright.chromium
    elif browser_name == "firefox":
        return playwright.firefox
    elif browser_name == "webkit":
        return playwright.webkit
    else:
        raise ValueError(f"不支持的浏览器: {
      
      browser_name}")

@pytest.fixture(scope="function")
def browser(browser_type, request):
    headless = request.config.getoption("--headless")
    browser = browser_type.launch(headless=headless)
    log.info(f"启动浏览器: {
      
      browser_type.name}, 无头模式: {
      
      headless}")
    yield browser
    browser.close()

@pytest.fixture(scope="function")
def base_url(request):
    env = request.config.getoption("--env")
    if env not in Config.ENVIRONMENTS:
        raise ValueError(f"不支持的环境: {
      
      env}")
    return Config.ENVIRONMENTS[env]

@pytest.fixture(scope="function")
def page(browser):
    page = browser.new_page()
    yield page
    page.close()

Pytest 中不同作用域的 fixture 的简要说明如下

  • function:每个测试函数都会调用这个 fixture,每次调用都会生成一个新的实例;
  • class:每个测试类都会共享同一个 fixture 实例,该实例在类中所有测试方法之前被创建;
  • module:每个模块(Python 文件)都会共享同一个 fixture 实例。在并行测试中,每个进程都会得到自己的 module 实例;
  • session:整个测试会话中只创建一次 fixture 实例,所有测试都会共享这个实例。

conftest.py 文件中,我们将 playwrightbrowser 的作用域设置为 function,这意味着每个测试函数都会创建自己的浏览器实例,确保并行执行时的隔离性。

五、运行并行测试

现在,我们已经配置好了并行执行的环境,通过以下命令来运行并行测试:

pytest

运行结果如下:
在这里插入图片描述

注意事项

  • 资源消耗:并行执行会增加系统的资源消耗,特别是内存和CPU。确保你的测试环境有足够的资源来支持并行执行;
  • 测试隔离性:确保每个测试用例都是独立的,不会相互影响;
  • 日志记录:在并行执行时,日志记录至关重要,它可以帮助你追踪每个测试用例的执行情况。

总结

通过使用 pytest-xdist 插件,可以在我们的自动化测试框架中,实现测试用例的并行执行。通过并行执行,我们可以缩短测试周期,更快地发现和修复缺陷。
在下一篇文章中,我们将继续探讨如何进一步优化我们的自动化测试框架,敬请期待!

猜你喜欢

转载自blog.csdn.net/weixin_48321392/article/details/143256815