• pytest自动化测试框架之标记用例(指定执行、跳过用例、预期失败)


    pytest中提供的mark模块,可以实现很多功能,如:

    标记用例,即打标签
    skip、skipif标记跳过,skip跳过当前用例,skipif符合情况则跳过当前用例
    xfail标记为预期失败
    标记用例
    有时候我们可能并不需要执行项目中的所有用例,而只执行其中的某些用例,即指定执行某一类或某个场景的测试用例,比如只执行冒烟用例,那么这个时候就需要使用@pytest.mark.标签名来进行打标签过滤。标签名需要先注册,然后才能使用。

    注册标签
    官方文档里提供了三种注册标签的方法,这里只介绍pytest.ini及conftest.py,有兴趣的可以去查看。

    方法一,在项目根目录新建pytest.ini,并在其中注册、管理标签。示例如下:

    1. [pytest]
    2. markers =
    3. smoke: marks test as smoke
    4. login
    5. order: 下单场景

    这里定义了三个标签,分别是:smoke、login、order,冒号后面的是标签说明,可不加。

    方法二,在conftest.py中定义钩子函数进行标签注册,格式如下:

    1. def pytest_configure(config):
    2. marker_list = [
    3. "smoke: marks test as smoke",
    4. "login",
    5. "order: 下单场景"
    6. ]
    7. for marker in marker_list:
    8. config.addinivalue_line("markers", marker)

    方法二需注意定义的格式,不能轻易修改函数名及入参。

    使用方法
    1. import pytest
    2. # 标记测试函数
    3. @pytest.mark.smoke
    4. def test_01():
    5. print("执行test_01")
    6. def test_02():
    7. print("执行test_02")
    8. # 标记测试类
    9. @pytest.mark.order
    10. class TestOrder:
    11. def test_order(self):
    12. print("下单")
    13. def test_pay(self):
    14. print("支付")
    15. # 多个标签
    16. @pytest.mark.smoke
    17. @pytest.mark.login
    18. def test_login():
    19. print("登录")

    给测试类打标签,还有另外一种方式,如下:

    1. # 标记测试类(单个标签)
    2. class TestOrder:
    3. # 给类中的所有测试方法打上order标签
    4. pytestmark = pytest.mark.order
    5. def test_order(self):
    6. print("下单")
    7. def test_pay(self):
    8. print("支付")
    9. # 标记测试类(多个标签)
    10. class TestOrder:
    11. # 给类中的所有测试方法打上order、smoke标签
    12. pytestmark = [pytest.mark.order, pytest.mark.smoke]
    13. def test_order(self):
    14. print("下单")
    15. def test_pay(self):
    16. print("支付")

    同样可以使用pytestmark标记模块,给模块中所有的测试类、测试函数打上标签,如下:

    1. import pytest
    2. # 模块中的所有测试函数、测试类都会被打上order、smoke标签
    3. pytestmark = [pytest.mark.order, pytest.mark.smoke]
    4. def test_01():
    5. print("执行test_01")
    6. def test_02():
    7. print("执行test_02")
    8. class TestOrder:
    9. def test_order(self):
    10. print("下单")
    11. def test_pay(self):
    12. print("支付")
    执行方法

    执行的时候加上参数-m标签名即可。

    命令行

    1. # 执行被标记为smoke的用例
    2. pytest -m smoke
    3. # 执行被标记为smoke且被标记为login的用例
    4. pytest -m "smoke and login"
    5. # 执行被标记为smoke或login的用例
    6. pytest -m "smoke or login"

    代码执行

    1. # 执行被标记为smoke的用例
    2. pytest.main(['-m smoke'])
    3. # 执行被标记为smoke或order的用例
    4. pytest.main(["-m", "smoke or order"])
    5. # 执行被标记为smoke同时被标记为login的用例
    6. pytest.main(["-m", "smoke and login"])
    7. # 执行被标记为smoke且不被标记为login的用例
    8. pytest.main(["-m", "smoke and not login"])

    这里需要注意,在测试模块中直接使用pytest.main()执行当前模块中的被打标签的用例是无效的,这样会执行当前模块中的所有测试用例。如下示例:

    1. import pytest
    2. # 标记测试函数
    3. @pytest.mark.smoke
    4. def test_01():
    5. print("执行test_01")
    6. def test_02():
    7. print("执行test_02")
    8. # 标记测试类
    9. @pytest.mark.order
    10. class TestOrder:
    11. def test_order(self):
    12. print("下单")
    13. def test_pay(self):
    14. print("支付")
    15. # 多个标签
    16. @pytest.mark.smoke
    17. @pytest.mark.login
    18. def test_login():
    19. print("登录")
    20. if __name__ == '__main__':
    21. pytest.main(['-s', '-m smoke'])

    运行该模块,结果如下

    从结果中可以看出,虽然代码中写了只执行标记为smoke的用例,但所有5条用例都被执行了,不能进行过滤。

    我们需要将执行代码分离出来,放在单独的执行模块里面,如放在run.py,代码如下:

    1. # run.py
    2. import pytest
    3. if __name__ == '__main__':
    4. pytest.main(["-s", "-m", "smoke or order"])

     运行结果如下:

    从结果可以看出来,这里只运行了标记为smoke或order的测试用例。

    标记跳过
    有时候我们需要跳过某些测试用例不去执行,如代码更新后老的用例不需要执行了,或者在某些特定场景下不需要执行某些用例,这时就需要给对应的测试用例做标记跳过处理。

    pytest中提供了两种标记跳过的方法,如下:

    直接跳过,@pytest.mark.skip(reason="跳过原因"),reason可写可不写。
    条件跳过,即满足某个条件则跳过不执行,@pytest.mark.skipif(b>3, reason="跳过原因")
    示例如下:

    1. import pytest
    2. @pytest.mark.skip(reason="不需要执行test_01")
    3. def test_01():
    4. print("执行test_01")
    5. @pytest.mark.skip(2>1, reason="如果2大于1则跳过不执行")
    6. def test_02():
    7. print("执行test_02")
    8. if __name__ == '__main__':
    9. pytest.main(['-s'])

    运行结果:

    从运行结果中可以看到,这2条用例都被跳过。如果想要 跳过测试类 或 测试模块,方法同上面给测试类、测试模块打标签的方法一样,不做过多说明。

    xfail(标记为预期失败)
    有些场景下需要将测试用例标记为预期失败,如对尚未实现的功能或尚未修复的错误进行测试,使用@pytest.mark.xfail可以将测试用例标记为预期失败。

    pytest.mark.xfail(condition=None, reason=None, raises=None, run=True, strict=False),参数说明如下:

    condition,预期失败的条件,默认值为None,表示只有满足条件时才标记用例为预期失败。

    reason,失败原因,默认值为None,说明标记用例的原因。

    strict关键字参数,默认值为False。

    当 strict=False 时,如果用例执行失败,则结果标记为xfail,表示符合预期的失败;如果用例执行成功,结果标记为XPASS,表示不符合预期的成功;

    当strict=True时,如果用例执行成功,结果将标记为failed。

    raises关键字参数,默认值为None,可以上报指定的一个或多个异常。如果用例的失败不是因为所期望的异常导致的,pytest将会把测试结果标记为failed。

    run关键字参数,默认值为True。当run=False时,pytest不会再执行测试用例,直接将结果标记为xfail。

    常用的参数示例如下:

    1. import pytest
    2. # run、strict都为默认,因为用例执行是失败的,所以该用例执行结果会被标记为xfail
    3. @pytest.mark.xfail(reason="bug待修复")
    4. def test_01():
    5. print("执行test_01")
    6. a = "hello"
    7. b = "hi"
    8. assert a == b
    9. # run、strict都为默认,因为用例执行是通过的,所以该用例执行结果会被标记为xpass
    10. @pytest.mark.xfail(condition=lambda: True, reason="bug待修复")
    11. def test_02():
    12. print("执行test_02")
    13. a = "hello"
    14. b = "hi"
    15. assert a != b
    16. # run=False,该用例不执行,直接将结果标记为xfail
    17. @pytest.mark.xfail(reason="功能尚未开发完成", run=False)
    18. def test_03():
    19. print("执行test_03")
    20. a = "hello"
    21. b = "hi"
    22. assert a == b
    23. # strict=True,因为用例执行是通过的,所以结果会被标记为failed
    24. @pytest.mark.xfail(reason="功能尚未开发完成", strict=True)
    25. def test_04():
    26. print("执行test_04")
    27. a = "hello"
    28. b = "he"
    29. assert b in a
    30. if __name__ == '__main__':
    31. pytest.main(['-s'])

    运行结果:

    从结果中可以看出来,test_01结果展示为xfail,test_02结果展示为xpass,test_03没有执行而是直接展示为xfail,test_04结果展示为failed

    总结
    以上示例仅仅只是为了说明@pytest.mark提供的这些功能的使用方法,实际自动化过程中需要灵活选用。

    在一般的自动化测试过程中,通过打标签的方式标记某个场景用例会比较多,如标记冒烟测试用例用于冒烟测试。跳过或条件跳过测试用例也经常会用到。而需要将用例标记为预期失败的场景则比较少。

    最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

     文档获取方式:点击右边链接领取:软件测试全套资料分享    

  • 相关阅读:
    分层化网络设计:核心层,汇聚层,接入层
    自定义弹窗dom元素的添加与使用的js文件
    【math】利用Cardano方法对一元三次方程求解及python实现
    **20.迭代器模式(Iterator)
    vncserver远程管理kvm虚拟机
    2023华为杯数学建模D题第三问——区域双碳目标情景设计样例
    老牌好用免费的数据恢复软件easyrecovery操作简单一键恢复
    c#学生管理系统
    VRP基础及操作
    俄罗斯人有哪些商务礼仪
  • 原文地址:https://blog.csdn.net/YJT1002/article/details/133774989