在PyCharm中使用Pytest测试框架
在PyCharm中使用Pytest测试框架
本文将详细介绍如何在PyCharm中使用Pytest测试框架。Pytest是Python语言中一款强大的单元测试框架,具有兼容性好、丰富的插件支持、使用方便等特点。通过本文的学习,你将掌握如何在PyCharm中配置和使用Pytest,以及Pytest的一些高级特性。
1. Pytest 介绍
Pytest是Python语言中一款强大的单元测试框架,它是基于unittest开发的扩展框架,用来管理和组织测试用例,可应用在单元测试、自动化测试工作中。
Pytest主要特点:
- 兼容性好:支持Python 2.7,Python 3.4+。
- 与unittest和nose测试框架兼容:如果之前测试用例全部是基于unittest或者nose来编写的,执行Pytest命令同样可以正常运行并得到结果。因此无需担心迁移测框架从而带来额外的人工成本。
- 丰富的插件支持:大约有300多个,像Pytest-repeat, pytest-xdist,pytest-ordering,pytest-rerunfailures以及pytest-html这些常用插件在测试重复执行、并发与生成报告方面都提供了非常强大的支持。
- 允许直接使用assert进行断言:相比unittest简单,unittest定义了assertEqual、assertIn、assertTrue、assertFalse等一系列断言。
- 可以自动寻找单测文件、类和函数:Pytest要求所有的单测文件名都需要满足test_.py格式或_test.py格式。在单测文件中,可以包含test_开头的函数,也可以包含Test开头的类。在单测类中,可以包含一个或多个test_开头的函数。在执行Pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行。
- 提供应用不同范围前置/后置方法:Pytest提供了模块级、函数级、类级、方法级的setup/teardown,比unittest的setUp/tearDown更灵活。
- 分类执行与测试数据参数化简单: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是功能非常强大的测试框架,在业内也比较被推崇,如果想真正掌握,建议多参考官方文档及相关的插件说明文档,这将帮助我们在开发单元测试与自动化测试过程中事半功倍。