测试框架pytest学习与实践

news2024/12/23 14:12:28

pytest是一个专业的测试框架,可以帮助我们对python项目进行测试,提高测试的效率。

pytest官网手册:pytest: helps you write better programs — pytest documentation

中文手册:Pytest 教程

入门学习

安装pytest

pip install pytest

写例子test_sample.py

def inc(x):
    return x + 1


def test_answer():
    assert inc(3) == 5


def test_answer2():
    assert inc(3) == 4

注意里面的测试函数都是test_开头,按照pytest的规范,需要以“test”4个字母开头的函数才会被测试。

执行测试

pytest test_sample.py

显示:

==================================== FAILURES =====================================
___________________________________ test_answer ___________________________________

    def test_answer():
>       assert inc(3) == 5
E       assert 4 == 5
E        +  where 4 = inc(3)

test_sample.py:9: AssertionError
============================= short test summary info =============================
FAILED test_sample.py::test_answer - assert 4 == 5
=========================== 1 failed, 1 passed in 0.20s ===========================

可以看到,两个测试函数,assert inc(3) == 5的这个没有测试通过。

pytest提高篇

多文件测试

当前目录和子目录的所有类似test_*.py*_test.py 的文件,都会自动参与测试。

比如我们在当前目录下,再写一个文件test_sysexit.py:

# content of test_sysexit.py
import pytest


def f():
    raise SystemExit(1)


def test_mytest():
    with pytest.raises(SystemExit):
        f()

然后在当前目录直接执行pytest命令,则会自动测试test_sample.py test_sysexit.py这两个文件,并给出测试结果:

collected 3 items                                                                 

test_sample.py F.                                                           [ 66%]
test_sysexit.py .                                                           [100%]

==================================== FAILURES =====================================
___________________________________ test_answer ___________________________________

    def test_answer():
>       assert inc(3) == 5
E       assert 4 == 5
E        +  where 4 = inc(3)

test_sample.py:9: AssertionError
============================= short test summary info =============================
FAILED test_sample.py::test_answer - assert 4 == 5
=========================== 1 failed, 2 passed in 0.46s ===========================

使用“raises helper”来引起异常

前面的例子中,如果f()函数没有抛出SystemExit异常,那么这个测试将会失败。如果抛出SystemExit异常,那么这个测试通过。

功能测试需求唯一的目录

为功能测试请求唯一目录

# content of test_tmp_path.py
def test_needsfiles(tmp_path):
    print(tmp_path)
    assert 0

输出信息如下:

/tmp/pytest-of-skywalk/pytest-2/test_needsfiles0
============================= short test summary info =============================
FAILED test_tmp.py::test_needsfiles - assert 0
1 failed in 0.17s

可以看到创建了一个临时文件目录:/tmp/pytest-of-skywalk/pytest-2/test_needsfiles0

在kotti项目里集成测试

在Kotti项目中进行pytest测试可以参考这个文档:以Kotti项目为例使用pytest测试项目-CSDN博客

下载安装Kotti库

pip install https://atomgit.com/skywalk/Kotti
cd Kotti
pip install -r requirements.txt
python3 setup.py develop --user

安装好pytest和其需要的库

pip install pytest
pip install mock
pip install pytest-flake8 pytest-cov

执行测试

~/github/Kotti]$ pytest

有很多报错,主要是 Unittest-style tests are deprecated as of Kotti 0.7.因此需要按照Kotti的文档和pytest的最佳实践,将unittest风格的测试迁移到pytest风格。

将unittest风格的测试迁移到pytes

这恐怕是一个比较大的工程了,但是肯定要先迁移过去,因为现在的测试已经不能用了。先订好这个目标。

在Kotti目录执行 pytest ./kotti/tests/test_app.py ,输出:

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html

-------- coverage: platform freebsd13, python 3.10.13-final-0 --------
Name                                Stmts   Miss  Cover   Missing
-----------------------------------------------------------------
kotti/__init__.py                     109     39    64%   1-30, 40-46, 50, 59-163, 167, 171, 186, 198, 249, 258
kotti/events.py                       209     51    76%   100-101, 105, 110-114, 117, 120, 123-125, 128, 270-278, 320, 332-340, 350-352, 356-366, 397, 412, 415, 423-424, 440, 444, 451, 458, 464, 510-511, 515-518, 522-524
kotti/fanstatic.py                     46      3    93%   66, 69, 90
kotti/filedepot.py                    284    142    50%   99-106, 114-127, 134, 140, 146, 152, 169-174, 182, 191, 210-211, 220-222, 242-245, 269-281, 313-327, 335-337, 346-348, 352, 356-358, 363-394, 455-492, 498-509, 513, 522, 528-538, 566, 587-619, 638-640
kotti/interfaces.py                     8      0   100%
kotti/message.py                       54     35    35%   22-23, 28-32, 59-68, 94-108, 117-128
kotti/migrate.py                      123     55    55%   66, 121-122, 140-164, 168-169, 173-190, 194-259
kotti/populate.py                      33      0   100%

kotti/workflow.py                      51     11    78%   24-32, 71-94
-----------------------------------------------------------------
TOTAL                                3975   1893    52%

============================= short test summary info =============================
FAILED kotti/tests/test_app.py::flake-8::FLAKE8 - AttributeError: 'Application' object has no attribute 'parse_preliminary_options'
==================== 1 failed, 16 passed, 1 warning in 14.36s =====================

说实话不太明白这个输出的意思,也就是只有一个测试文件是失败的,16个都是通过的。没看到说哪个文件失败啊? 还是说这个文件里面一共17个函数,失败了一个,通过了16个?应该是文件数目。

为什么用python -Wd setup.py test -q测试pytest显示: Ran 0 tests in 0.000s

看到有文章说要加入main函数

但是加入之后还是ran 0

最后在ubuntu下重新下载了kotti源码,进行了一系列修改,主要是加入了个库:

pip install pytest-flake8 pytest-cov

然后使用pytest进行测试,总算跑起来了,跑的结果是:

TOTAL                                3975    335    92%

但是还有一些报错,如:FAILED kotti/tests/test_httpexceptions.py::flake-8::FLAKE8 - AttributeError: 'Application' object has no attribute 'parse_preliminary_options',另外能看到tests目录里面的文件都没有执行测试,这也不太正常。

又安装了flake8-pytest ,现在最后的输出是:

FAILED kotti/views/edit/upload.py::flake-8::FLAKE8 - AttributeError: 'Application' object has no attribute 'parse_preliminary_options'
============= 75 failed, 379 passed, 7 warnings in 186.68s (0:03:06) ==============

一系列修改是这些

 1756  vi /home/linuxskywalk/github/Kotti/kotti/tests/conftest.py
 1757  pip install -e . 
 1761  pip install pytest-flake8 pytest-cov
 1760  pytest kotti/tests

也就是主要是安装了两个库:pip install pytest-flake8 pytest-cov

kotti成功测试了,后面就可以进行维护或修改代码工作了!

调试

直接运行pytest kotti/tests 目录报错

(py310) [skywalk@x250 ~/github/Kotti/kotti]$ pytest tests
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --flake8 --cov=kotti --cov-report=term-missing
  inifile: /usr/home/skywalk/github/Kotti/pytest.ini
  rootdir: /usr/home/skywalk/github/Kotti

安装缺少的库

pip install pytest-flake8 pytest-cov

运行kotti测试报错

FAILED kotti/tests/test_app.py::flake-8::FLAKE8 - AttributeError: 'Application' object has no attribute 'parse_preliminary_options'

不知道该怎么办.....

报错Unittest-style tests are deprecated as of Kotti 0.7.

/usr/local/lib/python3.10/unittest/loader.py:122: DeprecationWarning: _init_testing_db: Unittest-style tests are deprecated as of Kotti 0.7. Please use pytest function arguments instead. obj = getattr(module, name)

这是文心一言的回答:这个报错信息实际上是一个DeprecationWarning,而不是一个错误(error)。它告诉你关于Kotti框架中某个功能或方法的弃用警告。具体来说,_init_testing_db这个可能是用于初始化测试数据库的函数或方法,在Kotti 0.7版本及以后的版本中已经被弃用了。

警告信息中建议,你应该使用pytest的函数参数来替代旧的unittest风格的测试。这意味着如果你正在编写或维护针对Kotti的测试,你需要将你的测试从unittest风格迁移到pytest风格。

在pytest中,你通常会使用装饰器(如@pytest.mark.parametrize)和函数参数来组织和管理你的测试,而不是继承unittest的TestCase类并编写setUp、tearDown等方法。

例如,假设你有一个旧的unittest风格的测试:

import unittest  
from kotti import _init_testing_db  
  
class MyTest(unittest.TestCase):  
    def setUp(self):  
        _init_testing_db()  
  
    def test_something(self):  
        # 测试代码

你应该将其转换为pytest风格的测试,可能看起来像这样:

import pytest  
from kotti import create_app  
  
@pytest.fixture  
def app_with_testing_db():  
    # 这里是初始化测试数据库的代码  
    app = create_app(testing=True)  
    with app.app_context():  
        # 这里是初始化数据库的代码  
        # ...  
    yield app  
    # 这里是清理数据库的代码(如果需要)  
    # ...  
  
def test_something(app_with_testing_db):  
    # 测试代码,使用传入的app_with_testing_db作为应用上下文

在上面的pytest示例中,我们使用了@pytest.fixture装饰器来定义一个测试夹具(fixture),这个夹具会在每个测试函数执行之前创建并初始化测试环境(包括数据库)。test_something函数接受这个夹具作为参数,从而可以在测试函数内部使用已经设置好的测试环境。

请注意,上述代码只是示例,你需要根据你的具体情况和Kotti的API来调整代码。

要修复这个警告,你需要检查你的测试代码,并按照Kotti的文档和pytest的最佳实践,将unittest风格的测试迁移到pytest风格。这通常涉及到重构测试类和测试方法,以使用pytest的装饰器和夹具。

实际工作太多,作为一个初学者,我并没有按照文心的建议去修改代码。

使用pytest的时候,输出一个F后面跟很多绿色的点,是什么意思?

在使用pytest进行测试时,输出中的“F”代表一个失败的测试(Failed),而绿色的点(.)代表一个通过的测试(Passed)

输出中的“F”后面跟着很多绿色的点,意味着在测试套件中,有一个测试失败了,而其他的测试都通过了。应该查看失败的测试详情,了解为什么测试会失败,并据此修复代码或测试。 

原来是flake8那里测试没通过,具体见这里:pytest的时候输出一个F后面跟很多绿色的点解读-CSDN博客

kotti/alembic/versions/9398ccf41c2_add_content_state_fo.py::flake-8::FLAKE8 FAILED
kotti/tests/__init__.py::flake-8::FLAKE8 FAILED
kotti/tests/conftest.py::flake-8::FLAKE8 FAILED
kotti/tests/test_app.py::flake-8::FLAKE8 FAILED
kotti/tests/test_app.py::testing_db_url PASSED
kotti/tests/test_app.py::TestApp::test_override_settings PASSED
kotti/tests/test_app.py::TestApp::test_auth_policies_no_override PASSED
kotti/tests/test_app.py::TestApp::test_auth_policies_override PASSED
kotti/tests/test_app.py::TestApp::test_asset_overrides PASSED
kotti/tests/test_app.py::TestApp::test_pyramid_includes_overrides_base_includes PASSED

pytest输出是什么意思? Stmts Miss Cover Missing

这些统计数据更可能是由 pytest 结合代码覆盖率工具(如 coverage)生成的。这些统计数据提供了关于测试套件覆盖了多少源代码行的信息。 

  • Stmts: 表示总的源代码行数(statements)。
  • Miss: 表示没有被测试覆盖的源代码行数。
  • Cover: 表示代码覆盖率,通常以百分比表示。
  • Missing: 列出了没有被测试覆盖的具体源代码行或代码块。

提示@pytest.yield_fixture is deprecated.

/home/linuxskywalk/github/Kotti/kotti/tests/__init__.py:71: PytestDeprecationWarning: @pytest.yield_fixture is deprecated.

顺手改了init文件:

/home/linuxskywalk/github/Kotti/kotti/tests/__init__.py 将其中的yield_fixture全部改成fixture

搞定!

在有的版本的系统中,这个代码没有改也没有报错。但是有的有报错,可能跟pip版本不一样有关吧。

pyramid使用pytest报错:ImportError

pytest
ImportError while loading conftest '/home/linuxskywalk/github/Kotti/kotti/tests/conftest.py'.
_pytest.pathlib.ImportPathMismatchError: ('kotti.tests.conftest', '/home/linuxskywalk/py310/lib/python3.10/site-packages/kotti/tests/conftest.py', PosixPath('/home/linuxskywalk/github/Kotti/kotti/tests/conftest.py'))

执行pip install -e .之后,报错变成:

报错:ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]


ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --flake8 --cov=kotti --cov-report=term-missing
  inifile: /home/linuxskywalk/github/Kotti/pytest.ini
  rootdir: /home/linuxskywalk/github/Kotti

使用这条命令试试:pip install pytest-flake8 pytest-cov

好了,报错没有了,可以pytest执行下去了

执行结果显示:

TOTAL                                3975    335    92%

但是还有很多错误,如下:

报错 AttributeError: 'Application' object has no attribute 'parse_preliminary_options'

FAILED kotti/__init__.py::flake-8::FLAKE8 - AttributeError: 'Application' object has no attribute 'parse_preliminary_options'

安装flake8-pytest试试

pip install flake8-pytest

还是不行,照旧。不过输出好看一点了:

FAILED kotti/views/edit/upload.py::flake-8::FLAKE8 - AttributeError: 'Application' object has no attribute 'parse_preliminary_options'
============= 75 failed, 379 passed, 7 warnings in 186.68s (0:03:06) ==============

pytest最开始是ran 0 ?

看网上自己在testing.py文件里加了这句:

if __name__ == '__main__':
    unittest.main()

但是这个并没有影响。

真正的解决方法是安装需要的库

pip install pytest-flake8 pytest-cov

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1574580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023护网行动经验分享(2024护网招人)

今年的护网又开始摇人了,不知道大家有想法没? 去年的护网结束之后,朋友圈感觉是在过年,到处是倒计时和庆祝声。 看得出来防守方们7*24小时的看监控还是比较无奈的。 本次复盘基于我对整个护网行动的观察总结而来,仅…

CSS弹性布局:Flex布局及属性完全指南,点击解锁新技能!

Flex 布局是一种新型的 CSS 布局模式,它主要用于弹性盒子布局。相比于传统的布局方式,它更加灵活,易于调整,也更加适应不同的设备和屏幕尺寸。 下面我们就来详细解析 Flex 布局及其属性,帮助大家深入理解和运用 Flex …

基于Python的自然语言的话题文本分类(V2.0),附源码

博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&#x1f3…

并查集学习(836. 合并集合 + 837. 连通块中点的数量)

//得先加集合个数再合并!!!!!!!!! 核心代码: int find(int x){//返回父节点if(x ! p[x]) {p[x] find(p[x]);//路径压缩 } //孩子不等于爸爸,就…

如何搭建APP分发平台分发平台搭建教程

搭建一个APP分发平台可以帮助开发者更好地分发和管理他们的应用程序。下面是一个简要的教程,介绍如何搭建一个APP分发平台。 1.确定需求和功能:首先,确定你的APP分发平台的需求和功能。考虑以下几个方面: 用户注册和登录&#xff…

Kali WSL2(windows下安装了kali)

自从WSL2以来,感觉各方面也挺好的,有时候比vmware workstation方便,特别单独使用一个linux的时候。所以研究了下kali,也是很OK的,以及验证完成了。 本文参考官网: Kali Linux | Penetration Testing and Et…

【氮化镓】在轨实验研究辐射对GaN器件的影响

【Pioneering evaluation of GaN transistors in geostationary satellites】 摘要: 这篇论文介绍了一项为期6年的空间实验结果,该实验研究了在地球静止轨道上辐射对氮化镓(GaN)电子元件的影响。实验使用了四个GaN晶体管&#xf…

python绘制子图(旭日图、渐变堆积面积图、多数据折线图、比例关系图)

大家好,我是带我去滑雪! 子图可以更清晰地展示和理解复杂的数据关系,通过将数据分成多个小图,有助于观察数据间的关系和趋势。减少数据之间的重叠和混淆,使得每个子图更易于理解和解释。不同类型的子图可以呈现数据的不…

房企如何驱动新“三驾马车”,穿越地产周期?

今年以来,房地产行业在不确定性的周期中,逐渐显露出部分确定性。 今年两会期间,住建部明确指出,构建发展新模式是破解房地产发展难题的治本之策,在新模式下今后拼的是高质量、新科技、好服务。可以说,国家…

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换 前言代码实现思路实验结果 前言 Computed Tomography(CT,计算机断层成像)技术作为如今医学中重要的辅助诊断手段,也是医学图像研究的重要主题。如今,随…

前端三剑客 —— JavaScript (第一节)

目录 回顾内容 1.弹性布局 2.网格布局 JavaScript 概述 发展 浏览器 什么是Javascript JavaScript 能干什么 JavaScript需要的环境 JavaScript初体验 基本数据 JS书写方式 行内JS 页面JS 外部JS 1)创建外部JS文件 2)编写页面 对话框 警…

[C语言][数据结构][动态内存空间的开辟]顺序表的实现!

目录 零.必备知识 a.顺序表的底层是数组. b.数组在内存中是连续存放的. c.动态内存空间的开辟(malloc,calloc,realloc). 一.顺序表的定义与实现 1.1 顺序表的定义 1.2 顺序表的初始化 1.3 顺序表的销毁 1.4 顺序表容量的检查与调整(最关键的部分) 1.5 顺序表的尾插 1.…

【Flutter】Getx设计模式及Provider、Repository、Controller、View等

本文基于Getx 4,x 本本 1、引入 再次接触到Flutter项目,社区俨然很完善和活跃。pubs.dev 寻找状态管理的时候看到很熟悉的Getx时间,俨然发现Getx的版本已到是4.x版本,看到Getx的功能已经非常强大了,庞大的API俨然成为一种开发框架…

通俗易懂的理解 ADC(2)

理解什么是ADC 文章目录 1、通俗理解什么是ADC 2、什么是ADC 3、ADC的采样率 4、采样位数 5、采样精度 ADC实际没有这么的简单,深入了解需要去学各种寄存器之间如何协作,信号如何走通。这些概念在后面会有讲解。 1、通俗理解…

[mmu/cache]-MMU的地址翻译(Address translation)指令介绍

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 Address translation system instructions AT指令的语法格式: 有了上面的语法格式后,就非常好理解armv8的MMU提供了14条AT指令了: MMU的地址…

[mmu/cache]-ARMV8的cache的维护指令介绍

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 Armv8里定义的Cache的管理的操作有三种: 无效(Invalidate) 整个高速缓存或者某个高速缓存行。高速缓存上的数据会被丢弃。清除(Cl…

#{} 和 ${}区别

1、参数是Integer类型时候没区别(#是预编译SQL,$是即时SQL) 2、当参数是String类型时,就会出错了 (1)这是$的报错信息,因为我们的参数admin并没有加引号所以不满足字符串条件 (2)正确的SQL &am…

FJSP:美洲狮优化算法(Puma Optimizar Algorithm ,POA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题(Flexible Job Shop Scheduling Problem,FJSP),是一种经典的组合优化问题。在FJSP问题中,有多个作业需要在多个机器上进行加工,每个作业由一系列工序组成&a…

用可视化案例讲Rust编程5.用泛型和特性实现自适配绘制和颜色设置

上一节我们讲了用泛型实现返回结果,这一节我们来讲讲在函数签名里面使用泛型来对输入参数进行自适配。 先看UML设计图: 好吧,看起来有点复杂,我们一个个来解释。 首先定义的是一个生成绘图元素需要的参数结构,并且定义个特性&am…

LeetCode-1483. 树节点的第 K 个祖先【树 深度优先搜索 广度优先搜索 设计 二分查找 动态规划】

LeetCode-1483. 树节点的第 K 个祖先【树 深度优先搜索 广度优先搜索 设计 二分查找 动态规划】 题目描述:解题思路一:暴力解法会超时!【一级一级往上跳,效率太低】解题思路二:倍增,利用二进制运算&#xf…