Python测试工具-Pytest使用详解

这篇具有很好参考价值的文章主要介绍了Python测试工具-Pytest使用详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

Pytest是一个全功能Python测试工具,支持第三方扩展插件,能够使用其开展单元测试和复杂功能测试。可以和selenium、requests、appium等模块结合使用实现WEB UI、API、APP自动化测试。
详见参考指南文档:https://docs.pytest.org/en/7.1.x/#
PDF文档 : https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf

二、安装

0、前提:已安装配置好Python 3.7+环境
1、安装:在命令行或Pycharm终端中运行命令 pip install pytest
2、验证:运行命令 pytest --version,会显示已安装的pytest版本号

三、使用

1、Pytest发现测试用例的规则

  • py文件以test_开头或者_test结尾;
  • 类名以Test开头;
  • 测试用例以test_开头。

python pytest,测试笔记,python,测试工具,pytest,自动化

2、Pytest基础运行

按照Pytest发现用例规则编写用例直接运行,便能够调用Pytest收集符合规则的测试用例,执行用例,打印执行情况等信息。

"""
   Pytest运行demo
"""

class TestPytest():
    """测试Pytest类"""

    def test_001(self):
        """test_001"""
        print("test_001")
        assert 1 == 1

    def test_002(self):
        """test_002"""
        print("test_002")
        assert 1 < 2

    def test_003(self):
        """test_003"""
        print("test_003")
        assert 1 != 2

    def test_004(self):
        """test_004"""
        print("test_004")
        assert 1 == 0

下图中红框部分给出了测试结果信息,包含了每条用例的执行结果和耗时、通过和失败数量等;蓝色部分为启动信息;绿框部分呈现了执行过程、断言失败等信息。
python pytest,测试笔记,python,测试工具,pytest,自动化

3、常用功能

3.1 配置文件pytest.ini

pytest.ini文件优先于其他文件,即使是空的,执行的各类参数可在此文件进行配置,详见下文各示例内容。

3.2 执行参数

  • -v 显示详细的测试信息:pytest.main(['-v']),详细展示每条用例方法名称、结果、进度等信息
    python pytest,测试笔记,python,测试工具,pytest,自动化
  • -s 显示用例中打印信息:pytest.main(['-s'])
    python pytest,测试笔记,python,测试工具,pytest,自动化
  • -q 安静的输出,只显示运行的结果信息:pytest.main(['-q', '../Testcase/test_pytest_demo.py'])
    python pytest,测试笔记,python,测试工具,pytest,自动化- -n 多线程执行测试用例:pytest.main(['-vs', '../Testcase/test_pytest_demo.py','-n2']),n后面的数字为线程数,使用前需要安装pytest-xdist插件
    python pytest,测试笔记,python,测试工具,pytest,自动化
  • -m 执行指定标记的用例:pytest.main(['-m markName']),自定义的标记名称可在pytest.ini文件中进行注册才可以使用

python pytest,测试笔记,python,测试工具,pytest,自动化python pytest,测试笔记,python,测试工具,pytest,自动化python pytest,测试笔记,python,测试工具,pytest,自动化

  • –lf 重跑上次失败的用例:pytest.main(['-v', '../Testcase/test_pytest_demo.py', '--lf']),如果上次没有失败用例,则执行全部

python pytest,测试笔记,python,测试工具,pytest,自动化
python pytest,测试笔记,python,测试工具,pytest,自动化

  • –reruns=N 自动重跑失败用例N次:pytest.main(['-q', '--reruns=1', '../Testcase/test_pytest_demo.py'])

python pytest,测试笔记,python,测试工具,pytest,自动化

3.3 执行范围

  • 执行所有用例:pytest.main()
  • 执行指定目录的用例:pytest.main(['../Testcase'])
  • 执行指定模块的用例:pytest.main(['../Testcase/test_pytest_demo.py'])
  • 执行指定类的用例:pytest.main(['../Testcase/test_pytest_demo.py::TestPytest'])
  • 执行指定方法的用例:pytest.main(['../Testcase/test_pytest_demo.py::TestPytest::test_001'])
  • 另外,也可以通过pytest.ini配置执行用例时的搜索规则,示例:
[pytest]
testpaths = ../TestCase
python_files =  test_*.py
python_classes = Test*
python_functions = test_*

3.4 fixture装置

通过@pytest.fixture装饰器可以实现用例执行的前后置条件设置。在被装饰的方法中,通过yield的使用可实现前后置条件功能,yield具有return的返回功能,但yield后面的代码是可以被执行的(如果函数A有yield,执行时会被认为是一个生成器,函数A执行到yield时,会跳出函数A,去执行调用了A函数的代码段B,代码段B执行完后,继续回到函数A执行yield后的代码)。

fixture设置方式:

@pytest.fixture(scope=scope, params=Iterable[object], autouse=True, ids=Iterable[object], name=fixtureName)

  • scope:作用范围
    • function:默认作用域,用例级,测试用例结束时销毁夹装置(即执行yield后的代码);
    • class:作用于类,类中的最后一次测试结束时销毁装置;
    • module:作用于模块(.py文件),模块中最后一次测试销毁装置;
    • package:作用于python包,包中最后一次测试销毁装置;
    • session:作用于会话,会话中最后一次测试销毁装置。
  • params:参数,格式为元组或列表,参数的数量会决定执行的次数, 被装饰的方法需要继承request(非接口requests),使用request.param获取参数,每次获取一个;
  • autouse:自动调用设置,True/False,默认为False;
  • ids:测试ID,格式为元组或列表;
  • name:通过name可以设置装置名称,设置后调用需传入此名称。

fixture调用方式:

  • 方式1:直接作为参数传给测试用例调用
  • 方式2:通过装饰器调用 @pytest.mark.usefixtures('fixtureName1', 'fixtureName2')
  • 方式3:设置装置时,自动调用设为True @pytest.fixture(autouse=True)

fixture设置与调用示例代码:

"""
   Pytest fixture装置使用示例
"""
import pytest

@pytest.fixture
def human():
    """未设置参数,默认为用例级,谁调用谁享用"""
    name = '小明'
    print('前置条件:小明醒了,未设置参数,谁调用谁享用')
    yield name
    print('后置条件:小明睡了,未设置参数,谁调用谁享用')

@pytest.fixture(autouse=True)
def weather():
    """作用范围:默认为用例级,设置自动调用为True,每个用例都会调用"""
    sun = '晴天'
    print('前置条件:天亮了autouse=True,默认作用每个用例')
    yield sun
    print('后置条件:天黑了autouse=True,默认作用每个用例')

@pytest.fixture(scope='class')
def time():
    """作用范围:类级,谁调用谁享用"""
    t1 = '6:00'
    t2 = '20:00'
    print('前置条件:早上好class')
    yield t1, t2
    print('后置条件:晚上好class')

@pytest.fixture(scope='session', autouse=True)
def session():
    """作用范围:会话级,yield后可不写内容,不返回数据,设置自动调用为True"""
    print('前置条件:会话开始-----------------')
    yield
    print('后置条件:会话结束-----------------')

@pytest.fixture(params=['小美', '小帅'], ids=('mei', 'shuai'), name='clm')
def params_classmate(request):
    """作用范围:默认用例级,谁调用谁享用params和ids"""
    param = request.param
    print(f'前置条件:{param}')
    yield param
    print(f'后置条件:{param}')

class TestOneDay1:
    """调用方式一,直接作为参数传给测试用例:human,time,weather,clm"""
    def test_eat(self, human, time, clm):
        t1, t2 = time
        print(human + t1 + f'和{clm}吃了早餐')
    def test_school(self, weather, human):
        print('今天是'+weather+','+human + '去上学了')

@pytest.mark.usefixtures('human','time')
class TestOneDay2:
    """调用方式二:通过装饰器调用'human'和'time',但无法传递参数"""
    def test_homework(self):
        print('交了作业')
    def test_home(self):
        print('放学独自回家')

class TestOneDay3:
    """没有直接调用fixture,但设置了自动调用的会被调用"""
    def test_water(self):
        print('喝了水')
    def test_wc(self):
        print('去了wc')

if __name__ == '__main__':
    pytest.main(['-s'])

运行结果:

============================= test session starts =============================
collecting ... collected 7 items

test_pytest_fixture_demo.py::TestOneDay1::test_eat[mei] 前置条件:会话开始-----------------
前置条件:早上好class
前置条件:天亮了autouse=True,默认作用每个用例
前置条件:小明醒了,未设置参数,谁调用谁享用
前置条件:小美
PASSED           [ 14%]小明6:00和小美吃了早餐
后置条件:小美
后置条件:小明睡了,未设置参数,谁调用谁享用
后置条件:天黑了autouse=True,默认作用每个用例

test_pytest_fixture_demo.py::TestOneDay1::test_eat[shuai] 前置条件:天亮了autouse=True,默认作用每个用例
前置条件:小明醒了,未设置参数,谁调用谁享用
前置条件:小帅
PASSED         [ 28%]小明6:00和小帅吃了早餐
后置条件:小帅
后置条件:小明睡了,未设置参数,谁调用谁享用
后置条件:天黑了autouse=True,默认作用每个用例

test_pytest_fixture_demo.py::TestOneDay1::test_school 前置条件:天亮了autouse=True,默认作用每个用例
前置条件:小明醒了,未设置参数,谁调用谁享用
PASSED             [ 42%]今天是晴天,小明去上学了
后置条件:小明睡了,未设置参数,谁调用谁享用
后置条件:天黑了autouse=True,默认作用每个用例
后置条件:晚上好class

test_pytest_fixture_demo.py::TestOneDay2::test_homework 前置条件:早上好class
前置条件:天亮了autouse=True,默认作用每个用例
前置条件:小明醒了,未设置参数,谁调用谁享用
PASSED           [ 57%]交了作业
后置条件:小明睡了,未设置参数,谁调用谁享用
后置条件:天黑了autouse=True,默认作用每个用例

test_pytest_fixture_demo.py::TestOneDay2::test_home 前置条件:天亮了autouse=True,默认作用每个用例
前置条件:小明醒了,未设置参数,谁调用谁享用
PASSED               [ 71%]放学独自回家
后置条件:小明睡了,未设置参数,谁调用谁享用
后置条件:天黑了autouse=True,默认作用每个用例
后置条件:晚上好class

test_pytest_fixture_demo.py::TestOneDay3::test_water 前置条件:天亮了autouse=True,默认作用每个用例
PASSED              [ 85%]喝了水
后置条件:天黑了autouse=True,默认作用每个用例

test_pytest_fixture_demo.py::TestOneDay3::test_wc 前置条件:天亮了autouse=True,默认作用每个用例
PASSED                 [100%]去了wc
后置条件:天黑了autouse=True,默认作用每个用例
后置条件:会话结束-----------------


============================== 7 passed in 0.02s ==============================

进程已结束,退出代码0

在上面的示例中,fixture装置下的方法和测试用例写在了同一个文件内,而在实际的应用中,是要单独写在一个py文件内容,这时便可以通过conftest.py文件的帮助,更好的管理这些fixture装置方法(前后置条件用例)。
conftest.py文件是为整个目录提供固定装置的一种方法,可以将fixture装置写入到该文件中,使用时无需导入,在运行测试用例时,pytest会自动去发现该文件。但需要注意的是conftest.py的作用范围是其所在目录及子目录内的所有用例(例如所有的测试用例都在TestCase目录内,那么conftest.py文件需要放在TestCase目录内)
conftest.py示例代码:

"""
测试conftest.py文件
"""
import pytest

@pytest.fixture(autouse=True)
def test_conftest():
    print("conftest.py中的前置条件")
    yield
    print("conftest.py中的后置条件")

测试用例代码:

"""
   conftest.py文件使用
"""
import pytest

class TestPytest():
    """测试Pytest类"""

    def test_001(self):
        """test_001"""
        print("test_001")
        a = "a"
        assert a == a

    def test_002(self):
        """test_002"""
        print("test_002")
        assert 1 < 2

运行结果:

..\Testcase\test_pytest_demo.py::TestPytest::test_001 conftest.py中的前置条件
test_001
PASSEDconftest.py中的后置条件
..\Testcase\test_pytest_demo.py::TestPytest::test_002 conftest.py中的前置条件
test_002
PASSEDconftest.py中的后置条件
============================== 2 passed in 0.01s ==============================
进程已结束,退出代码0

3.5 参数化

通过装饰器@pytest.mark.parametrize('paramNameN', 'paramValue')可以实现测试数据的参数化,达到数据驱动的目的,参数名直接以字符串的形式传入,参数值可以是元组、列表、函数(自定义函数需要以列表形式传入)等。也可以通过与csv、yaml文件结合使用实现数据驱动测试。
参数化示例代码:

"""
   Pytest @pytest.mark.parametrize参数化装饰器使用示例
"""
import random
import pytest


def random_num():
    return random.randint(88888888, 99999999)

class TestParametrize():
    """@pytest.mark.parametrize参数化装饰器"""

    @pytest.mark.parametrize('name', ('小明', '小帅', '小黑'))
    def test_001(self, name):
        """1个参数"""
        print(f"{name}")
        assert 1 == 1

    @pytest.mark.parametrize('name, age', [('小明', '18'), ('小帅', '17'), ('小黑', '16')])
    def test_002(self, name, age):
        """多个参数"""
        print(f"{name}:{age}")
        assert 1 == 1

    @pytest.mark.parametrize('caseinfo', [{'name': '小明', 'age': '18', 'except': 'true'},
                                          {'name': '小美', 'age': '17', 'except': 'true'}])
    def test_003(self, caseinfo):
        """以列表字典形式传入多组测试数据"""
        name = caseinfo['name']
        age = caseinfo['age']
        print(f"{name}:{age}")
        assert caseinfo['except'] == 'true'

    @pytest.mark.parametrize('num', [random_num()])
    def test_004(self, num):
        """传入随机数"""
        print(f"中奖号码为:{num}")
        assert 1 == 1

    @pytest.mark.parametrize('num', range(5))
    def test_005(self, num):
        """传入一个range(函数)"""
        print(f"序号:{num}")
        assert 1 == 1

if __name__ == '__main__':
    pytest.main(['-s'])

运行结果:

============================= test session starts =============================
collecting ... collected 14 items
test_pytest_mark_parametrize.py::TestParametrize::test_001[\u5c0f\u660e] PASSED [  7%]小明
test_pytest_mark_parametrize.py::TestParametrize::test_001[\u5c0f\u5e05] PASSED [ 14%]小帅
test_pytest_mark_parametrize.py::TestParametrize::test_001[\u5c0f\u9ed1] PASSED [ 21%]小黑
test_pytest_mark_parametrize.py::TestParametrize::test_002[\u5c0f\u660e-18] PASSED [ 28%]小明:18
test_pytest_mark_parametrize.py::TestParametrize::test_002[\u5c0f\u5e05-17] PASSED [ 35%]小帅:17
test_pytest_mark_parametrize.py::TestParametrize::test_002[\u5c0f\u9ed1-16] PASSED [ 42%]小黑:16
test_pytest_mark_parametrize.py::TestParametrize::test_003[caseinfo0] PASSED [ 50%]小明:18
test_pytest_mark_parametrize.py::TestParametrize::test_003[caseinfo1] PASSED [ 57%]小美:17
test_pytest_mark_parametrize.py::TestParametrize::test_004[92025408] PASSED [ 64%]中奖号码为:92025408
test_pytest_mark_parametrize.py::TestParametrize::test_005[0] PASSED     [ 71%]序号:0
test_pytest_mark_parametrize.py::TestParametrize::test_005[1] PASSED     [ 78%]序号:1
test_pytest_mark_parametrize.py::TestParametrize::test_005[2] PASSED     [ 85%]序号:2
test_pytest_mark_parametrize.py::TestParametrize::test_005[3] PASSED     [ 92%]序号:3
test_pytest_mark_parametrize.py::TestParametrize::test_005[4] PASSED     [100%]序号:4

============================= 14 passed in 0.02s ==============================

进程已结束,退出代码0

3.6 日志

通过在pytest.ini配置日志相关参数,便可实现日志功能,可配置的参数:

  • log_level:捕获/显示日志的级别,CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,默认WARNING;
  • log_format:日志格式;
  • log_date_format:日志时间格式;
  • log_cli_level:实时日志级别;
  • log_cli_format:实时日志格式;
  • log_cli_date_format:实时日志时间格式;
  • log_file:日志写入文件路径(覆盖写入);
  • log_file_level:写入日志文件的日志级别;
  • log_file_format:写入日志文件的日志格式;
  • log_file_date_format:写入日志文件的时间格式;
  • log_auto_indent:自动缩进传递给日志模块的多行消息,接受true/on、false/off或整数。

pytest.ini配置日志示例:

[pytest]
addopts = -vs --color=yes
log_cli = true

log_level = DEBUG
log_format = %(asctime)s %(filename)-s:%(lineno)-s %(levelname)-8s - %(message)s
log_date_format = %Y/%m/%d %H:%M:%S
log_auto_indent = true

log_file = ../Log/logs.log
log_file_level = DEBUG
log_file_format = %(asctime)s %(filename)-s:%(lineno)-s %(levelname)-8s - %(message)s
log_file_date_format = %Y/%m/%d %H:%M:%S

日志示例代码:

"""
   Pytest logging使用示例
"""
from time import sleep
import logging
logger = logging.getLogger('__name__')

def test_pytest_log():
    logger.info('info msg')
    logger.debug('debug msg')
    logger.error('error msg')
    sleep(3)
    logger.critical('critical msg')
    sleep(3)
    logger.warning('warning msg')
    logger.info('info \n多行缩进\n多行缩进\n多行缩进')

if __name__ == '__main__':
    test_pytest_log()

运行结果-控制台:

python pytest,测试笔记,python,测试工具,pytest,自动化
运行结果-日志文件:

python pytest,测试笔记,python,测试工具,pytest,自动化

3.7 断言

可以直接使用python自带的断言,具体呈现形式,可见前面的示例代码。

  • assert a in b:断言a包含b
  • assert a == b:断言a等于b
  • assert 1 < 2:断言1小于2
  • ……

3.8 生成测试报告

方式1:安装三方插件pytest-allure,详细使用方法见Allure在Pytest自动化测试框架中的基本应用
python pytest,测试笔记,python,测试工具,pytest,自动化
方式2:安装三方插件pytest-html,执行是添加--html=../report/report.html参数便可生产html报告
运行pytest.main(['-vs', '--html=../report/report.html', '../Testcase/test_pytest_report_html.py'])
python pytest,测试笔记,python,测试工具,pytest,自动化

说明:本文为学习笔记,如错误、可优化等内容,欢迎交流与指正。文章来源地址https://www.toymoban.com/news/detail-784128.html

到了这里,关于Python测试工具-Pytest使用详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 测试员进阶必看系列 “ python自动化测试工具selenium使用指南 ”

    概述 python+selenium环境安装 使用selenium启动浏览器 selenium页面加载等待和检测 使用time.sleep()等待 使用implicitly_wait设置最长等待时间 使用WebDriverWait设置等待条件 检测document是否加载完成 selenium元素定位和读取 查找元素 dom元素交互 查找元素失败处理 selenium交互控制 ActionChains动

    2024年02月05日
    浏览(112)
  • 如何使用Python自动化测试工具Selenium进行网页自动化?

    Selenium 是一个流行的Web自动化测试框架, 它支持多种编程语言和浏览器,并提供了丰富的API和工具来模拟用户在浏览器中的行为 。 Selenium可以通过代码驱动浏览器自动化测试流程,包括页面导航、元素查找、数据填充、点击操作等。 与PyAutoGUI和AutoIt相比, Selenium更适合于处

    2023年04月09日
    浏览(126)
  • python自动化测试工具selenium使用指南 ,绝对能帮到你

    目录 概述 python+selenium环境安装 使用selenium启动浏览器 selenium页面加载等待和检测 使用time.sleep()等待 使用implicitly_wait设置最长等待时间 使用WebDriverWait设置等待条件 检测document是否加载完成 selenium元素定位和读取 查找元素 dom元素交互 查找元素失败处理 selenium交互控制 Actio

    2024年02月08日
    浏览(53)
  • 自动化工具 pytest 内核测试平台落地初体验

    测试平台,有人说它鸡肋,有人说它有用,有人说它轮子,众说纷纭,不如从自身出发,考虑是否要做测试平台: 第 1 阶段,用 Python+requests 写接口自动化。 第 2 阶段,选择 unitttest 或 pytest,更熟悉 pytest 选了 pytest。 第 3 阶段,快速搭建 pytest 项目脚手架,封装 tep 测试工具

    2023年04月08日
    浏览(47)
  • 接口测试工具——Postman使用详解

    目录 Postman简介 Postman主界面 菜单栏 工具栏 请求管理区 环境管理区 请求设计区 发送请求 发送GET请求 Postman发送GET请求 发送表单格式POST请求 发送JSON格式POST请求 发送XML格式POST请求 发送文件上传类型的请求 响应 环境和变量 环境变量设置 环境变量使用 全局变量 测试脚本及

    2024年02月08日
    浏览(60)
  • 【测试开发】Python+Django实现接口测试工具

    Python+Django接口自动化  引言:          最近被几个公司实习生整自闭了,没有基础,想学自动化又不知道怎么去学,没有方向没有头绪,说白了其实就是学习过程中没有成就感,所以学不下去。出于各种花里胡哨的原因,今天给大家整一个简单又有成就感的接口自动化学习

    2024年02月15日
    浏览(51)
  • Onvif协议及协议测试工具使用详解

    目录 ​1、Onvif协议的发展 2、Onvif协议概述及优势 2.1    协议概述 2.2、规范优势

    2024年01月15日
    浏览(41)
  • Python性能测试工具Locust入门

    1、性能测试该怎么做? 利用工具模拟真实用户操作。 2、性能测试基础: 性能:事物的性质和能效 --效率性能 (时间/资源/容量) 思考:如何评价软件系统的性能? 快慢:衡量系统的处理效率 (响应时间) 多少:衡量系统的处理能力(单位时间内,能处理多少个事物) 3、性

    2024年02月07日
    浏览(59)
  • 接口自动化测试工具,Postman使用详解

    1、Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件,Postman分为Postman native app和Postman Chrome app两个版本。目前Chrome app已经停止维护,官方也不推荐使用该版本。 2、官网下载地址:http://www.getpostman.com 3:官方文档:http://www.getpostman.com/docs 2、第二步:新建接口请

    2024年02月06日
    浏览(81)
  • 【Python百宝箱】Python测试工具大揭秘:从单元测试到Web自动化

    在现代软件开发中,测试是确保代码质量和稳定性的关键步骤。Python作为一门广泛应用的编程语言,拥有丰富的测试工具和库,从单元测试到Web自动化,覆盖了多个测试层面。本文将介绍一系列Python测试工具,帮助开发者选择适合项目需求的工具,提高代码的可靠性和可维护

    2024年02月03日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包