简介
大多数的初学者在使用 unittest 框架时候, 不清楚用例的执行顺序到底是怎样的. 对测试类里面的类和方法分不清楚, 不知道什么时候执行, 什么时候不执行. 虽然或许通过代码实现了, 也是稀里糊涂的一知半解, 这样还好, 好歹自己鼓
捣出了, 但是时间和效率并不是很高, 下次遇到还是老样子. 那么本篇通过最简单案例来给给为小伙伴详细讲解, 演示一下 unittest 执行顺序.
实例代码
参考代码
- # coding=utf-8
- #1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- #2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-4-23
- @author: 北京 - 宏哥
- Project: 学习和使用 unittest 框架编写测试用例执行顺序
- '''
- #3. 导入 unittest 模块
- import unittest
- #4. 执行顺序和运行测试
- import unittest
- class TestLogin(unittest.TestCase):
- def test_login_blog(self):
- """ 登录博客园
- :return:
- """
- def test_add_essay(self):
- """ 添加随笔
- :return:
- """
- def test_release_essay(self):
- """ 发布随笔
- :return:
- """
- def test_quit_blog(self):
- """ 退出博客园
- :return:
- """ if __name__ =="__main__()":
- unittest.main()
这是一个标准的使用 unittest 进行测试的例子, 写完后心里美滋滋, 嗯, 就按照一贯思路代码会按照这个顺序测就可以了. 结果一运行. 就傻眼了
这时候自己心里犯嘀咕, 这是什么鬼, 怎么回事呢. 执行的顺序乱了. 第一个执行的测试用例并不是登录博客园, 而是添加随笔, 此时用户还没登录博客园, 进行添加随笔的话会直接报错, 导致用例失败.
到这里有些小伙伴可能会说, 为什么要让测试用例之间有所依赖呢?
的确, 如果完全没依赖, 测试用例的执行顺序是不需要关注的. 但是这样对于用例的设计和实现, 要求就高了许多. 而对博客园来说, 一个系统内的操作, 是有很大的关联性的. 以添加随笔为例, 随笔内的每个操作都有一个前提, 你需要
登录博客园才能添加随笔. 所以要实现用例之间的完全解耦, 需要每个用例开始之前, 检测用户的登录状态.
如果可以控制测试用例的执行顺序, 按照功能流程一遍走下来, 节省的代码量是非常可观的, 阅读测试用例也会清晰明了许多.
如何控制 unittest 用例执行的顺序呢?
1, 带大家先看看源码, unittest 是怎么样对用例进行排序的. 在 loader.py 的 loadTestsFromTestCase 方法里边, 调用了 getTestCaseNames 方法来获取测试用例的名称
2, 从源码可以清楚地看到, getTestCaseNames 方法对测试用例的名称进行了排序
3, 一步一步跟进去, 查看其排序方法
4, 根据排序规则, unittest 执行测试用例, 默认是根据 ASCII 码的顺序加载测试用例, 数字与字母的顺序为: 0-9,A-Z,a-z.
5, 做个小 demo, 看看是不是我们所说的那种排序规则
6, 从上边的运行结果, 我们可以看出是: unittest 执行测试用例, 默认是根据 ASCII 码的顺序加载测试用例, 数字与字母的顺序为: 0-9,A-Z,a-z.
7, 基于 unittest 的机制, 如何控制用例执行顺序呢? 查了一些网上的资料, 主要介绍了两种方式:
方式 1, 通过 TestSuite 类的 addTest 方法, 按顺序加载测试用例
参考代码
- # coding=utf-8
- #1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- #2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-4-23
- @author: 北京 - 宏哥
- Project: 学习和使用 unittest 框架编写测试用例执行顺序
- '''
- #3. 导入 unittest 模块
- import unittest
- #4. 执行顺序和运行测试
- import unittest
- class TestLogin(unittest.TestCase):
- def setUp(self):
- pass
- def test_login_blog(self):
- """ 登录博客园
- :return:
- """ print(" 登录博客园 ")
- def test_add_essay(self):
- """ 添加随笔
- :return:
- """ print(" 添加随笔 ")
- def test_release_essay(self):
- """ 发布随笔
- :return:
- """ print(" 发布随笔 ")
- def test_quit_blog(self):
- """ 退出博客园
- :return:
- """ print(" 退出博客园 ")
- def tearDown(self):
- pass
- if __name__ == '__main__':
- # 启动单元测试
- # unittest.main()
- # 获取 TestSuite 的实例对象
- suite = unittest.TestSuite()
- # 将测试用例添加到测试容器中
- suite.addTest(TestLogin('test_login_blog'))
- suite.addTest(TestLogin('test_add_essay'))
- suite.addTest(TestLogin('test_release_essay'))
- suite.addTest(TestLogin('test_quit_blog'))
- # 创建 TextTestRunner 类的实例对象
- runner = unittest.TextTestRunner()
- runner.run(suite)
- #unittest.TextTestRunner(verbosity=3).run(suite)
方式 2, 通过修改函数名的方式
参考代码
- # coding=utf-8
- #1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- #2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-4-23
- @author: 北京 - 宏哥
- Project: 学习和使用 unittest 框架编写测试用例执行顺序
- '''
- #3. 导入 unittest 模块
- import unittest
- #4. 执行顺序和运行测试
- import unittest
- class TestLogin(unittest.TestCase):
- def setUp(self):
- pass
- def test_1_login_blog(self):
- """ 登录博客园
- :return:
- """ print(" 登录博客园 ")
- def test_2_add_essay(self):
- """ 添加随笔
- :return:
- """ print(" 添加随笔 ")
- def test_3_release_essay(self):
- """ 发布随笔
- :return:
- """ print(" 发布随笔 ")
- def test_4_quit_blog(self):
- """ 退出博客园
- :return:
- """ print(" 退出博客园 ")
- def tearDown(self):
- pass
- if __name__ == '__main__':
- # 启动单元测试
- unittest.main()
拓展练习
1, 实例
2, 运行结果
3, 运行结果分析
1, 从运行结果可以看出执行顺序:
start!- 执行测试用例 01-end!
start!- 执行测试用例 02-end!
start!- 执行测试用例 03-end!
2, 从执行结果可以看出几点
-- 先执行的前置 setUp, 然后执行的用例(test*), 最后执行的后置 tearDown
-- 测试用例 (test*) 的执行顺序是根据 01-02-03 执行的, 也就是说根据用例名称来顺序执行的
--addtest(self)这个方法没执行, 说明只执行 test 开头的用例
参考代码
- # coding=utf-8
- #1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- #2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-4-23
- @author: 北京 - 宏哥
- Project: 学习和使用 unittest 框架编写测试用例思路
- '''
- #3. 导入 unittest 模块
- import unittest
- #4. 执行顺序和运行测试
- import time
- class Test(unittest.TestCase):
- def setUp(self):
- print ("start!")
- def tearDown(self):
- time.sleep(1)
- print ("end!")
- def test01(self):
- print ("执行测试用例 01")
- def test03(self):
- print ("执行测试用例 03")
- def test02(self):
- print ("执行测试用例 02")
- def addtest(self):
- print ("add 方法")
- if __name__ == "__main__":
- unittest.main()
小结
1, 这个执行顺序, 看似简单, 实则不简单, 只有掌握最简单的才可以应付最复杂的.
2,setUp()和 tearDown()方法有什么用呢? 设想你的测试需要启动一个数据库, 这时, 就可以在 setUp()方法中连接数据库, 在 tearDown()方法中关闭数据库, 这样, 不必在每个测试方法中重复相同的代码.
来源: https://www.cnblogs.com/du-hong/p/10755530.html