百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

自动化测试框架 pytest 自动化测试框架搭建思路

zhezhongyun 2024-12-15 17:54 53 浏览

对我来说 pytest 可以说是 Python 语言中我最喜欢的测试框架了,它功能特别强大,却又简单易上手,支持许多的插件可以扩展额外的功能。这篇文章来单独介绍下 pytest 的使用。

目录

  1. 安装
  2. 用例编写
  3. 测试执行(命令行及程序化执行、运行参数介绍)
  4. conftest.py 文件介绍(包括 fixture 的使用)

安装

pip install pytest

用例编写

只有满足以下条件才会被识别为 pytest 用例:

  • 文件名需要以 test_ 开头或 _test 结尾
  • 测试函数或方法需要以 test_ 开头
  • 如果要把测试用例放在类中,测试类需要以 Test 开头

示例:

文件 test_example.py

def test_of_example():
    text = "example"
    assert len(text) == 7
    
    
class TestAdd:
    def test_of_add(self):
        result = 1 + 1
        assert result == 2

具体的测试用例写起来很简单,不重点介绍了,今天要重点介绍的是下面的内容。

测试执行

命令行运行

如果要运行项目所有的测试用例,可以直接在命令行运行 pytest,如果要运行指定的文件则在 pytest 后直接加测试文件路径即可,路径后还可以用“::”连接测试类和测试方法或函数来直接指定特定的测试类或测试用例运行。比如要运行上面示例代码的 test_of_add 测试用例,可以这样运行:

pytest test_example.py::TestAdd::test_of_add

程序化运行

pytest 提供了程序化执行测试的入口 pytest.main(),执行效果和命令行运行几乎没有区别。pytest.main() 可以将参数以列表的形式传入,比如要通过程序化运行的方式指定测试用例可以这样写:

pytest.main(["test_example.py::TestAdd::test_of_add"])

运行参数

下面列举一些常用的 pytest 运行参数

参数

参数描述

-v

打印详细的运行日志。加上此参数终端会打印每条用例的运行结果

-s

打印控制台输出内容。带上此参数运行时才会打印代码中 print() 输出语句

-m

运行打了指定标记的用例。每条测试用例或测试类都可以用 @pytest.mark.xxx 的方式来打标记,然后可以使用 pytest -m xxx 的方式来运行打了标记的用例。支持使用 and(与)、or(或)、not(非) 来筛选用例

--lf

运行上次失败的用例

--ff

先运行上次失败的用例,再运行其它用例

--reruns

失败重跑。需安装 pytest-rerunfailures 插件,后面跟需重试的次数。可以另外跟 --reruns_delay 参数设置重试之前等待秒数

--html

生成 html 测试报告。需安装 pytest-html 插件,后面跟测试报告存放的路径。可以另外跟 --self-contained-html 参数来生成单独的 html 报告,html 样式等文件不另外存放

pytest.ini 配置文件

pytest.ini 配置文件可以用来存放测试运行时比较固定的一些参数等内容。

pytest.ini 文件需放在项目根目录。

pytest.ini 比较常见的配置内容:

# pytest.ini
[pytest]
markers:
    example: 测试用例示例
    add: 加法
    
testpaths:
    testcases/

addopts:
    -s
    -v
    --lf
    --capture=fd
    --self-contained-html

上面配置文件中,markers 配置了测试用例标记,如果测试用例进行了标记此处没有列出的话,运行测试时会有警告错误,可以添加 filterwarnings: ignore::UserWarning 忽略警告错误。testpaths 可以指定测试用例路径,如果指定了测试用例路径,运行时不需要再指定测试文件路径。addopts 可以配置命令行参数,此处配置了命令行参数后,运行的时候不需再额外传参数,如果运行时也传有参数,则会取两者的合集。

重点内容——conftest.py 文件

conftest.py 文件是一个很神奇的文件,它可以极大地方便你的测试用例编写,简化你的自动化测试流程。先说下它的一些特点:

  • 命名固定,不可随意更改
  • 作用域为其所在的整个文件夹,包括子文件夹。所以当其存在于根目录时,它可以作用于整个项目
  • 可以存在多个 conftest.py 文件,但每个文件夹只能存在唯一一个
  • conftest.py 不能被其它文件导入,在代码运行时 pytest 会自动导入,并在文件夹内其它文件运行之前运行

conftest.py 主要是和 fixture 结合来使用,一般用法就是在 conftest.py 文件内存放 fixture 函数,然后在测试文件内调用,来实现测试环境的准备或清理等操作。当 conftest.py 存在于根目录时,里面的 fixture 函数可以被整个项目的文件调用。下面我们需要先简单介绍下 fixture。

@pytest.fixture()

当一个函数使用 @pytest.fixture() 装饰之后,这个函数就是 fixture 函数,它可以用来执行一些测试用例初始环境配置或测试环境清理的工作,类似 unittest 的 setup 和 teardwon 的功能。它可以设置作用范围,可设置的作用范围有 session(会话级别,整次测试执行一次)、module(模块级别,调用该函数的整个测试文件运行之前执行一次)、class(类级别,整个类运行一次)和 function(函数/方法级别,默认,每个函数或方法都会调用一次)。

当我们要使用 fixture 函数时,可以直接将它函数或方法名作为参数传入,也可以使用 @pytest.mark.usefixtures('fixture_name') 装饰器,还可以直接使用 @pytest.fixture(autouse=True) 自动使用。

下面上代码示例:

# conftest.py 文件
import pytest


@pytest.fixture()
def my_function_fixture():
    print("测试开始")
    yield
    print("测试结束")


@pytest.fixture(scope="session", autouse=True)
def my_session_fixture():
    print("整个测试开始")
    yield
    print("整个测试结束")

#====================================================#
# example_test.py 文件
import pytest


@pytest.mark.usefixtures("my_function_fixture")
def test_of_example():
    text = "example"
    assert len(text) == 7


class TestAdd:
    def test_of_add(self, my_function_fixture):
        result = 1 + 1
        assert result == 2

上面代码运行 pytest -s -v 之后会输出以下内容

testcases/example_test.py::test_of_example 整个测试开始
测试开始
PASSED测试结束

testcases/example_test.py::TestAdd::test_of_add 测试开始
PASSED测试结束
整个测试结束

可以看到作用范围为 session 的 my_session_fixture 只在整个测试运行之前和之后执行了一次,作用范围为 function 的 my_function_fixture 在两个用例运行之前和之后都分别执行了一次。

yield 在 fixture 函数内起到了 return 的作用,但是它更大的作用是分割了测试执行之前和之后的代码,如示例的运行结果,yield之前的代码会在作用范围的代码运行之前执行,yield 之后的代码会在作用范围的代码运行之后执行,所以 fixture 函数可以实现类似 setup 和 teardown 的作用。

conftest.py 和 fixture 结合来实现 UI 自动化特别方便,可以使用 fixture 来实现测试之前手机连接,测试应用的安装等操作,还可以实现每条用例都重启应用,以保证每条用例都不受上一条用例的影响等。

下一篇文章会结合 pytest 和 uiautomator2 来完整地实现一个 UI 自动化项目。

相关推荐

Excel高效技巧:批量合并重复数据的实用指南

在日常数据处理中,我们常会遇到需要合并相邻重复单元格的场景。无论是整理分类标签、统计重复项还是优化报表格式,手动逐个合并不仅耗时且容易出错。本文将详细介绍三种专业高效的批量合并方法,助您轻松应对各种复...

自主研发高速动车组列车又添新成员(新时代画卷)

数据来源:国铁集团">数据来源:国铁集团CR400AF—S型列车驶过重庆。龙帆摄(人民视觉)">CR400AF—S型列车驶过重庆。龙帆摄(人民视觉)CR400BF—GZ型列车行驶在京...

福彩双色球幻圆图的VBA程序(第一部分)

很多朋友喜欢玩福彩双色球彩票,都知道下面的这张图——福彩双色球红球幻圆图和篮球幻方图。图2是福彩双色球2024104期(红色)和2024105期(黄色)的幻圆图。图3是福彩双色球2024105期(红色...

技巧 | 往MCP服务器添加提示词模板

在我的上一篇文章[1]中,我已经构建了一个本地MCP服务器并向其添加了一些工具。在本文中,我们将向该MCP服务器添加提示词。这是如同上一篇博客的文件结构。但在这里,我为此创建了两个新文件。.├──...

Avalonia日志组件实现与优化指南

背景Avalonia目前没有富文本框可实现日志输出显示,但提供了SelectableTextBlock控件可以替换,这是站长实现的一个日志组件效果:可展示日志时间、日志级别、日志详细内容等,后台除输...

vim编辑器最后几行@代表什么意思

使用vim编辑文本时,屏幕下方会出现一些@符号,这些符号代表什么意思?当vim设置了wrap属性时,若一行太长则就会发生折行现象,此时一个逻辑行就会显示多个屏幕行,如下图由于文件的第2行太长,一个真实...

浅色AI云食堂APP完整代码(二)

以下是整合后的浅色AI云食堂APP完整代码,包含后端核心功能、前端界面以及优化增强功能。项目采用Django框架开发,支持库存管理、订单处理、财务管理等核心功能,并包含库存预警、数据导出、权限管理等增...

QML控件:TextInput, TextField, TextEdit, TextArea用法及自定义

本文主要介绍基本元素TextInput,TextField,TextEdit,TextArea等的基本属性。Textlnput与TextField为行编辑控件,TextEdit与T...

WPF - 10.特殊容器控件

摘要这里我们要介绍的特殊容器空间是ScrollViewer,该控件与其他控件不同的是,可以支持滚动显示容器内的元素。下面我们举例说明如何在WPF中使用ScrollViewer控件。新建一个WPF程...

rhino6.0 python中ETO的组件案例

1.按钮组件按钮几乎放置在每个对话框上。创建一个新的按钮很简单。使用forms.Button并指定Text显示在按钮面上。除了创建新按钮外,通常还通过.Click事件附加一个操作。使用+=语法,如下...

Rhino6.0 窗口开发使用角本说明

第1个:生成窗口代码第2点:Eto界面主要由Dialog(主程序界面)、Layout(界面布局)和Controls(控件)三个部分构成,逻辑简单且清晰。这个脚本被分为三个主要部分。该import...

手把手教你搭建属于自己的服务器!

最近总是想搭建自己的网站,奈何皮夹里空空如也,服务器也租不起,更别说域名了。于是我就寻思能否自己搭建个服务器,还不要钱呢?还真行!!!经过几天的冲浪,我发现有两个免费的建站工具:Apache和Ng...

HEAT杂志《欧美猛男》排行!“雷神”居然没进前三!

提到猛男的必备条件,应该就是要有着让人看了会流口水的大块肌肉,而一说到猛男,小编第一个想到的就是spanstyle="text-transform:none;background-color:...

Power Query 表格列历遍函数Table.TransformColumns函数

PowerQuery提取数字应该是非常方便的,EH有这样一道题:一看到这题首先想的是PowerQuery,可能中毒有点深,思路挺简单的,PowerQuery有一个从数字到非数字的分列分列后再提取...

自学前端踩了30个坑,终于整理出这份新手避坑指南

这是我在自学前端的第37天,对着一个简单的HTML页面卡了整整一下午。不是逻辑错误,不是语法问题,只是我不知道为什么,一个div死活居中不了。那时候的我,以为前端就是写写页面、调调样式,直到后来才...