1. 测试脚本的运行方式
unittest 测试脚本可以在 IDE 开发工具中直接运行,也可以通过命令行方式运行。这里取 PyCharm 中的两种运行方式以及命令行运行方式进行比较。
- 表中的三种运行方式,最终都是调用了 mian() 方法运行测试脚本,区别只是传参不同
- Python tests 运行方式通过 PyCharm 自带的插件(Teamcity)遍历并运行当前模块下的测试,但是不会执行 “if __name__ == '__main__':” 中的代码
2. 在 PyCharm 中运行测试脚本
在PyCharm中运行测试脚本主要分两类:“Python” 和 “Python tests” 方式,Python 方式是按标准的 python 方式运行当前模块中的测试,Python tests 方式是通过 PyCharm 自带的插件运行测试,两者的运行参数不同,运行器及测试结果输出的方式也不同。
打开测试脚本的Tab页签,依次选择菜单 Run -> Run...,弹出的运行窗口可见两种运行方式:
- Python 运行方式: 与当前测试脚本的模块名称相同。以 “if __name__ == '__main__':” 为运行的入口
- Python Tests 运行方式: Python tests for + 当前测试脚本的模块名称(或用例名称、或方法名称)。具体执行的测试对象与当前鼠标焦点位置有关:
- 如果当前焦点位于测试用例类所在行,则运行当前用例中的所有测试方法。
- 如果当前焦点位于某个测试方法所在行,则运行当前的测试方法。
- 如果当前焦点位于其它非以上区域,则运行当前模块下所有用例中的所有测试方法
- 也可以先用鼠标定位焦点行,再直接通过右键选择 “Run Python tests for ...” 来运行指定的测试对象
- 注意:此运行方式下,不会执行 “if __name__ == '__main__':” 下的代码。
2.1. 自行配置脚本运行方式
在PyCharm中可以通过 “Edit Configurations...” 进行脚本运行方式的配置,配置好后可以直接通过工具条上的运行按钮来快速运行。
进入配置运行方式窗口,在左侧的目录中可见已经配置好的运行方式。通过上面的 “+” 和 “-” 可以自行增减配置项。
- Python 运行方式,需要在右侧选择相应的测试脚本路径即可。
- Python tests 运行方式,需要在右侧选择 “模块名称” 或者 “测试脚本路径”
2.2. Python 运行方式
PyCharm 运行方式是在当前模块运行入口处,从 “unittest.main()” 语句开始运行测试脚本。
import unittest
# 测试用例: Test为前缀,继承自TestCase
class TestLab02(unittest.TestCase):
# 测试方法:test为前缀
def test_02(self):
# 断言判断结果的正确性
self.assertEqual(1, 1)
def test_lab(self):
# 断言判断结果的正确性
self.assertEqual(1, 1)
if __name__ == '__main__':
# 从这里开始运行测试脚本
unittest.main()
在运行列表处,选择当前脚本的“Python”运行方式执行,运行结果如下,显示两个点 “.”,每个点代表运行通过了一个测试方法。
如果要显示更详细的信息,可以在运行脚本处增加一个verbosity参数。 这个参数默认为1,就是简洁显示方式,即每通过的测试方法显示为一个点 “.”,如果该方法运行失败则显示为 “F”,如果该参数设为大于1的整数值,则显示更详细的信息。
将运行语句改为: unittest.main(verbosity=2),运行结果显示如下,输出了每个测试方法的名称及是否通过
2.3. Python tests 运行方式
Python tests 的运行方式不从 “ if __name__ == '__main__' ” 这个入口开始执行测试脚本,而是通过 PyCharm 提前内置好的方式自动搜索当前脚本中的测试用例和测试方法,进而自动运行这些测试,即 “ if __name__ == '__main__' ” 语句块中的语句都不被其运行。
2.4. 原因简析
python 运行方式
打开对应源码(按下Ctrl键同时鼠标点击main()方法),进入了......\Python\Lib\unittest\main.py 模块,这是整个 unittest 运行的主要调度框架。在该模块最尾处有一行代码 “main = TestProgram”,说明执行测试脚本的“unittest.main()” 就是在实例化 “TestProgram” 这个类。那么给main()方法传入的参数,实际就是创建TestProgram对象时提供的初始化参数。关于具体每个参数的含义和用法,我们后续有时间再详细分析。
通过阅读源码我们可以看到:
- module='__main__',说明运行的模块就是当前测试模块
- testRunner=None,testRunner是测试运行器,默认为None,在当前模块中还有后续代码 “self.testRunner = runner.TextTestRunner”,说明默认使用了TextTestRunner这个文本类型的测试运行器
- testLoader=loader.defaultTestLoader,使用的加载器为 defaultTestLoader,后续代码中有 defaultTestLoader = TestLoader(),指明默认的加载器对象。
python tests 运行方式
在输出结果区域可以发现PyCharm中对应的模块文件(_jb_unittest_runner.py),直接复制这个地址打开该文件。
打开后在文件末尾位置可见如下代码,也是调用的 main() 方法,即实例化TestProgram这个类,但是其传参与python运行方式不同,主要体现在:
- module=None,这个参数会影响后续测试运行的逻辑
- testRunner=unittestpy.TeamcityTestRunner,这里是最主要的区别,其与python运行方式使用了不同的运行器
- python运行方式使用的测试运行器:TextTestRunner
- python test运行方式使用的测试运行器:TeamcityTestRunner,使用了一个第三方的测试报告输出工具。
综上,python运行方式是使用的unitteset默认的测试运行器(TextTestRunner),python tests运行方式是使用的PyCharm中配置的第三方测试运行器(TeamcityTestRunner)。当我们在PyCharm中运行测试脚本的时候,如果自己想配置运行参数,就使用python的运行方式,这样会更加灵活。如果自己不需要指定运行参数就可以使用python tests的运行方式。
3. 命令行运行方式
命令行执行测试脚本是非常重要的测试执行方法,尤其是在进行 CI/CD 实施自动化运行测试的时候更是不可或缺。
命令行运行方式也可以通过两种方式执行脚本:普通方式和探索性测试方式
- 普通方式:明确指定要执行的模块、测试用例、测试方法等
- 探索性测试:通过指定目录范围后,由unittest自行搜索测试并执行
3.1. 查看帮助
先看一下unittset 命令行运行方式的自带帮助,运行命令:python -m unittest -h
- -m 是告诉python通过unittest来执行测试; -h 是显示帮助信息。
- 从帮助中可见,unittest命令行运行有两种模式
- python.exe -m unittest .......:我们暂且叫它普通运行方式
- python.exe -m unittest discover ....: 这里多了一个关键字 discover,所以这种运行方式称之为探索性测试。
- 这两种测试有公共参数:[-h] [-v] [-q] [--locals] [-f] [-c] [-b] [-k TESTNAMEPATTERNS]
- 它们还有各自特有的参数:
- python.exe -m unittest ....... [tests ...]:主要是用于直接指定要运行的测试模块、测试用例或测试方法。
- python.exe -m unittest discover ....[-s START] [-p PATTERN] [-t TOP]:主要是用于指定搜索目录后,让unittest自动遍历并执行目录中匹配到的测试。
命令行方式的入口:
关于命令行方式的具体用法后续文章再行介绍。