可以通过命令行查看所有marker,包括内置和自定义的

  1. pytest --markers

内置marker

内置marker本文先讲usefixtures 、filterwarnings 、skip 、skipif 、xfail这5个。参数化的marker我会写在《pytest参数化》中,hook的marker我会写在《pytest hook》中,插件的marker(pytest-ordering、allure等)我会写在《pytest插件》中。当前只需知道有以上这些分类的marker即可,更多内容请关注后续文章。

usefixtures

如果我们只想把fixture注入到test中,test不直接访问fixture的时候,就需要用到usefixtures。

示例,test需要一个临时目录,但是并不需要知道这个目录具体路径在哪

  1. # content of conftest.py
  2. import os
  3. import shutil
  4. import tempfile
  5. import pytest
  6. @pytest.fixture
  7. def cleandir():
  8. old_cwd = os.getcwd()
  9. newpath = tempfile.mkdtemp()
  10. os.chdir(newpath)
  11. yield
  12. os.chdir(old_cwd)
  13. shutil.rmtree(newpath)
  1. # content of test_setenv.py
  2. import os
  3. import pytest
  4. @pytest.mark.usefixtures("cleandir")
  5. class TestDirectoryInit:
  6. def test_cwd_starts_empty(self):
  7. assert os.listdir(os.getcwd()) == []
  8. with open("myfile", "w") as f:
  9. f.write("hello")
  10. def test_cwd_again_starts_empty(self):
  11. assert os.listdir(os.getcwd()) == []

TestDirectoryInit的测试方法需要一个临时目录作为当前工作目录,在类上添加@pytest.mark.usefixtures("cleandir"),类的方法不加fixture也能有"cleandir"的效果。

usefixtures可以添加多个fixture

  1. @pytest.mark.usefixtures("cleandir", "anotherfixture")

usefixtures可以用在pytestmark,作用域是定义所在module的所有tests

  1. pytestmark = pytest.mark.usefixtures("cleandir")

usefixtures也可以用在pytest.ini,作用域是整个项目的所有tests

  1. # content of pytest.ini
  2. [pytest]
  3. usefixtures = cleandir

不过需要注意的是fixture函数本身是不能用usefixtures的,如果想要嵌套fixture,只能通过在fixture修饰的函数中,添加参数这种方式。

filterwarnings

过滤警告信息。

示例,api_v1()抛出了“api v1”的警告,test_one()函数使用filterwarnings过滤掉了

  1. import warnings
  2. def api_v1():
  3. warnings.warn(UserWarning("api v1, should use functions from v2"))
  4. return 1
  5. @pytest.mark.filterwarnings("ignore:api v1")
  6. def test_one():
  7. assert api_v1() == 1

同样可以添加到pytestmark和pytest.ini中。

skip

跳过,不测试。

示例,skip需要添加reason哦

  1. @pytest.mark.skip(reason="no way of currently testing this")
  2. def test_the_unknown():
  3. ...

不过,更实用的方式是调用pytest.skip(reason)函数,而不是用mark,这样就可以用if判断跳不跳

  1. def test_function():
  2. if not valid_config():
  3. pytest.skip("unsupported configuration")

allow_module_level 可以跳过整个module

  1. import sys
  2. import pytest
  3. if not sys.platform.startswith("win"):
  4. pytest.skip("skipping windows-only tests", allow_module_level=True)

skipif

if判断跳不跳,还可以用skipif。

示例,如果Python版本小于3.6就跳过测试

  1. import sys
  2. @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
  3. def test_function():
  4. ...

如果想在summary中看到reason,需要添加-rs参数。

可以把skipif赋值给变量,然后直接引用变量,或者把变量import到其他module中使用

  1. # content of test_mymodule.py
  2. import mymodule
  3. minversion = pytest.mark.skipif(
  4. mymodule.__versioninfo__ < (1, 1), reason="at least mymodule-1.1 required"
  5. )
  6. @minversion
  7. def test_function():
  8. ...
  1. # test_myothermodule.py
  2. from test_mymodule import minversion
  3. @minversion
  4. def test_anotherfunction():
  5. ...

skipif添加到class上,会跳过类中所有方法。

可以使用pytestmark跳过module内所有test

  1. # test_module.py
  2. pytestmark = pytest.mark.skipif(...)

如果function有多个skipif作用,只要有一个为True,就会跳过。

xfail

明知失败,依然前行!不好意思跑偏了。xfail就是expected fail,预期失败

  1. @pytest.mark.xfail
  2. def test_function():
  3. ...

执行后summary不会统计为"failed",会单独列出来。如果结果失败了,“expected to fail” (XFAIL);如果结果成功了,“unexpectedly passing” (XPASS)。但是整个执行结果是”Tests passed“。

if判断

  1. def test_function():
  2. if not valid_config():
  3. pytest.xfail("failing configuration (but should work)")

值得注意的是,marker会继续执行所有test代码,pytest.xfail()函数会抛出异常,中断执行后续代码

添加condition,判断条件

  1. @pytest.mark.xfail(sys.platform == "win32", reason="bug in a 3rd party library")
  2. def test_function():
  3. ...

添加reason,理由

  1. @pytest.mark.xfail(reason="known parser issue")
  2. def test_function():
  3. ...

添加raises,抛出异常/错误

  1. @pytest.mark.xfail(raises=RuntimeError)
  2. def test_function():
  3. ...

添加run,禁止运行

  1. @pytest.mark.xfail(run=False)
  2. def test_function():
  3. ...

添加strict,严格模式,即使xpass也会强制失败,summary中有输出信息”[XPASS(strict)] “,测试结果为”Tests failed“。

  1. @pytest.mark.xfail(strict=True)
  2. def test_function():
  3. ...

断言成功也强制失败,确实够强势的!

可以在ini文件中定义全局strict

  1. [pytest]
  2. xfail_strict=true

在命令行添加--runxfail,忽略xfail marker,相当于没有添加这个标记的效果,该成功就成功,该失败就失败,再强势也不虚,哈哈,恶灵退散。

  1. pytest --runxfail
  1. pytest --runxfail

再强势也不虚,恶灵退散,哈哈。

自定义marker

通过注解自定义marker

  1. # content of test_server.py
  2. import pytest
  3. @pytest.mark.webtest
  4. def test_send_http():
  5. pass # perform some webtest test for your app
  6. def test_something_quick():
  7. pass
  8. def test_another():
  9. pass
  10. class TestClass:
  11. def test_method(self):
  12. pass

在命令行通过-m指定运行mark打标的test

  1. $ pytest -v -m webtest

也可以反选

  1. $ pytest -v -m "not webtest"

但是,这样定义的marker是未注册的!在执行后会警告,PytestUnknownMarkWarning。如果添加了命令行参数--strict-markers ,未注册的marker会报错

可以在pytest.ini文件中注册,冒号后面的所有代码都是marker说明,包括换行

  1. [pytest]
  2. markers =
  3. slow: marks tests as slow (deselect with '-m "not slow"')
  4. serial

更高级的,可以在pytest_configure hook函数中注册,这主要用在第三方插件

  1. def pytest_configure(config):
  2. config.addinivalue_line(
  3. "markers", "env(name): mark test to run only on named environment"
  4. )

简要回顾

本文介绍了5个pytest内置的marker,接着介绍了如何自定义marker和注册marker。通过marker,可以让我们更灵活的执行用例。

参考资料

docs-pytest-org-en-stable

pytest封神之路第四步 内置和自定义marker的更多相关文章

  1. pytest封神之路第五步 参数化进阶

    用过unittest的朋友,肯定知道可以借助DDT实现参数化.用过JMeter的朋友,肯定知道JMeter自带了4种参数化方式(见参考资料).pytest同样支持参数化,而且很简单很实用. 语法 在& ...

  2. pytest封神之路第零步 快速入门

    背景:本文是在系列第五篇发表后的补充篇章,第一篇介绍了tep,可能对不熟悉pytest的朋友不够友好,特意补充入门篇,帮大家快速了解如何动手写pytest.如果你是从这篇文章第一次阅读,那么请忽略以上 ...

  3. pytest封神之路第三步 精通fixture

    首先放一句"狠话". 如果你不会fixture,那么你最好别说自己会pytest. (只是为了烘托主题哈,手上的砖头可以放下了,手动滑稽) fixture是什么 看看源码 def ...

  4. pytest封神之路第六步 断言技巧

    pytest的断言把Python语言简洁的优点发挥的淋漓尽致,因为它用的就是Python的标准断言assert. assert基础 assert用法 assert_stmt ::= "ass ...

  5. pytest封神之路第二步 132个命令行参数用法

    在Shell执行pytest -h可以看到pytest的命令行参数有这10大类,共132个 序号 类别 中文名 包含命令行参数数量 1 positional arguments 形参 1 2 gene ...

  6. pytest封神之路第一步 tep介绍

    『 tep is a testing tool to help you write pytest more easily. Try Easy Pytest! 』 tep前身 tep的前身是接口自动化测 ...

  7. [Python笔记]第四篇:内置函数

    本篇主要内容:内置函数 函数 参考:https://docs.python.org/3.5/library/functions.html 内置函数列表 一.数学运算类 abs(x)求绝对值 >& ...

  8. python之路:进阶篇 内置函数

     li = [11, 22, 33] news = map(  li = [100, 2200, 3300] news = map(  [13, 24, 35] [11, 11, 11] [22, 4 ...

  9. GO语言系列(四)- 内置函数、闭包与高级数据类型

    一.内置函数.递归函数.闭包 内置函数 1. close:主要用来关闭channel 2. len:用来求长度,比如string.array.slice.map.channel 3. new:用来分配 ...

随机推荐

  1. 5.SSH 免密码登陆

    SSH 免密码登陆 serverA 机器上 userA 用户,想要免密钥登陆到serverB机器上 1.集群中的所有机器 安装ssh 服务端sudo apt-get updatesudo apt-ge ...

  2. 用java编程在10000到99999中的数字中找到aabcc类型的数字

    package com.diyo.offer; public class FindNum { public static void main(String[] args) { int count = ...

  3. LINUX进程ps -ef和ps -aux的区别及格式详解

    Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux.这两个到底有什么区别呢?两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格和BSD 风格, ...

  4. oracle修改用户密码操作

    打开命令提示框输入以下内容: 1.输入:sqlplus /nolog //进入oralce控制台2.输入:conn /as sysdba //以管理员权限登录3.输入:alter user apps ...

  5. MySQL数据库时间字段按年月日显示并多字段去重查询

    应用服务长久运行,难免要导出一些统计报表. 现在有一个日志表,记录了各种日志,需要导出十月份的登录日志,要求时间按日期显示,且每天用户登陆要去重. 先看日志表的字段构成: logType等于2的是登陆 ...

  6. Federated Optimization: Distributed Machine Learning for On-Device Intelligence

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:1610.02527v1 [cs.LG] 8 Oct 2016 坐标下降法:https://blog.csdn.net/qq_ ...

  7. 数据操纵DML

    数据操纵DML 1. 在dept表中插入两行数据 (1)50,'IT','SHENYANG';(2)60,'HR','DALIAN'; 2. 设置保存点beforeup 3. 更新dept表,将60号 ...

  8. wordpress个人常用标签调用

    wordpress常见标签调用,老是容易忘记,又要找半天,干脆搬到网站上. <?php bloginfo('name');?>网站名称 url <?php echo home_url ...

  9. 时间转换c#

    简要 本篇文章主要介绍基于.net(c#)封装的时间帮助类.主要功能是将时间戳与DateTime类型相互转换. 1.其中包括将毫秒级时间戳(13位).秒级时间戳(10位)转换为DateTime. 2. ...

  10. 用maven整合SSM中jsp运行报404和500问题解决方案

    如果代码检查没有错误,建议更改maven版本,可以改为maven-3.6.1 网址:https://archive.apache.org/dist/maven/maven-3/ 选择3.6.1 再点击 ...