首页 > 其他分享 > pytest--测试函数

pytest--测试函数

时间:2022-11-11 15:14:37浏览次数:77  
标签:tests -- py mark passwd pytest 测试函数 test

参考链接
https://docs.python.org/zh-cn/3/reference/simple_stmts.html?highlight=assert#grammar-token-assert_stmt

断言 assert

在 pytest 中,assert 是编写测试的最基础工具。如
assert a == b
assert a <= b

捕获异常 pytest.raises()

在测试过程中,经常需要测试是否如期抛出预期的异常,以确定异常处理模块生效。在 pytest 中使用 pytest.raises() 进行异常捕获:

# test_raises.py

def test_raises():
    with pytest.raises(TypeError) as e:
        connect('localhost', '6379')
    exec_msg = e.value.args[0]
    assert exec_msg == 'port type must be int'

运行结果

$ pytest test_raises.py
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0
rootdir: F:\self-repo\learning-pytest, inifile:
collected 1 item

tests\test-function\test_raise.py .                                      [100%]

========================== 1 passed in 0.07 seconds ===========================

标记函数 ::

pytest 查找测试策略

默认情况下,pytest会递归查找当前目录下所有已 test 开始或者结尾的python脚本,并执行文件内的所有以 test 开始或者结束的函数和方法

标记测试函数

由于某种原因,(如test_func2的功能尚未开发完成),我们只想执行指定的测试函数。
在pytest中有几种方式可以解决:

  1. 第一种,显示的指定函数名,通过::标记
    $ pytest tests/test-function/test_no_mark.py::test_func1
  2. 使用模糊匹配,使用 -k 选项标识
    $ pytest -k func1 tests/test-function/test_no_mark.py

注解:
以上两种方法,第一种一次只能指定一个测试函数,当要进行批量测试时无能无力;
第二种方法,可以批量操作,但需要所有测试的函数名包含相同的模式,也不方便

  1. 使用 pytest.mark 在函数上进行标记
# test_with_mark.py

@pytest.mark.finished
def test_func1():
    assert 1 == 1

@pytest.mark.unfinished
def test_func2():
    assert 1 != 1

测试时使用 -m 选择标记的测试函数:

$ pytest -m finished tests/test-function/test_with_mark.py
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0
rootdir: F:\self-repo\learning-pytest, inifile:
collected 2 items / 1 deselected

tests\test-function\test_with_mark.py .                                  [100%]

=================== 1 passed, 1 deselected in 0.10 seconds ====================

使用mark,我们可以给每个函数打上不同的标记,测试时指定就可以允许所有被标记的函数。

一个函数可以打上多个标记;多个函数也可以打相同的标记。
运行测试时使用 -m 选项可以加上逻辑。如:
$ pytest -m "finished and commit"
$ pytest -m "finished and not merged"

跳过测试 pytest.mark.skip

对于那些未完成开发的测试,最好的处理方式就是略过,而不是执行测试。
通过标记指定要跳过的测试 pytest.mark.skip

# test_skip.py

@pytest.mark.skip(reason='out-of-date api')
def test_connect():
    pass

执行结果可以看到该测试已被忽略:

$ pytest tests/test-function/test_skip.py
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0
rootdir: F:\self-repo\learning-pytest, inifile:
collected 1 item

tests\test-function\test_skip.py s                                       [100%]

========================== 1 skipped in 0.13 seconds ==========================

Pytest 还支持使用 pytest.mark.skipif 为测试函数指定被忽略的条件。

@pytest.mark.skipif(conn.__version__ < '0.2.0',
                    reason='not supported until v0.2.0')
def test_api():
    pa

预见的错误 pytest.mark.xfail

如果我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示。
pytest使用 pytest.mark.xfail 实现预见错误功能:

# test_xfail.py

@pytest.mark.xfail(gen.__version__ < '0.2.0',
                   reason='not supported until v0.2.0')
def test_api():
    id_1 = gen.unique_id()
    id_2 = gen.unique_id()
    assert id_1 != id_2

执行结果:

$ pytest tests/test-function/test_xfail.py
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0
rootdir: F:\self-repo\learning-pytest, inifile:
collected 1 item

tests\test-function\test_xfail.py x                                      [100%]

========================== 1 xfailed in 0.12 seconds ==========================

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

参数化

当对一个测试函数进行测试时,通常会给函数传递多组参数。比如测试账号登录,我们需要模拟各种千奇百怪的账号密码。
当然,我们可以把这些参数写在测试函数内部进行遍历,不过虽然参数众多,但仍然是一个测试,当某组参数导致断言失败,测试也就终止了。

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

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

这里是一个密码长度的测试函数,其中参数名为 passwd,其可选列表含三个值:

# test_parametrize.py

@pytest.mark.parametrize('passwd',
                      ['123456',
                       'abcdefdfs',
                       'as52345fasdf4'])
def test_passwd_length(passwd):
    assert len(passwd) >= 8

运行可知执行了三次测试:

$ pytest tests/test-function/test_parametrize.py
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0
rootdir: F:\self-repo\learning-pytest, inifile:
collected 3 items

tests\test-function\test_parametrize.py F..                              [100%]

================================== FAILURES ===================================

再看一个多参数的例子,用于校验用户密码:

# test_parametrize.py

@pytest.mark.parametrize('user, passwd',
                         [('jack', 'abcdefgh'),
                          ('tom', 'a123456a')])
def test_passwd_md5(user, passwd):
    db = {
        'jack': 'e8dc4081b13434b45189a720b77b6818',
        'tom': '1702a132e769a623c1adb78353fc9503'
    }

    import hashlib

    assert hashlib.md5(passwd.encode()).hexdigest() == db[user]

使用 -v 执行测试

$ pytest -v tests/test-function/test_parametrize.py::test_passwd_md5
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 -- c:\anaconda3\python.exe
cachedir: .pytest_cache
rootdir: F:\self-repo\learning-pytest, inifile:
collected 2 items

tests/test-function/test_parametrize.py::test_passwd_md5[jack-abcdefgh] PASSED [ 50%]
tests/test-function/test_parametrize.py::test_passwd_md5[tom-a123456a] PASSED [100%]

========================== 2 passed in 0.04 seconds ===========================

如果觉得每组测试的默认参数显示不清晰,我们可以使用 pytest.param 的 id 参数进行自定义。

# test_parametrize.py

@pytest.mark.parametrize('user, passwd',
                         [pytest.param('jack', 'abcdefgh', id='User<Jack>'),
                          pytest.param('tom', 'a123456a', id='User<Tom>')])
def test_passwd_md5_id(user, passwd):
    db = {
        'jack': 'e8dc4081b13434b45189a720b77b6818',
        'tom': '1702a132e769a623c1adb78353fc9503'
    }

    import hashlib

    assert hashlib.md5(passwd.encode()).hexdigest() == db[user]

现在的执行结果为:

$ pytest -v tests/test-function/test_parametrize.py::test_passwd_md5_id
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 -- c:\anaconda3\python.exe
cachedir: .pytest_cache
rootdir: F:\self-repo\learning-pytest, inifile:
collected 2 items

tests/test-function/test_parametrize.py::test_passwd_md5_id[User<Jack>] PASSED [ 50%]
tests/test-function/test_parametrize.py::test_passwd_md5_id[User<Tom>] PASSED [100%]

========================== 2 passed in 0.07 seconds ===========================

标签:tests,--,py,mark,passwd,pytest,测试函数,test
From: https://www.cnblogs.com/polly-ling/p/16879855.html

相关文章

  • Sublime如何在每一行行首增加字符串
    第一步:选中全部内容ctrl+A第二步:进入待操作状态ctrl+shift+L第三步:通过←和→控制光标的位置第四步:在光标处添加内容注:也可以只对多行进行操作,对多行进行操作只需在......
  • HTTP代理购买如何选套餐
    爬虫工作离不开HTTP代理的支持,选择合适的HTTP代理套餐可以让工作事半功倍,但网上各种各样的套餐实在是太多了,太难选择了,爬虫业务千千万,对HTTP代理的需求都不一样,因此,针......
  • DataLoader 每次迭代返回BatchEncoding还是dict类型依pytorch的版本而定
    发现DataLoader在不同的pytorch版本上,执行dataset的__item__会返回不同的效果。pytorch在1.12.1上,每一次迭代会返回BatchEncoding这个类型(可能会比这个版本低也......
  • Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境
    前文已经初始化了workspace-root,从本文开始就需要依次搭建组件库、example、文档、cli。本文内容是搭建组件库的开发环境。1packages目录前面在项目根目录下创建了p......
  • Unity一键制作预制体Prefab一键修改Prefab属性
    1.适用于制作多个预制体(一个模型文件下面几百个子物体,都需要制作成预制体,这一个一个拖不是要炸裂)模型资源如下图 2.模型先放到Resources文件夹下面方便读取,制作......
  • 用(Atomic原子类 使用)实现自增
    //静态变量存储最大值privatestaticfinalAtomicIntegeratomicNum=newAtomicInteger();privatestaticfinalIntegerINIT_CODE_NUM=0;publicStringgetCode......
  • 镜像仓库 Harbor搭建和使用教程
     架构Docker搭建yumupdateyuminstall-yyum-utilsdevice-mapper-persistent-datalvm2yum-config-manager--add-repohttp://mirrors.aliyun.com/docker-ce/l......
  • 实验7:基于REST API的SDN北向应用实践
    实验7:基于RESTAPI的SDN北向应用实践一、实验目的1.能够编写程序调用OpenDaylightRESTAPI实现特定网络功能;2.能够编写程序调用RyuRESTAPI实现特定网络功能。二、实......
  • java通过cglib动态生成实体bean的操作
    转载自:https://www.jb51.net/article/205882.htm maven依赖:12345678910<dependency>      <groupId>commons-beanutils</groupId>   ......
  • Mysql数据库函数-单行函数
    一.单行函数:可以理解为向函数传入一个参数,返回一个值。单行函数是指对每一题记录输入值进行计算,并得到相应的计算结果,然后返回给用户,也就是说,每条记录作为一个输入参数,经......