Pytest笔记

从年底换工作就没怎么写学习笔记了,期间在公司边学边用了 Android Python 过年在家看了iOS,还是b站神奇,竟然还有黑马的全套iOS视频,很nice ,就算纯小白应该也能看懂了,然后是最近老大要看pytest框架,国内查到的资料真不多,基本都是国外stack或别的地方写的example,记一下笔记:

Pytest

常用命令:
pytest --collect-only 只收集用例不执行测试

Pytest收集testcase

默认查找以test_开头和_test结尾的.py文件
从这些文件中查找以test开头的方法,包括 Test开头的类中的test* 方法
识别以test.开头的所有方法、类

Pytest fixtures

1.用作不同 testcase之间共享数据
在文件夹中创建conftest.py 将 fixture方法放在conftest中 则该文件夹下所有的testcase都可以使用该fixture
2.实现unittest等框架类似的 setUp tearDown()方法
通过在 [pytest.fixture]中指定 scope 参数来设置:@pytest.fixture(scope="module")

  • function —— 函数级,即调用每个测试函数前,均会重新生成 fixture
  • class —— 类级,调用每个测试类前,均会重新生成 fixture
  • module —— 模块级,载入每个测试模块前,均会重新生成 fixture
  • package —— 包级,载入每个包前,均会重新生成 fixture
  • session —— 会话级,运行所有用例前,只生成一次 fixture
import pytest
import smtplib

@pytest.fixture(scope="module")
def smtp_connection():
    return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

yield smtp_connection 及前面的语句相当于测试前置,通过 yield 返回准备好的测试资源 smtp_connection; 而后面的语句则会在用例执行结束(确切的说是测试夹具的生效级别的声明周期结束时)后执行,相当于测试清理

Pytest 用例执行顺序

Pytest mark

skip:
skips a test unconditionally.
无条件跳过一个用例

skipif:
skips a test if the expression passed to it evaluates to True.
如果判断条件为真 则跳过

xfail:
indicates that a test is expected to fail, so if the test does fail, the overall suite can still result in a passing status.
显式的声明一个用例会失败,如果确实失败,则测试结果显示为通过

parametrize:
(note the spelling) creates multiple variants of a test with different values as arguments.
创建多个变量组为参数

Pytest 参数化

参数换成 pytest.param,我们还可以有更高阶的玩法,比如知道最后一组参数是失败的,所以将它标记为 xfail:

@pytest.mark.parametrize(
    "test_input,expected",
    [("3+5", 8), ("2+4", 6), pytest.param("6*9", 42, marks=pytest.mark.xfail)],
)
def test_eval(test_input, expected):
    assert eval(test_input) == expected

下面的示例中会分别把 x=0/y=2、x=1/y=2、x=0/y=3和x=1/y=3带入测试函数,视作四个测试用例来执行。

如果测试函数的多个参数的值希望互相排列组合,我们可以这么写:@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
    pass复制代码上述示例中会分别把 x=0/y=2、x=1/y=2、x=0/y=3和x=1/y=3带入测试函数,视作四个测试用例来执行。

参数化例子3:

testdata = [
    (datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
    (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
]
​
​
@pytest.mark.parametrize("a,b,expected", testdata)
def test_timedistance_v0(a, b, expected):
    diff = a - b
    assert diff == expected

Pytest 其他

Test class中 test开头的case如果有参数,怎么避免自动附带self参数的问题
pytest --durations=3 用来获取耗时最慢的3 个 testcase

with pytest.raises(TypeError):
...
预期pytest 抛出指定异常

pytest 使用 . 标识测试成功(PASSED)

pytest 使用 s 表示测试被跳过(SKIPPED)

pytest 使用 F 标识测试失败(FAILED)

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

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

可以使用 -v 选项,显示测试的详细信息

第一种,显式指定函数名,通过 :: 标记。

$ pytest tests/test-function/test_no_mark.py::test_func1

第二种,使用模糊匹配,使用 -k 选项标识。

pytest -k func1 tests/test-function/test_no_mark.py

第三种,使用 pytest.mark 在函数上进行标记。

带标记的测试函数如:

@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

跳过测试:@pytest.mark.skip(reason='out-of-date api')

参数化:

每组参数都独立执行一次测试。使用的工具就是 pytest.mark.parametrize(argnames, argvalues)

# test_parametrize.py

@pytest.mark.parametrize('passwd',

['123456',

'abcdefdfs',

'as52345fasdf4'])

def test_passwd_length(passwd):

assert len(passwd) >= 8

@allure.step(“登陆”)

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

可以将数据库连接 或测试环境准备初始化等操作 放在 fixture 中

该测试函数执行完毕也会执行一遍 fixture

二者用 yield 关键字进行分隔,即

Fixture 标记函数yield之前的内容 在 测试函数之前运行 即。Setup

。。。。。。。。。。之后的内容 在之后运行, 即 Teardown

@pytest.fixture()

def some_data():

return 42

def test_some_data(some_data): //将 fixture标记 的 函数作为 测试函数 testxx 的参数

assert some_data == 42

如果测试函数的参数列表中包含fixture修饰的函数名字,那么pytest能检测到,先搜索该测试所在的模块,再去。conftest.py 中搜索

pytest --alluredir=/Users/tf/Desktop/PycharmProject/Pytest/Demo/Report

Purest -s 参数 可以在命令行显示 print 语句的输出

conftest.py

import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call':

always add url to report

extra.append(pytest_html.extras.url('http://www.example.com/')))
xfail = hasattr(report, 'wasxfail')
if (report.skipped and xfail) or (report.failed and not xfail):

only add additional html on failure

extra.append(pytest_html.extras.html('

Additional HTML'))

report.extra = extra

string[::-1] 字符串切片

你可能感兴趣的:(Pytest笔记)