书籍来源:房荔枝 梁丽丽《pytest框架与自动化测试应用》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:pytest框架进阶自学系列 | 汇总_热爱编程的通信人的博客-CSDN博客
在终端建立测试方法及执行过程
(1)在计算机磁盘上创建test_one.py文件。
(2)可以先使用记事本打开该文件,输入如下信息后保存并关闭文件。此文件定义了方法,以及断言1是否等于1。
def test_one():
assert 1 == 1
(3)在终端输入命令。
(4)或输入pytest加空格后把文件拖曳过去。
(5)按回车键执行。
执行结果如图1-2所示,它们的含义分别对应如下:
平台win32、Python的版本、pytest的版本、自带插件及版本。
根目录。
第三方插件及版本。
收集到1个测试。
文件名后面的点表示通过。
最下面一行是1,表示通过,所花费的时间为0.03s。
PS D:\SynologyDrive\CodeLearning\WIN\pytest_learning> pytest .\test_one.py
========================================================================================================= test session starts =========================================================================================================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest_learning
collected 1 item
test_one.py . [100%]
========================================================================================================== 1 passed in 0.32s ==========================================================================================================
PS D:\SynologyDrive\CodeLearning\WIN\pytest_learning>
注意:通常pytest执行测试用例的执行方式都是这种命令行的方式。
在PyCharm建立测试方法及执行过程
如果需要进行大量Python脚本的编写,我们则需要Python的IDE工具。下面的操作是在PyCharm中完成的。已建立项目pytest_book。
(1)新建test_first.py文件。
(2)输入import pytest#这是将pytest框架导入。
(3)建立一个测试方法def test_1():。
(4)缩进后输入print(“这是第一个测试方法”)。
(5)在下面输入if__name__=="__main__":。
注:name和main前后都是两个小短横。
(6)缩进后输入pytest.main(["-s","test_first.py"])。
(7)单击if左边的按钮,执行代码,如图1-3所示。
完整代码如下:
import pytest
def test_1():
print("这是第一个测试方法")
if __name__ == '__main__':
pytest.main("-s", "test_first.py")
执行结果如下:最后一句中的code 0表示没有执行错误。如果执行失败,则显示为code 1。
D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm Community Edition 2022.3.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_first.py
Testing started at 17:04 ...
Launching pytest with arguments D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_first.py in D:\SynologyDrive\CodeLearning\WIN\pytest_learning
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest_learning
collecting ... collected 1 item
test_first.py::test_1 PASSED [100%]这是第一个测试方法
============================== 1 passed in 0.01s ==============================
Process finished with exit code 0
注意:最后一句的快捷方式:直接输入main,按回车键后会自动建立主函数调用。import pytest如果有红色下波浪线,则表示没有导入成功。通常是由于计算机中除默认的环境以外,还有其他Python环境。更换到已经安装完pytest的Python环境便可以解决此问题,或把每个环境都安装上。
pytest的框架结构
在执行测试的过程中,我们经常会做些准备工作,再进行测试,测试完成后通常也会将现场恢复原状,因此我们希望执行测试的框架能提供各层次的测试前和测试后的方法。
绝大多数的测试框架只提供setup与teardown。在setup的方法中进行准备代码,在teardown方法中进行销毁代码。
pytest提供了相对自由和层次丰富的setup与teardown框架结构。pytest支持5个层次的setup和teardown,包括:session会话级、module模块级、function函数级、class类级、method方法级。
(1)模块级(setup_module/teardown_module):开始于模块始末(不在类中)。
(2)函数级(setup_function/teardown_function):对函数用例生效(不在类中)。
(3)方法级(setup_method/teardown_method):开始于方法始末(在类中)。
(4)类级(setup_class/teardown_class):只在类中前后运行一次(在类中)。
(5)还有兼容的类里面的层级(setup/teardown):运行在调用方法的前后。
这些级别用在配置初始化setup和销毁teardown中,同样可以配合pytest中fixture功能而变得更强大。将在3.3节具体讲解。
下面给大家逐步演示常用级别所影响的范围层次。先演示模块级和函数级,之后演示方法级、类级及兼容的setup和teardown,最后将整体5个常用级别放在一起演示执行效果。
模块和函数级实践步骤如下:
(1)新建Python文件test_frame_1.py。
(2)在文件中输入如下代码。
(3)单击执行代码。
(4)查看运行结果是否与方法中输入的文字含义相同。
完整代码如下:
import pytest
def setup_module():
print("\nsetup_module: 整个 test_module.py 模块只执行一次")
def teardown_module():
print("teardown_module: 整个 test_module.py 模块只执行一次")
def setup_function():
print("\nsetup_function: 每个用例开始前都会执行")
def teardown_function():
print("teardown_function: 每个用例结束后都会执行")
def test_one():
print("正在执行测试模块----test_one")
def test_two():
print("正在执行测试模块----test_two")
if __name__ == '__main__':
pytest.main(['-s', 'test_frame_1.py'])
执行结果如下:module级在py文件中只执行一次,function则在非类的测试方法前后执行,每个测试方法都会调用一次。
D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm Community Edition 2022.3.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_frame_1.py
Testing started at 17:16 ...
Launching pytest with arguments D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_frame_1.py in D:\SynologyDrive\CodeLearning\WIN\pytest_learning
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest_learning
collecting ... collected 2 items
test_frame_1.py::test_one
setup_module: 整个 test_module.py 模块只执行一次
setup_function: 每个用例开始前都会执行
PASSED [ 50%]正在执行测试模块----test_one
teardown_function: 每个用例结束后都会执行
test_frame_1.py::test_two
setup_function: 每个用例开始前都会执行
PASSED [100%]正在执行测试模块----test_two
teardown_function: 每个用例结束后都会执行
teardown_module: 整个 test_module.py 模块只执行一次
============================== 2 passed in 0.09s ==============================
Process finished with exit code 0
类和方法级实践如下:
(1)新建Python文件test_frame_2.py。
(2)在文件中输入如下代码。
(3)单击执行代码。
(4)查看运行结果是否与方法中输入的文字含义相同。
完整代码如下:
import pytest
class TestCase(object):
def setup_class(self):
print("\nsetup_class: 所有用例执行之前")
def teardown_class(self):
print("teardown_class: 所有用例执行之后")
def setup_method(self):
print("\nsetup_method: 每个用例开始前执行")
def teardown_method(self):
print("teardown_method: 每个用例结束后执行")
def setup(self):
print("setup: 每个用例开始前都会执行")
def teardown(self):
print("teardown: 每个用例结束后都会执行")
def test_three(self):
print("正在执行测试类----test_three")
def test_four(self):
print("正在执行测试类----test_four")
if __name__ == '__main__':
pytest.main(["-s", "test_frame_2.py"])
执行结果如下:
D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm Community Edition 2022.3.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_frame_2.py
Testing started at 17:21 ...
Launching pytest with arguments D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_frame_2.py in D:\SynologyDrive\CodeLearning\WIN\pytest_learning
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest_learning
collecting ... collected 2 items
test_frame_2.py::TestCase::test_three
setup_class: 所有用例执行之前
setup_method: 每个用例开始前执行
setup: 每个用例开始前都会执行
PASSED [ 50%]正在执行测试类----test_three
teardown: 每个用例结束后都会执行
teardown_method: 每个用例结束后执行
test_frame_2.py::TestCase::test_four
setup_method: 每个用例开始前执行
setup: 每个用例开始前都会执行
PASSED [100%]正在执行测试类----test_four
teardown: 每个用例结束后都会执行
teardown_method: 每个用例结束后执行
teardown_class: 所有用例执行之后
============================== 2 passed in 0.06s ==============================
Process finished with exit code 0
将类中方法和非在类中的方法等所有级放在一起执行,代码如下:
import pytest
def setup_module():
print("\nsetup_module: 整个test_module.py模块只执行一次")
def teardown_module():
print("teardown_module: 整个test_module.py模块只执行一次")
def setup_function():
print("\nsetup_function: 每个非类函数测试用例开始前都会执行")
def teardown_function():
print("teardown_function: 每个非类函数测试用例结束后都会执行")
def test_one():
print("正在执行测试模块----test_one")
def test_two():
print("正在执行测试模块----test_two")
class TestCase(object):
def setup_class(self):
print("\nsetup_class: 在类中所有测试用例执行之前")
def teardown_class(self):
print("teardown_class: 在类中所有测试用例执行之后")
def setup_method(self):
print("setup_method: 每个类中测试方法用例开始前执行")
def teardown_method(self):
print("teardown_method: 每个类中测试方法用例结束后执行")
def setup(self):
print("setup: 每个类中测试方法用例开始前执行")
def teardown(self):
print("teardown: 每个类中测试方法用例结束后都会执行")
def test_three(self):
print("正在执行测试类----test_three")
def test_four(self):
print("正在执行测试类----test_four")
if __name__ == '__main__':
pytest.main("-s", "test_frame.py")
执行结果如下:
D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm Community Edition 2022.3.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_frame.py
Testing started at 17:28 ...
Launching pytest with arguments D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_frame.py in D:\SynologyDrive\CodeLearning\WIN\pytest_learning
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest_learning
collecting ... collected 4 items
test_frame.py::test_one
setup_module: 整个test_module.py模块只执行一次
setup_function: 每个非类函数测试用例开始前都会执行
PASSED [ 25%]正在执行测试模块----test_one
teardown_function: 每个非类函数测试用例结束后都会执行
test_frame.py::test_two
setup_function: 每个非类函数测试用例开始前都会执行
PASSED [ 50%]正在执行测试模块----test_two
teardown_function: 每个非类函数测试用例结束后都会执行
test_frame.py::TestCase::test_three
setup_class: 在类中所有测试用例执行之前
setup_method: 每个类中测试方法用例开始前执行
setup: 每个类中测试方法用例开始前执行
PASSED [ 75%]正在执行测试类----test_three
teardown: 每个类中测试方法用例结束后都会执行
teardown_method: 每个类中测试方法用例结束后执行
test_frame.py::TestCase::test_four setup_method: 每个类中测试方法用例开始前执行
setup: 每个类中测试方法用例开始前执行
PASSED [100%]正在执行测试类----test_four
teardown: 每个类中测试方法用例结束后都会执行
teardown_method: 每个类中测试方法用例结束后执行
teardown_class: 在类中所有测试用例执行之后
teardown_module: 整个test_module.py模块只执行一次
============================== 4 passed in 0.07s ==============================
Process finished with exit code 0
在PyCharm中配置运行工具
刚才我们执行脚本是通过main方法执行的,也就是通过Python调用pytest的main方法执行。PyCharm支持pytest工具的执行方式,接下来讲解如何配置。
Windows系统下的配置如图1-6所示,单击File→Setting→Tools→Python Intergrated Tools,在Default test runner中选择py.test,单击OK或Apply按钮保存。
配置完成后,执行方式可以很灵活。既可以通过main方法执行,还可以通过pytest直接执行。
右击以pytest方式执行代码
我们可以通过右击选择运行test_first.py,如图1-7所示。
去掉main方法执行测试
真正编写代码时我们很少通过main方法执行,所以写代码时便不加main方法了。
修改test_first的代码如下:
import pytest
def test_1():
print("\n这是第一个测试方法")
def test_3():
print("\n这是第3个测试方法")
def t_2():
print("这是第2个测试方法")
在不是方法名的任何行用鼠标右击选择pytest in test_first并执行。
执行结果如下:
D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm Community Edition 2022.3.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_first.py
Testing started at 17:43 ...
Launching pytest with arguments D:\SynologyDrive\CodeLearning\WIN\pytest_learning\test_first.py in D:\SynologyDrive\CodeLearning\WIN\pytest_learning
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest_learning\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest_learning
collecting ... collected 2 items
test_first.py::test_1 PASSED [ 50%]
这是第一个测试方法
test_first.py::test_3 PASSED [100%]
这是第3个测试方法
============================== 2 passed in 0.19s ==============================
Process finished with exit code 0
PyCharm中执行某个测试方法
通常有以下两种方式:
(1)在某个测试方法所在行单击鼠标右键,只执行这个测试方法。
(2)使用左边按钮,只执行这个测试方法。
大家在实践过程中如果出现按上面方式操作仍执行全部测试方法,或单击鼠标右键执行时出现下面的结果,如图1-8所示,则需要修改一下执行配置。
执行配置修改步骤如下:
(1)选择工具栏中的配置:单击。
(2)单击Edit Configurations。
(3)在弹出的运行调试配置窗口中单击“+”。
(4)选择Python tests。
(5)在出现的窗口右侧的Configuration中选择Module name。
(6)在下面的文本框中输入test_first.test_1(前面是文件名,点后面是方法名)。
(7)如果此时Name没有自动填上,则可输入如图1-10所示的名字。
(8)保存。
修改完配置后,可以验证通过上述两种方式执行某一个测试方法是否成功。
注意:有些版本配置需要先关闭,然后重新打开PyCharm才配置成功。
运行窗口的工具栏含义
在pytest初体验过程中,我们了解了如何编写测试方法。如果需要执行并查看执行的结果,那么运行窗口中的工具都有什么含义呢?
运行窗口如图1-11所示,具体含义依次是:
- 对号表示可以查看所有通过的测试用例;
- 禁止号表示可以查看所有忽略的测试用例;
- 按a~z的顺序排序;
- 按执行的时间排序;
- 展开所有结果;
- 收起所有结果;
- 向上箭头表示执行前一个失败的用例;
- 向下箭头表示执行下一个失败的用例;
- 导出测试结果;
- 钟表表示导入执行过的测试结果可选;
- 最后一个是工具选项。
左侧框中工具如图1-12所示,其含义从上到下依次是:
- 绿色为运行测试方法;
- 重新运行失败的测试用例;
- 切换自动测试;
- 停止测试;
- 默认布局;
- 钉住窗口。