pytest

pytest 库及相关组件安装

pytest 单元测试
pytest-html 生成html测试报告
pytest-xdist 测试用例多线程执行
pytest-ordering 改变用例执行顺序
pytest-rerunfailures 用例失败重跑
allure-pytest 生成测试报告
pip install 安装即可

默认规则

  • 模块名以test_开头或者_test结尾
  • 测试类以Test开头,并且不能有init方法
  • 测试用例以test开头

示例:
test_login.py

class TestLogin():

    def test_login(self):
        print("测试用例执行。。。。。")

1.运行方式

1.1 主函数运行方式

#运行所有
pytest.main()

#指定模块运行
pytest.main(['test_login.py'])

#指定目录运行
pytest.main(["./testcase"])

1.2 命令行方式运行

#运行所有
pytest

#指定模块运行
pytest test_login.py

#指定目录运行
pytest ./testcase

1.3 命令行及主函数运行参数详解

  • -s: 表示输出调试信息
  • -v: 显示更详细的信息
  • -n: 支持多线程运行用例,
  • -x:只要一个用例报错,测试就会停止
  • -k: 根据测试用例的字符串模糊匹配用例执行
  • -maxfail={n}: 用例失败n次,测试停止
  • -reruns={n}: 用例失败重跑
  • --html {filename}: 生成html方式的测试报告, filename表示生成报告的路径及文件名
#命令行方式:
pytest -vs ./testcase --reruns 2

#主函数方式:
pytest.main(["-vs", "./testcase", "--reruns=2"])

1.4 pytest.ini运行配置文件

  • 一般放在项目的根目录
  • 文件编码必须是ANSI编码
  • 主函数或者命令行方式运行,都会去读取这个配置文件,按配置文件的规则执行用例
    addopts: 运行时添加的参数如 -v -s
    testpaths: 运行测试用例的路径
    python_files: 匹配测试模块名的规则
    python_classes: 匹配测试类的规则
    python_functions: 匹配方法名的规则
    log_cli: 是否开启控制台打印日志
    log_cli_level: 日志级别
    log_format: 日志格式
    配置文件:
[pytest]
log_cli = true
log_cli_level = INFO
log_format = %(message)s

addopts=-vs
testpaths=./testcase/tag
python_files=*Test.py
python_classes=*Test
python_functions=*test

用例:

class GetTagTest:

    def get_all_test(self):
        print("\n执行用例: 获取所有标签......")

    def get_tag(self):
        print("\n执行用例: 获取单个标签......")

根据以上规则执行:

./testcase/tag 路径下的用例以*Test.py结尾的用例模块

以*Test结尾的类名

以*test结尾的用例名

符合以上条件的用例将会被执行

pytest timeout设置 pytest运行流程_pytest timeout设置

1.5 给用例打上标签,指定运行标签关联的用例

使用装饰器给修饰在用例上,表示给此用例打上标签,如:
@pytest.mark.read
@pytest.mark.后的命名可自定义

代码:

@pytest.mark.read
    def test_login2(self):
        print("\npytest测试用例执行。。。。。")

pytest.ini配置文件需要添加以下参数:

markers =
    read: 只读用例
    write: 写用例

用例:

# -*- coding:utf-8 -*-
import pytest


class TagTest:

    @pytest.mark.read
    def get_all_test(self):
        print("\n执行用例: 获取所有标签......")

    @pytest.mark.read
    def get_tag_test(self):
        print("\n执行用例: 获取单个标签......")

    @pytest.mark.wirte
    def create_tag_test(self):
        print("\n执行用例: 创建单个标签......")

执行用例命令:

pytest -m "read"

执行结果:

可以查看到3个用例,只有打上read标签的用例被执行

pytest timeout设置 pytest运行流程_pytest timeout设置_02

如果多个标签只需要加上or关键字连接即可,如:

pytest -m "read or write"

pytest timeout设置 pytest运行流程_python_03

2.执行顺序

默认是按用例从上至下的方式执行

可用装饰器在用例上修饰:
@pytest.mark.run 装饰器参数order 表示用例的优先级
如果存在多个用例,只有部分用例使用装饰器,那么优先执行带有装饰器的用例,其他没有使用装饰器的用例按默认顺序执行;

@pytest.mark.run(order=1)
    def test_login2(self):
        print("\npytest测试用例执行。。。。。")

3. 断言

3.1 assert关键字进行断言

assert关键字后,接收一个表达式,以及描述字段
表达式为True断言成功:

class GetTagTest:

    def get_tag_test(self):
        print("\n执行用例: 获取所有标签......")
        assert 1 == 1, "获取标签失败"

执行结果:

pytest timeout设置 pytest运行流程_python_04

表达式为False断言失败, 会打印出后面描述字段

class GetTagTest:

    def get_tag_test(self):
        print("\n执行用例: 获取所有标签......")
        assert 1 == 2, "获取标签失败"

pytest timeout设置 pytest运行流程_用例_05

3.2 异常断言pytest.raises

关于异常断言建议使用pytest.raises 如下示例:

def create_tag_test(self):
        self.log_info("\n执行用例: 创建单个标签......")
        with pytest.raises(RuntimeError) as excinfo:
            def f():
                f()

            f()
        assert "maximum recursion" in str(excinfo.value)

4. 用例过滤

使用pytest的装饰器修饰在用例或者类上进行过滤用例

1.@pytest.mark.skip

skip:接收一个字符串参数reason,描述用例不执行原因

@pytest.mark.skip(reason="此用例不执行")
    def test_a01(self):
        print("执行test_a01。。。。。。")

执行结果:

pytest timeout设置 pytest运行流程_pytest timeout设置_06

2.@pytest.mark.skipIf

skipIf:接收两个参数
参数1: 接收一个条件表达式, 条件为True时用例不执行
参数2: 接收一个字符串参数reason, 描述用例不执行原因

@pytest.mark.skipif(1 == 1, reason="此用例不执行")
    def test_login2(self):
        print("\npytest测试用例执行。。。。。")

执行结果:

pytest timeout设置 pytest运行流程_测试用例_07