1.安装pytest
pytest要求:Python 3.6、3.7、3.8、3.9或PyPy3。
(1)在命令行中执行如下命令:
pip install -U pytest
执行结果:
(2)检查你是否安装了正确的版本:
(venv) E:\auto_pytest>pytest --version
pytest 6.2.3
2.创建第一个测试
创建一个名为test_sample.py的新文件,包含一个函数和一个测试:
#!/usr/bin/env python
# encoding: utf-8
"""
@author: 九九的金金子
@file: test_sample.py.py
@time: 2021/4/12 11:56
"""
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
执行及结果:
(venv) E:\auto_pytest>pytest test_sample.py
========================================================================== test session starts ==========================================================================
platform win32 -- Python 3.7.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
rootdir: E:\auto_pytest
plugins: allure-pytest-2.8.32
collected 1 item
test_sample.py F [100%]
=============================================================================== FAILURES ================================================================================
______________________________________________________________________________ test_answer ______________________________________________________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:14: AssertionError
======================================================================== short test summary info ========================================================================
FAILED test_sample.py::test_answer - assert 4 == 5
=========================================================================== 1 failed in 0.13s ===========================================================================
[100%]指的是运行所有测试用例的总体进度。完成后,pytest会显示一个失败报告,因为func(3)不返回5。
注意:
您可以使用assert语句来验证测试期望。pytest的高级断言内将智能地报告断言表达式的中间值。
3.运行多个测试
pytest将运行当前目录及其子目录中所有形式为test_.py或_test.py的文件。更一般地说,它遵循标准的测试发现规则。
断言某个异常被引发
使用raises助手来断言某些代码引发异常:
#!/usr/bin/env python
# encoding: utf-8
"""
@author: 九九的金金子
@file: test_sysexit.py
@time: 2021/4/12 13:49
"""
# content of test_sysexit.py
import pytest
def f():
raise SystemExit(1)
def test_mytest():
with pytest.raises(SystemExit):
f()
执行及结果:
(venv) E:\auto_pytest>pytest -q test_sysexit.py
. [100%]
1 passed in 0.12s
q/——quiet标志在这个示例和下面的示例中保持输出简短。
4.将多个测试分组到一个类中
一旦开发了多个测试,您可能希望将它们分组到一个类中。pytest让创建包含多个测试的类变得很容易:
#!/usr/bin/env python
# encoding: utf-8
"""
@author: 九九的金金子
@file: test_class.py
@time: 2021/4/12 13:52
"""
# content of test_class.py
class TestClass:
def test_one(self):
x = "this"
assert "h" in x
def test_two(self):
x = "hello"
assert hasattr(x, "check")
pytest发现所有遵循Python测试发现约定的测试,因此它发现两个以test_为前缀的函数。不需要子类化任何东西,但是要确保用Test作为类的前缀,否则类将被跳过。我们可以简单地通过传递它的文件名来运行模块:
执行及结果:
(venv) E:\auto_pytest>pytest -q test_class.py
.F [100%]
=============================================================================== FAILURES ================================================================================
__________________________________________________________________________ TestClass.test_two ___________________________________________________________________________
self = <test_class.TestClass object at 0x000001934888F248>
def test_two(self):
x = "hello"
> assert hasattr(x, "check")
E AssertionError: assert False
E + where False = hasattr('hello', 'check')
test_class.py:16: AssertionError
======================================================================== short test summary info ========================================================================
FAILED test_class.py::TestClass::test_two - AssertionError: assert False
1 failed, 1 passed in 0.12s
第一次测试通过了,第二次测试失败了。您可以很容易地看到断言中的中间值,以帮助您理解失败的原因。
将测试分组在类中是有益的,原因如下:
- 测试组织
- 仅为该特定类中的测试共享fixture
- 在类级别上应用标记,并隐式地将它们应用于所有测试进入翻译页面
在将测试分组到类中时,需要注意的是每个测试都有一个类的唯一实例。让每个测试共享相同的类实例对测试隔离非常不利,并且会促进糟糕的测试实践。这一点概述如下:
#!/usr/bin/env python
# encoding: utf-8
"""
@author: 九九的金金子
@file: test_class_demo.py
@time: 2021/4/12 13:56
"""
# content of test_class_demo.py
class TestClassDemoInstance:
def test_one(self):
assert 0
def test_two(self):
assert 0
执行及结果:
(venv) E:\auto_pytest>pytest -k TestClassDemoInstance -q
FF [100%]
=============================================================================== FAILURES ================================================================================
____________________________________________________________________ TestClassDemoInstance.test_one _____________________________________________________________________
self = <test_class_demo.TestClassDemoInstance object at 0x00000228F08E27C8>
def test_one(self):
> assert 0
E assert 0
test_class_demo.py:11: AssertionError
____________________________________________________________________ TestClassDemoInstance.test_two _____________________________________________________________________
self = <test_class_demo.TestClassDemoInstance object at 0x00000228F08DE748>
def test_two(self):
> assert 0
E assert 0
test_class_demo.py:14: AssertionError
======================================================================== short test summary info ========================================================================
FAILED test_class_demo.py::TestClassDemoInstance::test_one - assert 0
FAILED test_class_demo.py::TestClassDemoInstance::test_two - assert 0
2 failed, 5 deselected in 0.19s
请注意,在类级别添加的属性是类属性,因此它们将在测试之间共享。
5.为功能测试请求一个唯一的临时目录
pytest提供了内置的fixture /函数参数来请求任意资源,比如一个唯一的临时目录:
#!/usr/bin/env python
# encoding: utf-8
"""
@author: 九九的金金子
@file: test_tmp_path.py
@time: 2021/4/12 13:58
"""
# content of test_tmp_path.py
def test_needsfiles(tmp_path):
print(tmp_path)
assert 0
在测试函数签名中列出名称tmp_path, pytest将在执行测试函数调用之前查找并调用fixture工厂来创建资源。在运行测试之前,pytest创建一个每调用一次测试唯一的临时目录:
执行及结果:
(venv) E:\auto_pytest>pytest -q test_tmp_path.py
F [100%]
=============================================================================== FAILURES ================================================================================
____________________________________________________________________________ test_needsfiles ____________________________________________________________________________
tmp_path = WindowsPath('C:/Users/01399256/AppData/Local/Temp/pytest-of-01399256/pytest-2/test_needsfiles0')
def test_needsfiles(tmp_path):
print(tmp_path)
> assert 0
E assert 0
test_tmp_path.py:11: AssertionError
------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------
C:\Users\01399256\AppData\Local\Temp\pytest-of-01399256\pytest-2\test_needsfiles0
======================================================================== short test summary info ========================================================================
FAILED test_tmp_path.py::test_needsfiles - assert 0
1 failed in 0.19s
关于临时目录处理的更多信息可以在临时目录和文件中找到。
找出该命令存在哪种类型的内置pytest fixture:
pytest --fixtures # shows builtin and custom fixtures
注意,除非添加了-v选项,否则这个命令会省略以_开头的fixture。