Pytest单元测试框架-学习
pytest: Python的一个单元测试框架,基于UnitTest二次开发,语法上更加简洁,可以用来做Python开发项目的单元测试,UI自动化、接口自动化测试等,有很多的插件访问Pytest插件汇总,对Pytest进行扩展。
pytest是一个框架,它使构建简单且可伸缩的测试变得容易。测试具有表达性和可读性,不需要样板代码。在几分钟内开始对应用程序或库进行小的单元测试或复杂的功能测试。 -- 来自Pytest官方文档(由谷歌翻译)
https://docs.pytest.org/en/latest/parametrize.html
安装
pip install pytest
文件名称规则
与UnitTest类似,测试文件名称需要以test_文件名.py
(推荐使用这种)或者文件名_test.py
格式。
测试类的名称:Test类名
来定义一个测试类
测试方法(函数):test_方法名
来定义一个测试方法
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_01.py
@ide: PyCharm
@time: 2020/7/27
"""
# 测试类TestNumber
class TestNumber(object):
def __int__(self):
pass
def test_sum(self):
# assert进行断言
assert 1 == 2
def test_str(self):
# isinstance 判断对象是否为对应类型
assert isinstance(1, int)
运行测试
方法1:在当前目录下使用命令行,输入pytest
将会执行该目录下所有test_*.py
文件
(venv) bogon:pytest_study zy7y$ pytest
========================================================================= test session starts =========================================================================
platform darwin -- Python 3.8.3, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /Users/zy7y/PycharmProjects/pytest_study
collected 3 items
test_01.py F. # F.为测试失败 [ 66%]
test_02.py . # . 为测试通过 [100%]
============================================================================== FAILURES ===============================================================================
_________________________________________________________________________ TestNumber.test_sum _________________________________________________________________________
self = <test_01.TestNumber object at 0x1110fb580>
def test_sum(self):
# assert进行断言
> assert 1 == 2
E assert 1 == 2
test_01.py:19: AssertionError
======================================================================= short test summary info =======================================================================
FAILED test_01.py::TestNumber::test_sum - assert 1 == 2
===================================================================== 1 failed, 2 passed in 0.07s =====================================================================
方法2: 在当前目录下使用命令行,输入pytest test_*.py
指定运行某个测试文件
(venv) bogon:pytest_study zy7y$ pytest test_01.py
F. [100%]
============================================================================== FAILURES ===============================================================================
_________________________________________________________________________ TestNumber.test_sum _________________________________________________________________________
self = <test_01.TestNumber object at 0x10824aac0>
def test_sum(self):
# assert进行断言
> assert 1 == 2
E assert 1 == 2
test_01.py:19: AssertionError
======================================================================= short test summary info =======================================================================
FAILED test_01.py::TestNumber::test_sum - assert 1 == 2
1 failed, 1 passed in 0.06s
方法3:在测试文件下使用pytest.main()
方法来运行.
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_01.py
@ide: PyCharm
@time: 2020/7/27
"""
# 测试类TestNumber
class TestNumber(object):
def __int__(self):
pass
def test_sum(self):
# assert进行断言
assert 1 == 2
def test_str(self):
assert isinstance(1, int)
if __name__ == '__main__':
import pytest
# 相当于在命令行当前目录中执行了 pytest
pytest.main()
# 执行pytest -q test_01.py : -q 简短输出测试信息
pytest.main(['-q', 'test_01.py'])
方法4:使用Pycharm修改单元测试框架来启动单个测试文件.


临时目录
pytest提供内置的fixtures / function参数来请求任意资源,例如唯一的临时目录:
在测试函数签名中列出名称tmpdir,pytest将在执行测试函数调用之前查找并调用夹具工厂来创建资源。 在测试运行之前,pytest创建一个“每次测试调用唯一”临时目录
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_02.py
@ide: PyCharm
@time: 2020/7/27
"""
def test_02():
assert 1 == 1
# 临时目录
def test_neddsfiles(tmpdir):
# 打印临时目录地址
print(tmpdir) # tmpdir = local('/private/var/folders/m4/gq5zy91j62x8qx_msq5mdbxw0000gn/T/pytest-of-zy7y/pytest-7/test_neddsfiles0')
# 0 和 None 、 '' 在python中属于 False
assert None
pytest其他命令
命令行中执行:
pytest --fixtures # 显示内置和自定义 fixtures
pytest -h # 查看帮助
pytest -x # 第一次故障后停止测试
pytest --maxfail=2 # 2次失败后停止
运行测试方法:
pytest test_*.py # 在模块中运行测试(运行整个.py下的测试类、方法、函数)
pytest testing/ # 在工作目录运行测试(运行指定文件目录下的所有测试类、方法、函数)
pytest -k "Number and not str" # 关键字运行
这将运行包含与给定字符串表达式(大小写不敏感)匹配的名称的测试,其中可以包括使用文件名、类名和函数名作为变量的Python操作符。上面的示例将运行TestNumber。测试一些东西,但不运行test_str测试方法。
pytest test_02.py::test_02 # 在模块中运行测试,就是说运行test_02.py文件中test_02的函数
pytest test_01.py::TestNumber::test_sum # 运行模块下指定测试类的测试方法
pytest -m slow # 将运行所有用@pytest.mark.slow装饰的测试
pytest --pyargs pkg.testing # 运行文件名称为testing的包下面所有的测试文件
fixture(依赖注入)
注意: Pytest对于每个fixture只会缓存一个实例,这意味着如果使用参数化的fixture,pytest可能会 比定义的作用域更多次的调用fixture函数(因为需要创建不同参数的fixture)
作为函数入参的fixture
"""
@project: pytest_study
@author: zy7y
@file: test_03.py
@ide: PyCharm
@time: 2020/7/27
""" import pytest # 其他测试函数传入这个函数名称时会得到一个实例对象,且一直都是这个实例对象
@pytest.fixture
def get_driver():
from selenium import webdriver
# 返回一个操控Chrome浏览器的驱动实例 driver
driver = webdriver.Chrome()
return driver def test_browse(get_driver):
get_driver.get("http://www.baidu.com")
print(id(get_driver)) def test_close(get_driver):
get_driver.close()
print(id(get_driver))
在类/模块/中共享fixture实例
将fixture函数放在独立的
conftest.py
文件中,可以达到在多个测试模块中访问使用这个fixture;将scope="module"参数添加到@pytest.fixture中# conftest.py
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: conftest.py
@ide: PyCharm
@time: 2020/7/27
""" import pytest
@pytest.fixture(scope='module')
def browse_driver():
from selenium import webdriver
# 返回一个操控Chrome浏览器的驱动实例 driver
driver = webdriver.Chrome()
return driver
# test_04.py
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_04.py
@ide: PyCharm
@time: 2020/7/27
""" def test_open_browse(browse_driver):
browse_driver.get("https://www.baidu.com") def test_open_blog(browse_driver):
import time
time.sleep(3)
browse_driver.get("https://www.baidu.com")
print(browse_driver.window_handles)
browse_driver.close()
fixture结束/执行清理代码
# 修改后的conftest.py
import pytest
@pytest.fixture(scope='module')
def browse_driver():
# from selenium import webdriver
# # 返回一个操控Chrome浏览器的驱动实例 driver
# driver = webdriver.Chrome()
# return driver # 调用结束/执行清理代码
from selenium import webdriver
driver = webdriver.Chrome()
# 调用前 会实例一个 driver, 然后通过yield 返回
yield driver
# 用例结束后使用close关闭driver
driver.close()
# test_05.py
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_05.py
@ide: PyCharm
@time: 2020/7/27
""" def test_open_browse(browse_driver):
browse_driver.get("https://www.baidu.com")
assert browse_driver.title == '百度一下,你就知道' def test_open_blog(browse_driver):
import time
time.sleep(3)
browse_driver.get("https://www.cnblogs.com/zy7y/")
assert 'zy7y' in browse_driver.title
fixture固件作用域
在定义固件时,通过 scope 参数声明作用域,可选项有: function: 函数级,每个测试函数都会执行一次固件; class: 类级别,每个测试类执行一次,所有方法都可以使用; module: 模块级,每个模块执行一次,模块内函数和方法都可使用; session: 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。 package,表示fixture函数在测试包(文件夹)中第一个测试用例执行前和最后一个测试用例执行后执行一次
# 启动顺序 session(单元测试集 -> 模块 -> 类 - >方法)
用例初始化(UnitTest的类前运行等方法)
模块级别(setup_module/teardown_module) 全局的 函数级别(setup_function/teardown_function) 只对函数用例生效(不在类中的) 类级别 (setup_class/teardown_class) 只在类中前后运行一次(只在类中才生效) 方法级别 (setup_method/teardown_method) 开始后与方法始末(在类中) 类内用例初始化结束 (setup/teardown) 运行在测试用例的前后
import pytest
def setup_module():
print('\nsetup_module 执行')
def teardown_module():
print('\nteardown_module 执行')
def setup_function():
"""函数方法(类外)初始化"""
print('setup_function 执行')
def teardown_function():
"""函数方法(类外)初始化"""
print('\nteardown_function 执行')
def test_in_class():
"""类(套件)外的测试用例"""
print('类外测试用例')
class Test_clazz(object):
"""测试类"""
def setup_class(self):
print('setup_class 执行')
def teardown_class(self):
print('teardown_class 执行')
def setup_method(self):
print('setup_method 执行')
def teardown_method(self0):
print('teardown_method 执行')
def setup(self):
print('\nsetup 执行')
def teardown(self):
print('\nteardown 执行')
def test_case001(self):
"""测试用例一"""
print('测试用例一')
def test_case002(self):
"""测试用例二"""
print('测试用例二')
跳过测试函数
实现部分场景该测试函数不需要执行
# test_07.py
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_07.py
@ide: PyCharm
@time: 2020/7/27
"""
import pytest
import sys
# 这将强制跳过
@pytest.mark.skip(reason="该测试函数将被跳过")
def test_sum():
assert 1 != 2
def test_count():
assert 1 == 0
# 满足条件才跳过
@pytest.mark.skipif(sys.version_info < (3, 6), reason="版本低于3.6将跳过不执行!")
def test_num():
assert 1 + 3 == 5
# 标记测试用例期望失败
@pytest.mark.xfail(reason='期望这个测试是失败的')
def test_func01():
assert 1 == 1
参数化-UnitTest的DDT
内置的pytest.mark.parametrize装饰器可以用来对测试函数进行参数化处理。
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: pytest_study
@author: zy7y
@file: test_08.py
@ide: PyCharm
@time: 2020/7/27
"""
import pytest
"""
'username, password, expect' 来传递 需要使用到的行参名
[('admin', '123456', '登录成功'), ('admin', '111111', '密码错误')] 来传递对应的实参,这个列表中每一个元组执行一次
ids=["正常登录测试用例标题", "密码错误登录测试用例"] 来传递对应每一次测试的用例标题
这个文件中执行了两次
"""
@pytest.mark.parametrize('username, password, expect',
[('admin', '123456', '登录成功'),
('admin', '111111', '密码错误')], ids=["正常登录测试用例标题", "密码错误登录测试用例"])
def test_login(username, password, expect):
if username == 'admin' and password == '123456':
assert expect == '登录成功'
else:
assert expect == '密码错误'
# 这将实现两个装饰器的参数组合并且用来测试
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
assert x + y == 5
运行脚本,会发生一个字符编码的错误:
解决方法是在 项目根目录下建立一个
pytest.ini
文件并写入[pytest]
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True
Pytest单元测试框架-学习的更多相关文章
- Pytest单元测试框架-测试用例运行规则
1.Pytest测试用例运行规则 在pytest单元测试框架下面执行用例,需要满足以下几个特点: 1. 文件名以test_*.py开头或者*_test.py 2. 测试类.测试函数以test开头 3. ...
- Pytest单元测试框架-Pytest环境安装
unittest是python自带的单元测试框架,它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作,使得单元测试易于开展,因为它的易用性,很多同学也拿它来做功能测试和接口测试,只需简单开发 ...
- Pytest单元测试框架:插件-allure-pytest环境搭建并在本地生成一个测试报告
之前写了allure-pytest的官方文档啃的内容,有些交流的朋友,实践起来没什么头绪,所以就有了这篇文章,也给自己填个坑 第一步:搭建Allure.JDK环境 1. 搭建JDK环境 不装jdk你会 ...
- Pytest单元测试框架之简单操作示例
前言: Pytest是第三方单元格测试框架,更加简单,灵活,而且提供了更多丰富的扩展: Pytest与UnitTest框架的区别 UnitTest测试用例执行顺序是依照ascii码执行,而Pytest ...
- Pytest 单元测试框架
1.pytest 是 python 的第三方单元测试框架,比自带 unittest 更简洁和高效 2.安装 pytest pip install pytest 3.验证 pytest 是否安装成功 p ...
- Pytest单元测试框架——Pytest+Allure+Jenkins的应用
一.简介 pytest+allure+jenkins进行接口测试.生成测试报告.结合jenkins进行集成. pytest是python的一种单元测试框架,与python自带的unittest测试框架 ...
- Pytest单元测试框架之FixTure基本使用
前言: 在单元测试框架中,主要分为:测试固件,测试用例,测试套件,测试执行及测试报告: 测试固件不难理解,也就是我们在执行测试用例前需要做的动作和测试执行后的需要做的事情: 比如在UI自动化测试中,我 ...
- pytest单元测试框架
一.安装方式 1.安装命令:pip install pytest 2.html安装插件:pip install pytest -html 二.pytest执行指定测试用例 1.思想:通过对测试用例进行 ...
- Pytest单元测试框架-allure测试报告
Allure Test Report 对于不同的编程语言,有很多很酷的测试框架.不幸的是,它们中只有少数能够提供测试执行输出的良好表示.Qameta软件测试团队正在致力于Allure--一个开源框架, ...
随机推荐
- 十年老苹果(A1286)强升Catalina及Win10踩坑记
前言 手头有一台十年老苹果,MacBook Pro,A1286,连视网膜屏都没有,电池也早就衰减以后直接拆掉了(减重). 早些年用得还挺多,后来家里也弄了台式,用得逐渐少了,再后来时不时Windows ...
- Typora上传图片设置
Typora上传图片设置 问题 使用Typora写文档时上传图片的路径默认是本地磁盘的路径,这样就导致一个问题,当写好的文档上传到blog.csdn等博客网站时,会导致图片失效无法识别的问题. 解决方 ...
- Scala 面向对象(二):package 包 (一) 入门
1 Scala包的基本介绍 和Java一样,Scala中管理项目可以使用包,但Scala中的包的功能更加强大,使用也相对复杂些,下面我们学习Scala包的使用和注意事项. 2 Scala包快速入门 使 ...
- 02-flask项目创建及debug模式的开启
一.flask文件的创建 打开pycharm,选择flask文件,选择相关配置,需要配置的有虚拟环境,flask文件名.如下图所示: 新建的flask文件如下所示: static:用来存放静态文件,包 ...
- C#文件说明
Bin -- 用来存放编译的结果,是默认的输出路径,项目属性—>配置属性—>输出路径. obj -- 用于存放编译过程中生成的中间临时文件.增量编译:项目属性—>配置属性—>高 ...
- node -v node is not define
安装node js 踩过的坑 应该是在CMD 命令里执行 node -v 我却傻傻的跑到 node.js 里执行 node -v 结果就报 node is not define 真相如下图!!!
- 搭建sonarqube分析golang代码
准备postgres 为什么不使用Mysql呢,因为从7.9就不支持了 docker启动postgres docker run -d \ --name sonar-postgres \ -e POST ...
- 洛谷 P1080 国王游戏 题解
原题 传送门 思路 分析 我们先假设队伍如下: People left hand right hand Before \(S_a\) A \(a_1\) \(b_1\) B \(a_2\) \(b_2 ...
- 6.ALOHA协议
动态媒体接入控制/多点接入特点:信道并非在用户通信时固定分配给用户. 一.纯ALOHA协议 纯 ALOHA协议思想:不监听信道,不按时间槽发送,随机重发.想发就发 二.时隙ALOHA协议 时隙 ALO ...
- springboot(八)内置SpringMvc静态文件地址修改
参考:作者:恒宇少年链接:https://www.jianshu.com/p/c6ab1081fd5f 介绍: SpringMVC大家都不陌生,而被SpringBoot集成的SpringMVC除了 ...