问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

在PyCharm中使用Pytest测试框架

创作时间:
作者:
@小白创作中心

在PyCharm中使用Pytest测试框架

引用
1
来源
1.
http://m.imooc.com/wiki/pycharmlesson-pytest

本文将详细介绍如何在PyCharm中使用Pytest测试框架。Pytest是Python语言中一款强大的单元测试框架,具有兼容性好、丰富的插件支持、使用方便等特点。通过本文的学习,你将掌握如何在PyCharm中配置和使用Pytest,以及Pytest的一些高级特性。

1. Pytest 介绍

Pytest是Python语言中一款强大的单元测试框架,它是基于unittest开发的扩展框架,用来管理和组织测试用例,可应用在单元测试、自动化测试工作中。

Pytest主要特点:

  1. 兼容性好:支持Python 2.7,Python 3.4+。
  2. 与unittest和nose测试框架兼容:如果之前测试用例全部是基于unittest或者nose来编写的,执行Pytest命令同样可以正常运行并得到结果。因此无需担心迁移测框架从而带来额外的人工成本。
  3. 丰富的插件支持:大约有300多个,像Pytest-repeat, pytest-xdist,pytest-ordering,pytest-rerunfailures以及pytest-html这些常用插件在测试重复执行、并发与生成报告方面都提供了非常强大的支持。
  4. 允许直接使用assert进行断言:相比unittest简单,unittest定义了assertEqual、assertIn、assertTrue、assertFalse等一系列断言。
  5. 可以自动寻找单测文件、类和函数:Pytest要求所有的单测文件名都需要满足test_.py格式或_test.py格式。在单测文件中,可以包含test_开头的函数,也可以包含Test开头的类。在单测类中,可以包含一个或多个test_开头的函数。在执行Pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行。
  6. 提供应用不同范围前置/后置方法:Pytest提供了模块级、函数级、类级、方法级的setup/teardown,比unittest的setUp/tearDown更灵活。
  7. 分类执行与测试数据参数化简单:unittest需依赖ddt库实现数据参数化,而Pytest直接使用@pytest.mark.parametrize装饰器。

总之,Pytest因其功能强大性及使用的方便性,已经成为主流的测试框架之一,unittest更适合入门级的测试,当执行比较复杂的测试Pytest就更适合一些,这也是为什么我们会单列一小节讲Pytest的原因。更多关于Pytest使用请参考官网。

2. 使用Pytest执行测试

在PyCharm里使用Pytest执行测试的过程与unittest是一致的,所以对于步骤上的操作在本小节将不再过多说明,将把重点关注在Pytest一些特性上。

2.1 配置测试框架

主菜单:

PyCharm/File -> Preference/Settings -> Tools -> Python Integrated Tools

点击Default Test Runner选择Pytest。

2.2 创建测试

创建一个新的Python project,增加新文件rectangle.py,添加下面的代码到文件,继续沿用上一小节用到的待测代码。

import math

class Rectangle:
    def __init__(self, length, width, size=(40, 20)):
        self.length = length
        self.width = width
        self._size = size

    def area(self):
        area = self.length * self.width
        return area

    def perimeter(self):
        perimeter = (self.length + self.width) * 2
        return perimeter

    def diff(self):
        diff = math.fabs(self.length - self.width)
        return diff

    def resize(self, width, height):
        if width <= 0 or height <= 0:
            raise ValueError("illegal size")
        self._size = (width, height)

    def get_length(self):
        return self.length

    def get_width(self):
        return self.width

在编辑器中,将光标放在类声明或方法中的位置。

  • 从主菜单中,选择

Navigate -> Test

  • 编辑器内,右键上下文菜单中选择

Go to -> Test (⌘⇧T: Ctrl + Shift + T)

PyCharm显示可用测试的列表。单击"创建新测试"。在打开Create test对话框中进行设置,点击OK会自动生成测试文件test_rectangle与测试方法模板。

生成的模板如下图所示:没有像unittest那样创建同名测试类,无需像导入unittest一样导入pytest,断言直接用assert。使用pytest写测试用例看上去更简单一些。

2.3 修改代码与执行测试

根据Pytest规则更新代码:

from rectangle import Rectangle

def test_area():
    rect = Rectangle(30, 15)
    assert rect.area() == 450

def test_perimeter():
    rect = Rectangle(30, 15)
    assert rect.perimeter() == 90

在编辑器的上下文菜单,选择Run pytest for Name,会默认运行当前文件所有以‘test’开头的所有方法。Run窗口会自动弹出,显示测试结果。

3. Pytest一些特性

从上面介绍可以看出,无论用哪种测试框架,基本流程都是一样的。下面介绍一些Pytest一些特性,这些特性都是使用频率比较高,也是相对于unittest测试功能更为便利与先进的功能。

3.1 使用fixture

fixture是Pytest特有的功能,它用pytest.fixture标识,定义在函数前面。在你编写测试函数的时候,你可以将此函数名称做为传入参数,pytest将会以依赖注入方式,将该函数的返回值作为测试函数的传入参数。

我们可以把fixture看做是资源,在你的测试用例执行之前需要去配置这些资源,执行完后需要去释放资源。比如module类型的fixture,适合于那些许多测试用例都只需要执行一次的操作。更多使用请参考这里

上面的两个测试方法都有

rect = Rectangle(30, 15)

实例化类,此时可以使用fixture简化代码:

from rectangle import Rectangle
import pytest

@pytest.fixture()
def my_rect():
    rect = Rectangle(30, 15)
    return rect

def test_area(my_rect):
    assert my_rect.area() == 450

def test_perimeter(my_rect):
    assert my_rect.perimeter() == 90

3.2 标记用例

pytest.mark定义在函数前面。可以给用例打标签,用于给用例分类与筛选用例。每个用例可以加多个标签。在执行用例时根据标签名选择执行。相比unittest通过TestSuite加载不同的测试用例要方便的多。

from rectangle import Rectangle
import pytest

@pytest.fixture()
def my_rect():
    rect = Rectangle(30, 15)
    return rect

@pytest.mark.smoke
@pytest.mark.p1
def test_area(my_rect):
    assert my_rect.area() == 450

@pytest.mark.regression
def test_perimeter(my_rect):
    assert my_rect.perimeter() == 90

在运行之前,需要先创建一个pytest.ini文件在当前项目下,注册标签名。

[pytest]
markers=
    smoke
    p1
    regression

运行的时候加参数-m 标签名,就可以只执行带标签名的用例。

3.3 测试数据参数化

你可能希望在预定义的数据集上运行测试。PyCharm支持通过@pytest.mark.parametrize在pytest中实现的测试参数化。更多使用参考

增加下面的测试用例在test_rectangle.py文件中,传递三个参数两组数据给测试用例。如果数据可以用于其它用例,也可以定义数据做为全局变量。

@pytest.mark.parametrize(("length", "width", "expected_diff"), [(30, 20, 10), (20, 20, 0)])
def test_diff(length, width, expected_diff):
    rect = Rectangle(length, width)
    assert rect.diff() == expected_diff

点击编辑器侧边框绿色箭头执行上面的用例,可以看到用例执行了两次:

3.4 重复运行用例

有时候需要重复运行单个用例,Pytest也提供相应的插件支持。需要事先安装包pytest-repeat,Preference/Settings -> Project -> Python Interpreter

通过在函数前加@pytest.mark.repeat(次数),指定函数重复的次数,也可以通过命令行–count=次数,为所有函数级别方法指定重复次数。

@pytest.mark.regression
@pytest.mark.repeat(5)
def test_perimeter(my_rect):
    assert my_rect.perimeter() == 90

执行测试用例,可以看到用例被执行了5次:

3.5 并发执行用例

有时候为了节省测试时间,需要并发执行测试用例。Pytest是支持并发测试的,需提前安装包pytest-xdist。运行的时候加参数-n 并发进程数或者-n auto(根据当前cpu信息自动分配合理的核数运行用例。也可以在pytest.ini指定。

[pytest]
addopts = -n3

为了增强演示效果,在三个用例里都增加了10秒的延迟,并设置了三个并发,可以观察到三个用例是同时执行的。

Tips:当使用这个插件做并发测试时,只能用于没有依赖关系的测试用例。

4. 小结

本节主要介绍了在PyCharm里如何使用Pytest测试框架和一些测试过程中常用插件。Pytest是功能非常强大的测试框架,在业内也比较被推崇,如果想真正掌握,建议多参考官方文档及相关的插件说明文档,这将帮助我们在开发单元测试与自动化测试过程中事半功倍。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号