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] 字符串切片

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容