从年底换工作就没怎么写学习笔记了,期间在公司边学边用了 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] 字符串切片