pytest框架

pytest框架

pytest是Python的单元测试框架,同自带的unittest框架类似,但pytest框架使用起来更简洁,效率更高。

pytest特点

  • 入门简单易上手,文档支持较好。

  • 支持单元测试和功能测试。

  • 支持参数化。

  • 可以跳过指定用例,或对某些预期失败的case标记成失败。

  • 支持重复执行失败的case。

  • 支持运行由unittest编写的测试用例。

  • 有很多第三方插件,并且可自定义扩展。

  • 方便和支持集成工具进行集成。

    安装

    pip install pytest

演示脚本的目录中:

d:\py_tests\ # 我的是d盘的 py_tests 目录,所有操作都在 py_tests 目录内完成
    ├─scripts   
    │  ├─test_case_dir1
    │  │  ├─test_case_02.py    # 用例脚本文件
    │  │  └─__init__.py
    │  ├─test_allure_case.py   # 脚本文件
    │  ├─test_case_01.py   # 脚本文件
    │  └─__init__.py
    ├─report
    │  ├─report.html   # pytest-html生成的用例报告
    │  ├─assets  # allure的依赖目录
    │  ├─result  # allure生成的用例数据
    │  └─allure_html   # allure生成的用例报告目录
    |     └─index.html  # allure生成的最终的html类型的测试报告  
    ├─case_set.py
    ├─demo0.py   # 用例脚本文件
    ├─demo1.py   # 用例脚本文件
    ├─pytest.ini  # 配置文件
    └─__init__.py

简单示例

demo1.py

import pytest

def test_case01():
    print('执行用例01.......')
    assert 0  # 断言失败

def test_case02():
    print('执行用例02.......')
    assert 1  # 断言成功
    
def custom_case03():
    print('执行用例03.......')
    assert 1  # 断言成功
    
if __name__ == '__main__':
    pytest.main(["-s", "demo1.py"])
    # pytest.main("-s demo1.py")

上例中,当我们在执行(就像Python解释器执行普通的Python脚本一样)测试用例的时候,pytest.main(["-s", "demo1.py"])中的传参需要是一个元组或者列表(我的pytest是5.2.2版本),之前的版本可能需要这么调用pytest.main("-s demo1.py"),传的参数是str的形式,至于你使用哪种,取决于报不报错:

TypeError: `args` parameter expected to be a list or tuple of strings, got: '-s demo1.py' (type: <class 'str'>)

遇到上述报错,就是参数需要一个列表或者元组的形式,而我们使用的是str形式。

上述代码正确的执行结果是这样的:

===================================================== test session starts ======================================================
platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: d:\py_tests
collected 2 items                                                                                                               

demo1.py 执行用例01.......
F执行用例02.......
.

=========================================================== FAILURES ===========================================================
_________________________________________________________ test_case01 __________________________________________________________

    def test_case01():
        print('执行用例01.......')
>       assert 0  # 断言失败
E       assert 0

demo1.py:11: AssertionError
================================================= 1 failed, 1 passed in 0.13s ==================================================

大致的信息就是告诉我们:

  • collected 2 items:本次执行中,收集了2个用例。
  • 完了开始执行用例,.表示执行成功,F表示执行失败。
  • 脚本中的第一个用例执行失败;第二个用例执行成功;但是第三个也就是custom_case03并没有执行,由此我们知道,pytest只识别以test_开头的用例。

pytest.main(["-s", "demo1.py"])参数说明

  • -s,表示输出用例执行的详细结果。
  • demo1.py是要执行的脚本名称。

除了上述的函数这种写法,也可以有用例类的写法:

import pytest

class TestCase(object):

    def test_case01(self):
        """ 用例 01 """
        print('执行用例01.......')
        assert 0  # 断言失败

    def test_case02(slef):
        """ 用例 02 """
        print('执行用例02.......')
        assert 1  # 断言成功

if __name__ == '__main__':
    pytest.main(["-s", "demo1.py"])

用法跟unittest差不多,类名要以Test开头,并且其中的用例方法也要以test开头,然后执行也一样。

执行结果:

M:\py_tests>python demo1.py
========================================================== test session starts ===========================================================
platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: d:\py_tests
collected 2 items                                                                                                                         

demo1.py 执行用例01.......
F执行用例02.......
.

================================================================ FAILURES ================================================================
__________________________________________________________ TestCase.test_case01 __________________________________________________________

self = <demo1.TestCase object at 0x03DD6110>

    def test_case01(self):
        """ 用例 01 """
        print('执行用例01.......')
>       assert 0  # 断言失败
E       assert 0

demo1.py:49: AssertionError
====================================================== 1 failed, 1 passed in 0.12s =======================================================

setup和teardown

在unittest中,setup和teardown可以在每个用例前后执行,也可以在所有的用例集执行前后执行。那么在pytest中,有以下几种情况:

  • 模块级别,也就是在整个测试脚本文件中的用例集开始前后,对应的是:
    • setup_module
    • teardown_module
  • 类级别,在类中的所有用例集执行前后,对应的是:
    • setup_class
    • teardown_class
  • 在类中呢,也可以在进一步划分,在每一个方法执行前后,对应:
    • setup_method
    • teardown_methd
  • 函数级别,在用例函数之前后,对应:
    • setup_function
    • teardown_function

来一一看看各自的用法。

模块级别setup_module/teardown_module

import pytest


def setup_module():
    """ 模块级别的 setup,在该脚本内所有用例集执行之前触发执行 """
    print('模块级别的 setup.....')

#类级别的 def setup_class(self):
        """ 类级别的 setup,在该类中内用例集执行之前触发执行 """
        print('类级别的 setup.....')

   # def teardown_class(self):
        """ 类级别的 teardown,在该类中内用例集执行之后触发执行 """
        print('类级别的 teardown.....')

def test_case01():
    print('执行用例01.......')
    assert 0  # 断言失败

def test_case02():
    print('执行用例02.......')
    assert 1  # 断言成功

def teardown_module():
    """ 模块级别的 teardown,在该脚本内所有用例集执行之后触发执行 """
    print('模块级别的 teardown.....')

if __name__ == '__main__':
    pytest.main(["-s", "demo1.py"])
    
结果:
d:\py_tests>python demo1.py
========================================================== test session starts ===========================================================
platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: d:\py_tests
collected 2 items                                                                                                                         

demo1.py 模块级别的 setup.....
执行用例01.......
F执行用例02.......
.模块级别的 teardown.....


================================================================ FAILURES ================================================================
______________________________________________________________ test_case01 _______________________________________________________________

    def test_case01():
        print('执行用例01.......')
>       assert 0  # 断言失败
E       assert 0

demo1.py:16: AssertionError
====================================================== 1 failed, 1 passed in 0.12s =======================================================

小结

  • 在类中,不需要__init__方法。
  • 测试类的类名必须以Test开头。
  • 类中的测试方法编写规则跟函数一致。

配置文件

该脚本有多种运行方式,如果处于PyCharm环境,可以使用右键或者点击运行按钮运行,也就是在pytest中的主函数中运行:

if __name__ == '__main__':
    pytest.main(["-s", "demo1.py"])   # 就是调用的 pytest 的 main 函数

也可以在命令行中运行:

d:\py_tests>python demo1.py

这种方式,跟使用Python解释器执行Python脚本没有什么两样。也可以如下面这么执行:

d:\py_tests>pytest -s demo1.py

当然,还有一种是使用配置文件运行,来看看怎么用。

在项目的根目录下,我们可以建立一个pytest.ini文件,在这个文件中,我们可以实现相关的配置:

[pytest]
addopts = -s -v
testpaths = ./scripts
python_files = test_*.py
python_classes = Test*
python_functions = test_*

注意,配置文件中不许有中文

那这个配置文件中的各项都是什么意思呢?

首先,pytest.ini文件必须位于项目的根目录,而且也必须叫做pytest.ini

其他的参数:

  • addopts可以搭配相关的参数,比如-s。多个参数以空格分割,其他参数后续用到再说。

    • -s,在运行测试脚本时,为了调试或打印一些内容,我们会在代码中加一些print内容,但是在运行pytest时,这些内容不会显示出来。如果带上-s,就可以显示了。
    • -v,使输出结果更加详细。
  • testpaths配置测试用例的目录,

    • 因为我们用例可能分布在不同的目录或文件中,那么这个scripts就是我们所有文件或者目录的顶层目录。其内的子文件或者子目录都要以test_开头,pytest才能识别到。
    • 另外,上面这么写,是从一个总目录下寻找所有的符合条件的文件或者脚本,那么我们想要在这个总目录下执行其中某个具体的脚本文件怎么办?
    [pytest]
    testpaths = ./scripts/
    python_files = test_case_01.py

    这么写就是执行scripts目录下面的test_case_01.py这个文件。

  • python_classes则是说明脚本内的所有用例类名必须是以Test开头,当然,你也可以自定义为以Test_开头,而类中的用例方法则当然是以test_开头。

  • python_functions则是说脚本内的所有用例函数以test_开头才能识别。

    有了配置文件,我们在终端中(前提是在项目的根目录),直接输入pytest即可。

d:\py_tests>pytest

进阶

跳过用例

在unittest中,跳过用例可以用skip,那么这同样是适用于pytest。

import pytest

@pytest.mark.skip(condition='我就是要跳过这个用例啦')
def test_case_01():
    assert 1

@pytest.mark.skipif(condition=1 < 2, reason='如果条件为true就跳过用例')
def test_case_02():
    assert 1

跳过用例,我们使用@pytest.mark.skipif(condition, reason)

  • condition表示跳过用例的条件。
  • reason表示跳过用例的原因。

然后将它装饰在需要被跳过用例的的函数上面。

效果如下:

d:\py_tests>pytest                                                                                                                   

scripts/test_allure_case.py::test_case_01 SKIPPED
scripts/test_allure_case.py::test_case_02 SKIPPED

=========================================================== 2 skipped in 0.14s ===========================================================

上例执行结果相对详细,因为我们在配置文件中为addopts增加了-v,之前的示例结果中,没有加!

标记预期失败

如果我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示。

Pytest 使用 pytest.mark.xfail实现预见错误功能::

xfail(condiition, reason, [raises=None, run=True, strict=False])

需要掌握的必传参数的是:

  • condition,预期失败的条件,当条件为真的时候,预期失败。
  • reason,失败的原因。

那么关于预期失败的几种情况需要了解一下:

  • 预期失败,但实际结果却执行成功。
  • 预期失败,实际结果也执行执行失败。
    来看示例:
import pytest


class TestCase(object):

    @pytest.mark.xfail(1 < 2, reason='预期失败, 执行失败')
    def test_case_01(self):
        """ 预期失败, 执行也是失败的 """
        print('预期失败, 执行失败')
        assert 0

    @pytest.mark.xfail(1 < 2, reason='预期失败, 执行成功')
    def test_case_02(self):
        """ 预期失败, 但实际执行结果却成功了 """
        print('预期失败, 执行成功')
        assert 1

结果如下:

M:\py_tests>pytest
========================================================== test session starts ===========================================================
platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: d:\py_tests, inifile: pytest.ini, testpaths: ./scripts/
plugins: allure-pytest-2.8.6, cov-2.8.1, forked-1.1.3, html-2.0.0, metadata-1.8.0, ordering-0.6, rerunfailures-7.0, xdist-1.30.0
collected 2 items                                                                                                                         

scripts\demo1.py xX                                                                                                                 [100%]

===================================================== 1 xfailed, 1 xpassed in 0.15s =================================================

pytest 使用 x 表示预见的失败(XFAIL)。

如果预见的是失败,但实际运行测试却成功通过,pytest 使用 X 进行标记(XPASS)。

而在预期失败的两种情况中,我们不希望出现预期失败,结果却执行成功了的情况出现,因为跟我们想的不一样嘛,我预期这条用例失败,那这条用例就应该执行失败才对,你虽然执行成功了,但跟我想的不一样,你照样是失败的!

所以,我们需要将预期失败,结果却执行成功了的用例标记为执行失败,可以在pytest.ini文件中,加入:

[pytest]
xfail_strict=true

这样就就把上述的情况标记为执行失败了。

参数化

pytest身为强大的测试单元测试框架,那么同样支持DDT数据驱动测试的概念。也就是当对一个测试函数进行测试时,通常会给函数传递多组参数。比如测试账号登陆,我们需要模拟各种千奇百怪的账号密码。

当然,我们可以把这些参数写在测试函数内部进行遍历。不过虽然参数众多,但仍然是一个测试,当某组参数导致断言失败,测试也就终止了。

通过异常捕获,我们可以保证程所有参数完整执行,但要分析测试结果就需要做不少额外的工作。

在 pytest 中,我们有更好的解决方法,就是参数化测试,即每组参数都独立执行一次测试。使用的工具就是 pytest.mark.parametrize(argnames, argvalues)

  • argnames表示参数名。
  • argvalues表示列表形式的参数值。

使用就是以装饰器的形式使用。

只有一个参数的测试用例

import pytest

mobile_list = ['10010', '10086']

@pytest.mark.parametrize('mobile', mobile_list)
def test_register(mobile):
    """ 通过手机号注册 """
    print('注册手机号是: {}'.format(mobile))

来看(重要部分)结果::

M:\py_tests>pytest
scripts/test_case_01.py::test_register[10010] 注册手机号是: 10010
PASSED
scripts/test_case_01.py::test_register[10086] 注册手机号是: 10086
PASSED

====================================================== 2 passed in 0.11s ======================================================

可以看到,列表内的每个手机号,都是一条测试用例。

多个参数的测试用例

import pytest

mobile_list = ['10010', '10086']
code_list = ['x2zx', 'we2a']

@pytest.mark.parametrize('mobile', mobile_list)
@pytest.mark.parametrize('code', code_list)
def test_register(mobile, code):
    """ 通过手机号注册 """
    print('注册手机号是: {} 验证码是: {}'.format(mobile, code))

(重要部分)结果:

M:\py_tests>pytest                            

scripts/test_case_01.py::test_register[x2zx-10010] 注册手机号是: 10010 验证码是: x2zx
PASSED
scripts/test_case_01.py::test_register[x2zx-10086] 注册手机号是: 10086 验证码是: x2zx
PASSED
scripts/test_case_01.py::test_register[we2a-10010] 注册手机号是: 10010 验证码是: we2a
PASSED
scripts/test_case_01.py::test_register[we2a-10086] 注册手机号是: 10086 验证码是: we2a
PASSED

====================================================== 4 passed in 0.17s =======================================================

可以看到,每一个手机号与每一个验证码都组合一起执行了,这样就执行了4次。那么如果有很多个组合的话,用例数将会更多。我们希望手机号与验证码一一对应组合,也就是只执行两次,怎么搞呢?

import pytest

mobile_list = ['10010', '10086']
code_list = ['x2zx', 'we2a']

@pytest.mark.parametrize('mobile,code', zip(mobile_list, code_list))
def test_register(mobile, code):
    """ 通过手机号注册 """
    print('注册手机号是: {} 验证码是: {}'.format(mobile, code))

在多参数情况下,多个参数名是以,分割的字符串。参数值是列表嵌套的形式组成的。

M:\py_tests>pytest                   

scripts/test_case_01.py::test_register[10010-x2zx] 注册手机号是: 10010 验证码是: x2zx
PASSED
scripts/test_case_01.py::test_register[10086-we2a] 注册手机号是: 10086 验证码是: we2a
PASSED

====================================================== 2 passed in 0.44s ======================================================

固件

固件(Fixture)是一些函数,pytest 会在执行测试函数之前(或之后)加载运行它们,也称测试夹具。

我们可以利用固件做任何事情,其中最常见的可能就是数据库的初始连接和最后关闭操作。

Pytest 使用 pytest.fixture() 定义固件,下面是最简单的固件,访问主页前必须先登录:

import pytest

@pytest.fixture()
def login():
    print('登录....')

def test_index(login):
    print('主页....')

结果:

d:\py_tests>pytest               

scripts/test_case_01.py::test_index 登录....
主页....
PASSED

====================================================== 1 passed in 0.13s =======================================================

作用域

在之前的示例中,你可能会觉得,这跟之前的setup和teardown的功能也类似呀,但是,fixture相对于setup和teardown来说更灵活。pytest通过scope参数来控制固件的使用范围,也就是作用域。

在定义固件时,通过 scope 参数声明作用域,可选项有:

  • function: 函数级,每个测试函数都会执行一次固件;
  • class: 类级别,每个测试类执行一次,所有方法都可以使用;
  • module: 模块级,每个模块执行一次,模块内函数和方法都可使用;
  • session: 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。

默认的作用域为 function

比如之前的login固件,可以指定它的作用域:

import pytest

@pytest.fixture(scope='function')
def login():
    print('登录....')

def test_index(login):
    print('主页....')

常用插件

先来看一个重要的,那就是生成测试用例报告。

pytest测试报告插件

想要生成测试报告,首先要有下载,才能使用。

下载

pip install pytest-html

https://github.com/pytest-dev/pytest-html

如果下载失败,可以使用PyCharm下载

使用

在配置文件中,添加参数:

[pytest]
addopts = -s --html=report/report.html

完事之后,让我们继续终端中使用pytest重新跑测试用例,用例结果就不展示了,跟上面的结果一样,我们关注项目目录下的report/report.html文件,我们用浏览器打开它,你会发现:

这就是测试报告

allure

Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。

Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。
从开发人员(dev,developer)和质量保证人员(QA,Quality Assurance)的角度来看,Allure报告简化了常见缺陷的统计:失败的测试可以分为bug和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与TMS和BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
从管理者的角度来看,Allure提供了一个清晰的“大图”,其中包括已覆盖的特性、缺陷聚集的位置、执行时间轴的外观以及许多其他方便的事情。allure的模块化和可扩展性保证了我们总是能够对某些东西进行微调。

少扯点,来看看怎么使用。

Python的pytest中allure下载

pip install allure-pytest

但由于这个allure-pytest插件生成的测试报告不是html类型的,我们还需要使用allure工具再“加工”一下。所以说,我们还需要下载这个allure工具。

allure工具下载

在现在allure工具之前,它依赖Java环境,我们还需要先配置Java环境。

PS:Java请自行官网下载

配置完了Java环境,我们再来下载allure工具,我这里直接给出了百度云盘链接,你也可以去其他链接中自行下载:

https://github.com/allure-framework/allure2

优先选择:https://bintray.com/qameta/maven/allure2

百度云盘链接:链接:https://pan.baidu.com/s/1Xj1A_xsRscOZHskTR4xjAg 提取码:6b33

下载并解压好了allure工具包之后,还需要将allure包内的bin目录添加到系统的环境变量中。

完事后打开你的终端测试:

C:\Users\Anthony\Desktop>allure --version
2.10.0

返回了版本号说明安装成功。

使用

一般使用allure要经历几个步骤:

  • 配置pytest.ini文件。
  • 编写用例并执行。
  • 使用allure工具生成html报告。

来看配置pytest.ini

[pytest]
addopts =  -v -s --html=report/report.html --alluredir ./report/result
testpaths = ./scripts/
python_files = test_allure_case.py
python_classes = Test*
python_functions = test_*
# xfail_strict=true

就是--alluredir ./report/result参数。

在终端中输入pytest正常执行测试用例即可:

import pytest

def test_case_01():
    assert 1

def test_case_02():
    assert 0

def test_case_03():
    assert 1

执行完毕后,在项目的根目下,会自动生成一个report目录,这个目录下有:

  • report.html是我们的之前的pytest-html插件生成的HTML报告,跟allure无关。
  • result和assets目录是allure插件生成的测试报告文件,但此时该目录内还没有什么HTML报告,只有一些相关数据。

接下来需要使用allure工具来生成HTML报告。

此时我们在终端(如果是windows平台,就是cmd),路径是项目的根目录,执行下面的命令。

PS:我在pycharm中的terminal输入allure提示'allure' 不是内部或外部命令,也不是可运行的程序或批处理文件。但windows的终端没有问题。

d:\py_tests>allure generate report/result -o report/allure_html --clean
Report successfully generated to report\allure_html

命令的意思是,根据report\result目录中的数据(这些数据是运行pytest后产生的)。在report目录下新建一个allure_html目录,而这个目录内有index.html才是最终的allure版本的HTML报告;如果你是重复执行的话,使用--clean清除之前的报告。

结果:

在使用allure生成报告的时候,在编写用例阶段,还可以有一些参数可以使用:

  • title,自定义用例标题,标题默认是用例名。

  • description,测试用例的详细说明。

  • feature和story被称为行为驱动标记,因为使用这个两个标记,通过报告可以更加清楚的掌握每个测试用例的功能和每个测试用例的测试场景。或者你可以理解为feature是模块,而story是该模块下的子模块。

  • allure中对bug的严重(severity)级别也有定义,allure使用

    severity

    来标识测试用例或者测试类的bug级别,分为blocker,critical,normal,minor,trivial5个级别。一般,bug分为如下几个级别:

    • Blocker级别:中断缺陷(客户端程序无响应,无法执行下一步操作),系统无法执行、崩溃或严重资源不足、应用模块无法启动或异常退出、无法测试、造成系统不稳定。
    • Critical级别:即影响系统功能或操作,主要功能存在严重缺陷,但不会影响到系统稳定性。比如说一个服务直接不可用了,微信不能发消息,支付宝不能付款这种,打开直接报错。
    • Major:即界面、性能缺陷、兼容性。如操作界面错误(包括数据窗口内列名定义、含义是否一致)、长时间操作无进度提示等。
    • Normal级别:普通缺陷(数值计算错误),是指非核心业务流程产生的问题,比如说知乎无法变更头像,昵称等。这个要看自己的定义。
    • Minor/Trivial级别:轻微缺陷(必输项无提示,或者提示不规范),比如各种影响体验,但不影响使用的内容。
  • dynamic,动态设置相关参数。

allure.title与allure.description

import pytest
import allure

@allure.title('测试用例标题1')
@allure.description('这是测试用例用例1的描述信息')
def test_case_01():
    assert 1

def test_case_02():
    assert 0

def test_case_03():
    assert 1

feature和story

import pytest
import allure

@allure.feature('登录模块')
class TestCaseLogin(object):

    @allure.story('登录模块下的子模块: test1')
    def test_case_01(self):
        assert 1

    @allure.story('登录模块下的子模块: test1')
    def test_case_02(self):
        assert 1

    @allure.story('登录模块下的子模块: test2')
    def test_case_03(self):
        assert 1

    @allure.story('登录模块下的子模块: test3')
    def test_case_04(self):
        assert 1

@allure.feature('注册模块')
class TestCaseRegister(object):
    @allure.story('注册模块下的子模块: test1')
    def test_case_01(self):
        assert 1

    @allure.story('注册模块下的子模块: test1')
    def test_case_02(self):
        assert 1

    @allure.story('注册模块下的子模块: test1')
    def test_case_03(self):
        assert 1

    @allure.story('注册模块下的子模块: test2')
    def test_case_04(self):
        assert 1

由上图可以看到,不同的用例被分为不同的功能中。

allure.severity

allure.severity用来标识测试用例或者测试类的级别,分为blocker,critical,normal,minor,trivial5个级别。

import pytest
import allure

@allure.feature('登录模块')
class TestCaseLogin(object):

    @allure.severity(allure.severity_level.BLOCKER)
    def test_case_01(self):
        assert 1

    @allure.severity(allure.severity_level.CRITICAL)
    def test_case_02(self):
        assert 1

    @allure.severity(allure.severity_level.MINOR)
    def test_case_03(self):
        assert 1

    @allure.severity(allure.severity_level.TRIVIAL)
    def test_case_04(self):
        assert 1

    def test_case_05(self):
        assert 1

severity的默认级别是normal,所以上面的用例5可以不添加装饰器了。

allure.dynamic

import pytest
import allure

@allure.feature('登录模块')
class TestCaseLogin(object):

    @allure.severity(allure.severity_level.BLOCKER)
    def test_case_01(self):
        assert 1

    @allure.severity(allure.severity_level.CRITICAL)
    def test_case_02(self):
        assert 1

    @allure.severity(allure.severity_level.MINOR)
    def test_case_03(self):
        assert 1

    @allure.severity(allure.severity_level.TRIVIAL)
    def test_case_04(self):
        assert 1
    @pytest.mark.parametrize('name', ['动态名称1', '动态名称2'])
    def test_case_05(self, name):
        allure.dynamic.title(name)

猜你喜欢

转载自www.cnblogs.com/zzsy/p/12245399.html