Pytest

安装pytest
#安装pytest
pip install pytest
#检查是否安装
pytest --version
创建第一个测试
def func(x):
return x + 1 def test_answer():
assert func(3) == 5
运行多个测试
pytest将运行当前目录及其子目录中所有 test_*.py 或 *_test.py 形式的文件。更一般地说,它遵循标准测试发现规则。
pytest实施以下标准测试发现: 如果未指定参数,则收集从testpaths (如果配置)或当前目录开始。或者,命令行参数可以用于目录、文件名或节点 ID 的任意组合。 递归到目录,除非它们匹配norecursedirs. 在这些目录中,搜索test_*.py或文件,通过其测试包名称*_test.py导入。 从这些文件中收集测试项目: test在类之外添加前缀测试函数或方法。 test带前缀的测试类中带前缀的测试函数或方法Test(没有__init__方法)。@staticmethod用和修饰的方法@classmethods也被考虑。
断言引发了某个异常
#使用raises帮助器来断言某些代码引发异常
import pytest def f():
raise SystemExit(1) def test_mytest():
with pytest.raises(SystemExit):
f()
将多个测试分组到一个类中
class TestClass:
def test_one(self):
x = "this"
assert "h" in x def test_two(self):
x = "hello"
assert hasattr(x, "check") #pytest发现遵循Python 测试发现约定 的所有测试,因此它会找到两个test_带前缀的函数。不需要对任何内容进行子类化,但请确保在您的类中添加前缀Test,否则该类将被跳过。我们可以通过传递文件名来简单地运行该模块:
断言方法来验证异常是否被正确处理
import pytest  

def test_exception_handling():
try:
# 模拟除以零的异常
1 / 0
except ZeroDivisionError:
# 验证是否捕获了除以零的异常
assert True
else:
# 如果上面的代码块没有引发异常,测试将失败
assert False #在这个示例中,我们使用 try-except 块来捕获除以零的异常。如果异常被捕获,我们使用 assert True 来验证异常被正确处理。如果上面的代码块没有引发异常,我们将使用 assert False 来确保测试失败。
标记函数

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

使用pytest.mark在函数上进行标记

@pytest.mark.finished
def test_func1():
assert 1 == 1 @pytest.mark.unfinished
def test_func2():
assert 1 != 1 # pytest -m finished .\test_demo5.py 使用mark,我们可以给每个函数打上不同的标记,测试时指定就可以运行所有被标记的函数
一个函数可以打多个标记,多个函数也可以打相同的标记
$ pytest -m "finished and commit" $ pytest -m "finished and not merged"
跳过测试

对于那些尚未开发完成的测试,最好的处理方式就是略过而不执行测试

Pytest 使用特定的标记 pytest.mark.skip


import pytest @pytest.mark.skip(reason='out-of-date api')
def test_connect():
pass """
这是一个使用pytest标记的测试函数,使用了@pytest.mark.skip装饰器,表示这个测试函数将被跳过,不执行。标记参数reason的值为'out-of-date api',表示跳过的原因是由于使用了过时的API。
"""
预见的错误

若我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示

pytest使用pytest.mark.xfail实现预见错误功能

@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 使用 x 表示预见的失败(XFAIL)。 如果预见的是失败,但实际运行测试却成功通过,pytest 使用 X 进行标记(XPASS)。
"""
参数化

当对一个测试函数进行测试时,通常会给函数传递多组参数。比如测试账号登录,我们需要模拟各种千奇百怪的账号密码

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

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

# 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]
什么是固件

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

我们可以利用固件做任何事情,其中最常见的可能就是数据库的初始链接和最后关闭操作

pytest使用pytest.fixture()定义固件,

@pytest.fixture()
def postcode():
return '010' def test_postcode(postcode):
assert postcode == '010' """
固件可以直接定义在各测试脚本中,就像上面的列子。更多时候,我们希望一个固件可以在更大程度上复用,这就需要对固件进行集中管理。Pytest使用文件conftest.py集中管理固件
"""
在复杂的项目中,可以在不同的目录层级定义 conftest.py,其作用域为其所在的目录和子目录。
不要自己显式调用 conftest.py,pytest 会自动调用,可以把 conftest 当做插件来理解。
预处理和后处理
很多时候需要在测试前进行预处理(如新建数据库链接),并在测试完成后进行清理(关闭数据库连接)
当有大量重复的这类操作,最佳实践就是使用固件来自动化所有预处理和后处理
pytest使用 yield关键词将固件分为俩部分,yield之前的代码属于预处理,会在测试前执行;
yield之后的代码属于后处理,将在测试完成后执行 @pytest.fixture()
def db():
print('Connection successful') yield print('Connection closed') def search_user(user_id):
d = {
'001': 'xiaoming'
}
return d[user_id] def test_search(db):
assert search_user('001') == 'xiaoming'
自动执行

目前为止,所有的固件的使用都是手动指定,或者作为参数,或者使用usefixtures

如果我们想让固件自动执行,可以在定义时指定autouse参数

下面是两个自动计时固件,一个用于统计每个函数运行时间(function 作用域),一个用于计算测试总耗时(session 作用域):

import pytest,time
DATE_FORMAT = '%Y-%m-%d %H:%M:%S' @pytest.fixture(scope='session', autouse=True)
def timer_session_scope():
start = time.time()
print('\nstart: {}'.format(time.strftime(DATE_FORMAT, time.localtime(start)))) yield finished = time.time()
print('finished: {}'.format(time.strftime(DATE_FORMAT, time.localtime(finished))))
print('Total time cost: {:.3f}s'.format(finished - start)) @pytest.fixture(autouse=True)
def timer_function_scope():
start = time.time()
yield
print(' Time cost: {:.3f}s'.format(time.time() - start)) def test_1():
time.sleep(1) def test_2():
time.sleep(2) #pytest -s test_demo.py
重命名

固件的名称默认为定义时的函数名,如果不想使用默认,可以通过name选项指定名称

@pytest.fixture(name='age')
def calculate_average_age():
return 28 def test_age(age):
assert age == 28
如何参数化夹具和测试功能

@pytest.mark.parametrize允许在测试函数或类中定义多组参数和装置

内置的pytest.mark.parametrize装饰器可以对测试函数的参数进行参数化

import pytest

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

@pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])
class TestClass:
def test_simple_case(self, n, expected):
assert n + 1 == expected def test_weird_simple_case(self, n, expected): assert (n * 1) + 1 == expected
对特定参数应用间接方法

参数化常常使用多个参数名称,indirect对特定参数应用参数。可通过将参数名称的列表或元组传递给来完成indirect。

import pytest

@pytest.fixture(scope="function")
def x(request):
return request.param * 3 @pytest.fixture(scope="function")
def y(request):
return request.param * 2 @pytest.mark.parametrize("x, y", [("a", "b")], indirect=["x"])
def test_indirect(x, y):
assert x == "aaa"
assert y == "b"

pytest参数化及应用的更多相关文章

  1. pytest「conftest、pytest参数化、重运行、出测试报告」

    文章总览图 一.conftest问题整理: 1.这个conftest.py分路径吗?如果在TestCases下建这个包可以直接用吗? TestCases这里有ModeA和ModeB,想在ModeA或M ...

  2. 『德不孤』Pytest框架 — 15、Pytest参数化

    目录 1.Pytest参数化说明 2.Pytest参数化方式 3.parametrize装饰器参数说明 4.Pytest参数化(单个参数) 5.Pytest参数化(多个参数) 6.ids参数说明 1. ...

  3. pytest参数化 parametrize

    pytest.mark.parametrize装饰器可以实现测试用例参数化 parametrizing 1.这里是一个实现检查一定的输入和期望输出测试功能的典型例子 # content of test ...

  4. pytest参数化代码笔记

    #!/usr/local/bin/python3 # -*- coding: utf-8 -*- import pytest __author__ = "Carp-Li" __da ...

  5. pytest参数化

    Pytest可以在多个级别上实现测试参数化 一.@pytest.fixture装饰器调用参数 示例 import pytest from selenium import webdriver from ...

  6. Pytest 学习(二十五)- 解决pytest参数化测试标题都一样问题

    前言 使用参数化测试化后,allure的报告如下显示: 源代码如下: # -*- coding: utf-8 -*- # @Time : 2020/12/13 17:27 # @Author : lo ...

  7. Python基础之pytest参数化

    上篇博文介绍过,pytest是目前比较成熟功能齐全的测试框架,使用率肯定也不断攀升.在实际 工作中,许多测试用例都是类似的重复,一个个写最后代码会显得很冗余.这里,我们来了解一下 @pytest.ma ...

  8. pytest参数化的两种方式

    1.传统方式 import requests,pytest from Learning.variable import * # 定义变量 #url = "https://www.baidu. ...

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

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

  10. 【PYTEST】第三章参数化

    知识点: 参数化 1. parametrize() 参数化测试用例 实际工作中,我们不可能就传一组数据,参数化支持多组数据测试,并且每组都会去执行,parametrize(), 第一个参数用逗号开分隔 ...

随机推荐

  1. PVE 下虚拟机 Ubuntu 无法进入恢复模式的解决方案——提取原有系统文件

    问题说明 某天重启虚拟机 Ubuntu,发现虚拟机只有容器IP,桥接的接口在虚拟机显示状态为 DOWN: 想重启进入恢复模式,却发现恢复模式一直花屏,无法使用: 没有办法了,只能想办法提取原有系统内原 ...

  2. 第五周阅读笔记|人月神话————胸有成竹(Calling the Shot)

    这个章节标题是胸有成竹,而要做到胸有成竹就必须在项目计划阶段我们对项目的预测和估算都需要很准确.因此整个章节的内容就是在讲估算,而估算就涉及到预测和估算模型,估算要做到准确必须通过前期多个历史项目和版 ...

  3. Codeforces Round #691 (Div. 2) D - Glass Half Spilled(DP)

    题目 补下因实验漏掉的CF(还以为是晚上,没想到是下午开始).前三题过的很顺利,到D题时想了会发现数据很小爆搜貌似能过,就以为是道水题,交了一发T了,胡乱加了点剪枝还是T.逐渐意识到事情的严重性.考虑 ...

  4. 使用咱们公司的DataInside可视化产品配置了一个教育行业的大屏展示软件

    今天在公司用配置了一个可视化大屏软件,大家觉得如何?

  5. 我理解的null和“ “,希望大家给予更正。

    我认为null是零的意思,就是没有任何的东西,比如说文件的读取中,没有任何的东西就是null,刚刚用new String创建的String里面有一个引用,所以它不为null,如果用String h=& ...

  6. Head First Java学习:第七章-继承和多态

    第七章:继承和多态 1. 覆盖(override) 覆盖的意思是由子类重新定义继承下来的方法,以改变或延伸此方法的行为. 2. 继承(extends) 类的成员:实例变量+方法 实例变量无法覆盖是因为 ...

  7. 2018年长沙理工大学第十三届程序设计竞赛 G 题:逃离迷宫

    题目链接:https://www.nowcoder.com/acm/contest/96/G 思路:两遍bfs,找到p到k的情况,记录时间:找到E到k的情况,记录时间.题目超时点在于输入需要用scan ...

  8. Arrarylist集合的使用

    前提:最近JAVA实训课老师讲了一些Arrarylist集合的相关知识,刚好端午假期有空就把这课上学到的知识和自己碰到的一些问题总结下来. 一.Arrarylist集合的使用(以学生信息存储作为演示) ...

  9. 【1】从零玩转OSS阿里云存储服务之阿里云平台等操作-1-cong-ling-wan-zhuan-oss-a-li-yun-cun-chu-fu-wu-zhi-a-li-yun-ping-tai-deng-cao-zuo

    title: [1]从零玩转OSS阿里云存储服务之阿里云平台等操作 date: 2021-06-09 17:21:12.037 updated: 2021-12-26 17:43:18.92 url: ...

  10. tty详解

    linux下tty命令详解 [功能] 打印连接到标准输入的终端的文件名. [描述] 命令项: -s, --silent, --quiet: 什么也不打印,只是返回退出状态码. --help: 打印帮助 ...