pytest 测试实战 - 进阶篇

目录

  • Fixture 高级用法
  • pytest 插件应用
  • pytest 配置(pytest.ini)
  • allure 生成测试报告

Fixture 用法

Fixture 特点及优势

  • 1、命令灵活:对于 setup,teardown,可以不起这两个名字
  • 2、数据共享:在 conftest.py 配置⾥写⽅法可以实现数据共享,不需要 import 导⼊。可以跨⽂件共享
  • 3、scope 的层次及神奇的 yield 组合相当于各种 setup 和 teardown

Fixture 在自动化中的应用 1

  • 场景:

测试⽤例执⾏时,有的⽤例需要登陆才能执⾏,有些⽤例不需要登陆。

setup 和 teardown ⽆法满⾜。fixture 可以。默认 scope(范围)function

  • 步骤:
    • 1.导⼊ pytest
    • 2.在登陆的函数上⾯加@pytest.fixture()
    • 3.在要使⽤的测试⽅法中传⼊(登陆函数名称),就先登陆
    • 4.不传⼊的就不登陆直接执⾏测试⽅法。

Fixture 在自动化中的应用 2

  • 场景:

你与其他测试⼯程师合作⼀起开发时,公共的模块要在不同⽂件中,要在⼤家都访问到的地⽅。

  • 解决:

使⽤ conftest.py 这个⽂件进⾏数据共享,并且他可以放在不同位置起着不同的范围共享作⽤。

  • 前提:

    • conftest ⽂件名是不能换的
    • 放在项⽬下是全局的数据共享的地⽅
  • 执⾏:

    • 系统执⾏到参数 login 时先从本模块中查找是否有这个名字的变量什么的,
    • 之后在 conftest.py 中找是否有。
  • 步骤:

将登陆模块带@pytest.fixture 写在 conftest.py

Fixture 在自动化中的应用 3

场景:

不想原测试⽅法有任何改动,或全部都⾃动实现⾃动应⽤,

没特例,也都不需要返回值时可以选择⾃动应⽤

解决:

使⽤ fixture 中参数 autouse=True 实现

步骤:

在⽅法上⾯加 @pytest.fixture(autouse=True)

Fixture 在自动化中的应用 4

场景:

你已经可以将测试⽅法前要执⾏的或依赖的解决了,

测试⽅法后销毁清除数据的要如何进⾏呢?

范围是模块级别的。类似 setupClass

解决:

通过在同⼀模块中加⼊ yield 关键字,yield 是调⽤第⼀次返回结果,

第⼆次执⾏它下⾯的语句返回。

步骤:

在@pytest.fixture(scope=module)。在登陆的⽅法中加 yield,之后加销毁清除的步骤

Fixture 在自动化中的应用 5

取值 范围 说明
function 函数级 每一个函数或方法都会调用
class 类级别 每个测试类只运行一次
module 模块级 每一个.py文件调用一次
session 会话级 每次会话只需要运行一次,会话内所有方法及类,模块都共享这个方法

Fixture 在自动化中的应用 6

场景:

测试离不开数据,为了数据灵活,⼀般数据都是通过参数传的

解决:

fixture 通过固定参数 request 传递

步骤:

在 fixture 中增加@pytest.fixture(params=[1, 2, 3, ‘linda’])

在⽅法参数写 request,方法体里面使用 request.param 接收参数

Fixture的用法总结

  • 模拟setup,teardown(一个用例可以引用多个fixture)
  • yield 的用法
  • 作用域( session,module, 类级别,方法级别 )
  • 自动执行 (autouse 参数)
  • conftest.py用法,一般会把fixture写在conftest.py 文件中(这个文件名字是固定的,不能改)
  • 实现参数化

Pytest 实用的插件介绍

pytest 常用的插件

pip install pytest-ordering  控制用例的执行顺序(重点)
pip install pytest-xdist    分布式并发执行测试用例(重点)
pip install pytest-dependency   控制用例的依赖关系 (了解)
pip install pytest-rerunfailures   失败重跑(了解)
pip install pytest-assume          多重较验(了解)
pip install pytest-random-order  用例随机执行(了解)
pip install pytest-html            测试报告(了解)

pytest 执行顺序控制

场景:

对于集成测试,经常会有上下文依赖关系的测试用例。

比如 10 个步骤,拆成 10 条 case,这时候能知道到底执行到哪步报错。

用例默认执行顺序:自上而下执行

解决:

可以通过 setup,teardown 和 fixture 来解决。也可以使用对应的插件。

安装:pip install pytest-ordering

用法:@pytest.mark.run(order=2)

注意:多个插件装饰器(>2)的时候,有可能会发生冲突

Pytest 多线程并行与分布式执行

场景 1:

测试用例 1000 条,一个用例执行 1 钟,一个测试人员执行需要 1000 分 钟。

通常我们会用人力成本换取时间成本,加几个人一起执行,时间就会 缩短。

如果 10 人一起执行只需要 100 分钟,这就是一种布式场景。

场景 2:

假设有个报名系统,对报名总数统计,数据同时进行修改操作的时候有可能出现问题,

需要模拟这个场景,需要多用户并发请求数据。

解决:

使用分布式并发执行测试用例。分布式插件:pytest-xdist

安装及运行: pip install pytest-xdist

注意: 用例多的时候效果明显,多进程并发执行,同时支持 allure

分布式执行测试用例原则

  • 用例之间是独立的,不要有依赖关系
  • 用例执行没有顺序,随机顺序都能正常执行
  • 每个用例都能重复运行,运行结果不会影响其他用例

Pytest 执行-失败重新运行

场景:

测试失败后要重新运行 n 次,要在重新运行之间添加延迟时间, 间隔 n 秒再运行。

安装: pip install pytest-rerunfailures

执行:

pytest -vs --reruns 3 test_class.py
pytest -vs --reruns 5 --reruns-delay 1

@pytest.mark.flaky(reruns=5, reruns_delay=2) 用例的装饰器,指定这个用例rerun5次,每次延时2秒 

注意:

  • 1、失败的 fixture 与 setup_class 也会被执行
  • 2、不要与 setup_class,setup_module 方法使用

Pytest 执行-支持多断言

场景:

一个方法中写多条断言,通常第一条过不去,下面就不执行了。

我们想报错也都执行一下。

安装: pip install pytest-assume

执行:

pytest.assume(1==4)
pytest.assume(2==4)

pytest 用例信赖

场景:

比如用例 A(添加购物车),用例 B(去结算)

如果测试用例 A 运行失败了,执行用例 B 的时候可能也会失败,而且也没有必要运行。

设置用例间依赖关系一旦 A 失败,B 也不会被执行。

解决:

https://pytest-dependency.readthedocs.io/en/latest/usage.html#basic-usage

安装:

pip install pytest-dependency

用法:

@pytest.mark.dependency(name='cart')
@pytest.mark.dependency(depends=["cart"])

Pytest 编写自己的插件-编码

含有中文的测试用例名称,改写编码格式:

item.name = item.name.encode('utf-8').decode('unicode-escape')
item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

pytest 配置

pytest.ini

https://ceshiren.com/t/topic/13105

Allure生成测试报告

Allure

提前准备环境:Java1.8

Allure2 解析过程:

  • 1.安装 allure2 (信赖Java1.8)

下载地址:

https://repo1.maven.org/maven2/io/qameta/allure/allure-commandline/

  • 2.安装 allure-pytest 命令:pip install allure-pytest
  • 3.生成 allure 测试结果 :pytest --alluredir=./report/
  • 4.展示报告:allure serve ./report
  • 5.生成最终版本的报告: allure generate ./report