0


Pytest全栈自动化测试指南-入门

Pytest介绍

Pytest是一个成熟的全功能Python测试工具,可以帮助您编写更好的程序。该pytest框架使编写可读测试变得容易,并且可以扩展以支持应用程序和库的复杂功能测试。pytest需要:Python 3.7+ 或 PyPy3。

Pytest特点

开箱即用.自动发现测试用例简化断言语句,统一为assert丰富的插件架构,超过 800 多个外部插件具有灵活的扩展性和方便的参数化方法

安装&使用

$ pip install  pytest
$ pytest --version
pytest 7.1.2

命名规则&断言

  1. 模块:test_*.py 或*_test.py。
  2. 函数:test*。
  3. 类:Test*,测试类不能有init函数。
  4. 断言:assert ,支持所有python的布尔表达式

用例执行顺序

  1. 在包含用例的项目根路径下(root-dir)执行:pytest -v
  2. 目录和py文件:按照ascii码排序方式,进行文件递归顺序收集和运行
  3. py文件中:按照代码从上到下
  4. 验证执行顺序:pytest --collect-only

命令行选项

pytest
pytest

assert 布尔表达式

  • 比较运算符:【>】【<】【<=】【>=】【==】【!=】 例如:assert actual == expected
  • 身份和成员运算符: 【is】、【is not】、【in】、【not in】 例如: assert expected in actual
  • 逻辑运算符和布尔函数:【not】【and】【or】【startswith()】 例如 :assert not expected 例如 :assert version.startswith(“3.8”)

待测student功能

# ---------------------------------student.py--------------------------------------# 以字典的形式返回学生的姓名和成绩defstudent_score():return{'小明':99,'小红':100}# 以列表的形式返回学生的姓名defstudent_name():return['小明','小红']

编写pass 与fail 用例

# ---------------------------------test_01_pass_fail.py---------------------------# 这是通过用例deftest_pass():# 期望值
    expected =1# 实际值
    actual =1# 通过(实际值)跟(预期值)进行相等比较,相等通过,不相等报错assert actual == expected

# 这是失败,不通过用例deftest_fail():# 期望值
    expected =2# 实际值
    actual =3# 通过(实际值)跟(预期值)进行相等比较,相等通过,不相等报错assert actual == expected
    
# ---------------------------------test_02_datatype.py----------------------------from btest.Day1.student import student_score, student_name

# 这是student_score的验证全数据等式用例deftest_student_score():# 期望值
    expected ={'小红':100,'小明':99}# 实际值
    actual = student_score()# 通过(实际值)跟(预期值)进行相等比较,相等通过,不相等报错assert actual == expected

# 这是student_score 的验证部分数据等式用例# 验证小红是否等于100,是:pass 、否:faildeftest_student_score_other():# 期望值
    expected =100# 实际值
    actual = student_score()['小红']# 通过(实际值)跟(预期值)进行相等比较,相等通过,不相等报错assert actual == expected

# 这是student_name 的包含用例:# 验证小明是否在学生姓名列表中,是:pass(通过), 否:fail(失败)deftest_student_name():# 期望值
    expected ='小明123123'# 实际值
    actual = student_name()# 通过判断(预期数据)是否在实际数据中,在:pass,不在:failassertlen(actual)==2assert expected in actual

多断言

# ---------------------------------test_03_many_assert.py-------------------------# 安装: pip install pytest-assume -i https://pypi.douban.com/simplefrom pytest_assume.plugin import assume

from btest.Day1.student import student_score

deftest_student_score_hard():
    actual = student_score()with assume:# 实际数据类型是否跟预期数据类型一致。assertisinstance(actual,dict)with assume:# 实际的数据长度是否跟预期长度相同assertlen(actual)==3with assume:# 预期数据是否在实际数据内assert'小红123123'in actual

    with assume:# 实际数据是否等于预期数据assert actual['小红']==60

自定义异常信息

# ---------------------------------test_04_custom_fail.py-------------------------import pytest
from pytest_assume.plugin import assume

from btest.Day1.student import student_name

deftest_student_name_hard_custom_fail():
    actual = student_name()with assume:# 实际的数据长度是否跟预期长度相同assertlen(actual)==3, \
            f"实际数据长度:{len(actual)} 与预期数据长度:{3}不相同!!"with assume:# 预期数据是否在实际数据内assert'小红'in actual, \
            f"预期数据:{'小红'}没在实际数据中:{actual}!!"if'小乐'notin actual:
        pytest.fail(f"预期数据:小乐,没有在实际数据{actual}中")

处理异常

# ---------------------------------test_05_exceptions.py--------------------------import pytest

from btest.Day1.student import student_score

# 通用try/finally 处理用例异常deftest_student_score_error():
    actual = student_score()try:
        actual['小红']= actual['小红']+'10'except:passfinally:assert'小乐'in actual,"小乐没有在学生成绩表里!!"# pytest用例异常处理deftest_student_score_raise():
    actual = student_score()with pytest.raises(Exception):# 更具可读性且不易出错。
        actual['小红']= actual['小红']+'10'# assert '小乐' in actual # 不会执行# 会执行assert'小乐'in actual, \
        f" 预期数据:小乐,没有在实际数据中{actual}!!"# ---------------------------------test_06_get_error.py---------------------------"""
1、获取用例的所在的模块、
2、获取用例的名称、
3、获取用例的具体错误信息。
"""import inspect  # 从实时 Python 对象中获取有用的信息import pytest

# python-inspect 捕获详细异常信息deftest_inspect_info():# 期望值为 模块名::用例名::错误信息
    expected ='test_06_get_error::test_inspect_info::division by zero'with pytest.raises(Exception)as exc_info:
        c =2/0# 获取错误文本:exc_info.value.args[0]# 如获取错误类型:exc_info.type
    error_info = exc_info.value.args[0]# 获取用例具体错误信息

    module_name = inspect.getmodulename(__file__)# 获取用例所在模块
    method_name = inspect.stack()[0][3]# [0][3]获取用例名字,[1][4][0]获取用例名字和参数

    actual =f"{module_name}::{method_name}::{error_info}"assert actual == expected

# Pytest内置功能捕获异常信息deftest_get_raises(request):# 期望值为 模块名::用例名::错误信息
    expected ='test_06_get_error::test_get_raises::division by zero'with pytest.raises(Exception)as exc_info:
        c =2/0

    error_info = exc_info.value.args[0]

    module_name = request.module.__name__.split('.')[-1]# 获取模块 包名.test_06xxx
    method_name = request.function.__name__  # 获取用例名字
    actual =f"{module_name}::{method_name}::{error_info}"assert actual == expected

数据类

Dataclass这个模块提供了一个类装饰器和一些函数,用于自动添加生成的 special method,例如 init() 和 repr() 到用户定义的类。 它最初描述于 PEP 557 .

对标准库的补充,称为数据类。可以将数据类视为“具有默认值的可变命名元组”

数据类使用普通的类定义语法,你可以自由地使用继承、元类、文档字符串、用户定义的方法、类工厂和其他 Python 类特性.

装饰器: http://www.ztloo.com/2021/11/06/decorators/

Python术语对照社区文档: https://docs.python.org/zh-cn/3/glossary.html?highlight=decorator

special method(特殊方法) :https://docs.python.org/zh-cn/3/glossary.html#term-special-method

PEP 557(Python 增强建议) :https://www.python.org/dev/peps/pep-0557

标准库:https://docs.python.org/zh-cn/3/library/index.html

命名元组: https://docs.python.org/zh-cn/3/library/collections.html?highlight=namedtuple

# ---------------------------------face_to_object.py------------------------------from dataclasses import asdict, dataclass, astuple, replace

# https://docs.python.org/3/library/dataclasses.html?highlight=dataclass#module-dataclasses@dataclassclassGirlFriend:# 节省了__init__函数
    name:str
    age:int
    height:int=170# cm
    weight:int=50# kg@classmethoddeffrom_dict(cls, d):return GirlFriend(**d)defto_dict(self):return asdict(self)defto_tuple(self):return astuple(self)defupdate(self,**changes):return replace(self,**changes)if __name__ =='__main__':# 把字典转行成类对象
    ym_dict ={'name':'杨幂','age':18,'height':170,'weight':68}
    ym = GirlFriend.from_dict(ym_dict)print('我是类对象型杨幂', ym)# 把类对象转化成字典
    ym_dict = ym.to_dict()print('我是字典型杨幂:', ym_dict)# 把类对象转化成元组
    ym_tuple = ym.to_tuple()print(f'我是元组型杨幂:{ym_tuple}')# 把杨幂修改成刘亦菲
    lyf = ym.update(name='刘亦菲', age=22)print(f'我是刘亦菲:{lyf}')

自定义辅助断言函数

import pytest

from btest.Day2.face_to_object import GirlFriend

defassert_identical(gf_1, gf_2):if gf_1.name != gf_2.name:
        pytest.fail(f"name不匹配. {gf_1.name} != {gf_2.name}")deftest_identical():
    gf_1 = GirlFriend("刘亦菲",18,170,60)
    gf_2 = GirlFriend("刘亦菲",18,170,60)
    assert_identical(gf_1, gf_2)

更多案例,更多内容,请点击: https://edu.csdn.net/course/detail/37237


本文转载自: https://blog.csdn.net/arron_12/article/details/127705153
版权归原作者 百里图书 所有, 如有侵权,请联系我们删除。

“Pytest全栈自动化测试指南-入门”的评论:

还没有评论