pytest(9)-标记用例(指定执行、跳过用例、预期失败)

简介: pytest中提供的mark模块,可以实现很多功能,如:1. 标记用例,即打标签2. skip、skipif标记跳过,skip跳过当前用例,skipif符合情况则跳过当前用例3. xfail标记为预期失败

标记用例


有时候我们可能并不需要执行项目中的所有用例,而只执行其中的某些用例,即指定执行某一类或某个场景的测试用例,比如只执行冒烟用例,那么这个时候就需要使用@pytest.mark.标签名来进行打标签过滤。标签名需要先注册,然后才能使用。


注册标签


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

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

[pytest]
markers =
    smoke: marks test as smoke
    login
    order: 下单场景

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

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

def pytest_configure(config):
    marker_list = [
        "smoke: marks test as smoke",
        "login",
        "order: 下单场景"
    ]
    for marker in marker_list:
        config.addinivalue_line("markers", marker)

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


使用方法


import pytest
# 标记测试函数
@pytest.mark.smoke
def test_01():
    print("执行test_01")
def test_02():
    print("执行test_02")
# 标记测试类
@pytest.mark.order
class TestOrder:
    def test_order(self):
        print("下单")
    def test_pay(self):
        print("支付")
# 多个标签 
@pytest.mark.smoke
@pytest.mark.login
def test_login():
    print("登录")

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

# 标记测试类(单个标签)
class TestOrder:
    # 给类中的所有测试方法打上order标签
    pytestmark = pytest.mark.order
    def test_order(self):
        print("下单")
    def test_pay(self):
        print("支付")
# 标记测试类(多个标签)
class TestOrder:
    # 给类中的所有测试方法打上order、smoke标签
    pytestmark = [pytest.mark.order, pytest.mark.smoke]
    def test_order(self):
        print("下单")
    def test_pay(self):
        print("支付")

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

import pytest
# 模块中的所有测试函数、测试类都会被打上order、smoke标签
pytestmark = [pytest.mark.order, pytest.mark.smoke]
def test_01():
    print("执行test_01")
def test_02():
    print("执行test_02")
class TestOrder:
    def test_order(self):
        print("下单")
    def test_pay(self):
        print("支付")


执行方法


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


命令行

# 执行被标记为smoke的用例
pytest -m smoke
# 执行被标记为smoke且被标记为login的用例
pytest -m "smoke and login"
# 执行被标记为smoke或login的用例
pytest -m "smoke or login"


代码执行

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


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

import pytest
# 标记测试函数
@pytest.mark.smoke
def test_01():
    print("执行test_01")
def test_02():
    print("执行test_02")
# 标记测试类
@pytest.mark.order
class TestOrder:
    def test_order(self):
        print("下单")
    def test_pay(self):
        print("支付")
# 多个标签 
@pytest.mark.smoke
@pytest.mark.login
def test_login():
    print("登录")
if __name__ == '__main__':
    pytest.main(['-s', '-m smoke'])


运行该模块,结果如下:

微信图片_20220425172254.png

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

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

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

运行结果如下:

微信图片_20220425172258.png

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


标记跳过


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

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

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

示例如下:

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

运行结果:

微信图片_20220425172302.png

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


xfail(标记为预期失败)


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

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

  1. condition,预期失败的条件,默认值为None,表示只有满足条件时才标记用例为预期失败。
  2. reason,失败原因,默认值为None,说明标记用例的原因。
  3. strict关键字参数,默认值为False。
    当 strict=False 时,如果用例执行失败,则结果标记为xfail,表示符合预期的失败;如果用例执行成功,结果标记为XPASS,表示不符合预期的成功;
    当strict=True时,如果用例执行成功,结果将标记为failed。
  4. raises关键字参数,默认值为None,可以上报指定的一个或多个异常。如果用例的失败不是因为所期望的异常导致的,pytest将会把测试结果标记为failed。
  5. run关键字参数,默认值为True。当run=False时,pytest不会再执行测试用例,直接将结果标记为xfail。

常用的参数示例如下:

import pytest
# run、strict都为默认,因为用例执行是失败的,所以该用例执行结果会被标记为xfail
@pytest.mark.xfail(reason="bug待修复")
def test_01():
    print("执行test_01")
    a = "hello"
    b = "hi"
    assert a == b
# run、strict都为默认,因为用例执行是通过的,所以该用例执行结果会被标记为xpass
@pytest.mark.xfail(condition=lambda: True, reason="bug待修复")
def test_02():
    print("执行test_02")
    a = "hello"
    b = "hi"
    assert a != b
# run=False,该用例不执行,直接将结果标记为xfail
@pytest.mark.xfail(reason="功能尚未开发完成", run=False)
def test_03():
    print("执行test_03")
    a = "hello"
    b = "hi"
    assert a == b
# strict=True,因为用例执行是通过的,所以结果会被标记为failed
@pytest.mark.xfail(reason="功能尚未开发完成", strict=True)
def test_04():
    print("执行test_04")
    a = "hello"
    b = "he"
    assert b in a
if __name__ == '__main__':
    pytest.main(['-s'])

运行结果:

微信图片_20220425172307.png

从结果中可以看出来,test_01结果展示为xfailtest_02结果展示为xpasstest_03没有执行而是直接展示为xfailtest_04结果展示为failed


总结


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

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

相关文章
|
边缘计算 网络协议 网络架构
DoIP看这篇就够了,吐血整理
DoIP看这篇就够了,吐血整理
DoIP看这篇就够了,吐血整理
|
5月前
|
自然语言处理 数据可视化 测试技术
告别‘人海战术’!基于EvalScope 的文生图模型智能评测新方案
生成式模型在文本生成图片等领域的快速发展,为社区带来了日新月异的诸多文生图模型。
606 20
|
设计模式 监控 Java
Zabbix对Tomcat的监控
Zabbix通过java gateway 及 JMX  对Tomcat 进行监控,并实现自定义模板的导入及应用,模拟实际生产中的Tomacat性能等参数的图形监测显示。
32281 84
Zabbix对Tomcat的监控
|
自然语言处理 Python
通义灵码个人使用体验
我是一位Python初学者,使用通义灵码进行代码生成与解析,学习更便捷高效。具体流程包括:1. 安装与配置插件;2. 输入需求,描述代码功能或优化目标;3. 点击生成,自动获得代码片段或优化建议。
|
JavaScript 前端开发 开发者
vue3+ts配置跨域报错问题解决:> newpro2@0.1.0 serve > vue-cli-service serve ERROR Invalid options in vue.
【6月更文挑战第3天】在 Vue CLI 项目中遇到 "ERROR Invalid options in vue.config.js: ‘server’ is not allowed" 错误是因为尝试在 `vue.config.js` 中使用不被支持的 `server` 选项。正确配置开发服务器(如代理)应使用 `devServer` 对象,例如设置代理到 `http://xxx.com/`: ```javascript module.exports = { devServer: {
649 1
|
12月前
|
缓存 监控 前端开发
Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信
本文探讨了在 Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信。首先介绍了 WebSocket 和 Socket.IO 的基本概念及其优势,接着详细讲解了 Go 语言中 WebSocket 的实现方法,以及二者集成的重要意义和具体步骤。文章还讨论了集成过程中需要注意的问题,如协议兼容性、消息格式、并发处理等,并提供了实时聊天、数据监控和在线协作工具等应用案例,最后提出了性能优化策略,包括数据压缩、缓存策略和连接管理优化。旨在帮助开发者更好地理解并应用这些技术。
606 3
|
机器学习/深度学习 人工智能 自然语言处理
【大语言模型-论文精读】谷歌-BERT:用于语言理解的预训练深度双向Transformers
【大语言模型-论文精读】谷歌-BERT:用于语言理解的预训练深度双向Transformers
|
机器学习/深度学习 人工智能 机器人
万物皆可AIGC获奖名单公布
2023年9月15日起,阿里云开发者社区推出“万物皆可AIGC”活动,号召广大开发者领取免费算力,释放AI创意,累计收到500+高质量的AI创意图文及视频作品,经审核与评选,现公布获奖名单!
1950 72
万物皆可AIGC获奖名单公布
|
消息中间件 运维 监控
中间件技术选型
【7月更文挑战第7天】
327 6
|
存储 编译器 Go
深入理解Go Workspace的三个关键目录结构
【8月更文挑战第31天】
626 0