简介
前边的随笔主要介绍的 requests 模块的有关知识个内容, 接下来看一下 python 的单元测试框架 unittest. 熟悉 或者了解 java 的小伙伴应该都清楚常见的单元测试框架 Junit 和 TestNG, 这个招聘的需求上也是经常见到的. python 里面也有单元
测试框架 - unittest, 相当于是一个 python 版的 junit.python 里面的单元测试框架除了 unittest, 还有一个 pytest 框架, 这个实际上用的比较少, 后面有空再继续介绍和分享. unittest 单元测试框架不仅可以适用于单元测试, 还可以适用 web 自动化测
试用例的开发与执行, 该测试框架可组织执行测试用例, 并且提供了丰富的断言方法, 判断测试用例是否通过, 最终生成测试结果.
学习和了解 unittest
1, 查看其中文官网: https://docs.python.org/zh-cn/3/library/unittest.html 英文官网: https://docs.python.org/3/library/unittest.html
http://www.python-requests.org/en/master/
2, 先导入 unittest 用 help 函数查看源码解析查看描述:
Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's Smalltalk testing framework.
翻译: python 的单元测试框架, 是基于 java 的 junit 测试框架
简单的用法
1, 从官网源码或者 print 的 help 里查找 unittest 用法
2, 我们将上图的这段代码 copy 出来, 单独运行, 看看测试和运行结果, 抱着怀疑的心态自己体验一下, 因为所有人都不可能是不犯错的, 官网和源码也不例外.
代码分析和说明:
1, 第一行是导入 unittest 这个模块
2,class 这一行是定义一个测试的类, 并继承 unittest.TestCase 这个类
定义测试类, 父类为 unittest.TestCase. #可继承 unittest.TestCase 的方法, 如 setUp 和 tearDown 方法, 不过此方法可以在子类重写, 覆盖父类方法. #可继承 unittest.TestCase 的各种断言方法.
3, 接下来是定义了两个测试 case 名称: testAdd 和 testMultiply4, 注释里面有句话很重要:## test method names begin 'test*'-- 翻译: 测试用例的名称要以 test 开头
4, 然后是断言 assert, 这里的断言方法是 assertEqual - 判断两个是否相等, 这个断言可以是一个也可以是多个
5,if 下面的这个 unittest.main()是运行主函数, 运行后会看到测试结果(跑了两个用例耗时 0.000 秒, 两个用例都通过)
模仿和实践
1, 既然都了解的差不多了, 还等什么呢, 开始模仿和敲起了来吧.
2, 上面的两个案例是加法和乘法, 我们可以写个 case 试下减法和除法.
3, 有很多小伙伴不知道断言怎么写, 断言其实就是拿实际结果和期望结果去对比, 对比的方法很多, 这里只是举的最简单的一个判断相等的方法
参考代码
- # coding=utf-8
- #1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- #2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-4-23
- @author: 北京 - 宏哥
- Project: 学习和使用 unittest 框架编写测试用例思路
- '''
- #3. 导入 unittest 模块
- import unittest
- #4.copy 和运行测试
- class IntegerArithmeticTestCase(unittest.TestCase):
- def testSubtract(self): # test method names begin with 'test'
- result = 6-5 #实际结果
- hope = 1 #期望结果
- self.assertEqual(result, hope)
- def testDivide(self):
- result = 7 / 2 # 实际结果
- hope = 3.5 # 期望结果
- self.assertEqual(result, hope)
- if __name__ == '__main__':
- unittest.main()
前置条件和后置条件
1,setUp: 在写测试用例的时候, 每次操作其实都是基于打开浏览器输入对应网址这些操作, 这个就是执行用例的前置条件.
2,tearDown: 执行完用例后, 为了不影响下一次用例的执行, 一般有个数据还原的过程, 这就是执行用例的后置条件.
3, 很多小伙伴执行完用例, 都不去做数据还原, 以致于下一个用例执行失败, 这就是典型的自己给自己挖坑埋自己, 自己坑自己, 习惯不好.
4, 前置和后置都是非必要的条件, 如果没有也可以写 pass
参考代码
- # coding=utf-8
- #1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- #2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-4-23
- @author: 北京 - 宏哥
- Project: 学习和使用 unittest 框架编写测试用例思路
- '''
- #3. 导入 unittest 模块
- import unittest
- #4. 前置, 后置 和运行测试
- class Test(unittest.TestCase):
- def setUp(self):
- pass #如果没有可以不写或者 pass 代替
- def tearDown(self):
- pass
- def testSubtract(self): # test method names begin with 'test'
- result = 6-5 #实际结果
- hope = 1 #期望结果
- self.assertEqual(result, hope)
- def testDivide(self):
- result = 7 / 2 # 实际结果
- hope = 3.5 # 期望结果
- self.assertEqual(result, hope)
- if __name__ == '__main__':
- unittest.main()
小结
一, unittest 模块的各个属性说明
先来聊一聊 unittest 模块的各个属性, 所谓知己知彼方能百战百胜, 了解 unittest 的各个属性, 对于后续编写用例有很大的帮助.
1.unittest 的属性如下:
['BaseTestSuite', 'FunctionTestCase', 'SkipTest', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult', 'TestSuite', 'TextTestResult', 'TextTestRunner', '_TextTestResult', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__unittest', 'case', 'defaultTestLoader', 'expectedFailure', 'findTestCases', 'getTestCaseNames', 'installHandler', 'loader', 'main', 'makeSuite', 'registerResult', 'removeHandler', 'removeResult', 'result', 'runner', 'signals', 'skip', 'skipIf', 'skipUnless', 'suite', 'util']
说明:
unittest.TestCase:TestCase 类, 所有测试用例类继承的基本类.
class BaiduTest(unittest.TestCase):
unittest.main(): 使用她可以方便的将一个单元测试模块变为可直接运行的测试脚本, main()方法使用 TestLoader 类来搜索所有包含在该模块中以 "test" 命名开头的测试方法, 并自动执行他们. 执行方法的默认顺序是: 根据 ASCII 码的顺序加载测试用例, 数字与字母的顺序为: 0-9,A-Z,a-z. 所以以 A 开头的测试用例方法会优先执行, 以 a 开头会后执行.
unittest.TestSuite():unittest 框架的 TestSuite()类是用来创建测试套件的.
unittest.TextTextRunner():unittest 框架的 TextTextRunner()类, 通过该类下面的 run()方法来运行 suite 所组装的测试用例, 入参为 suite 测试套件.
unittest.defaultTestLoader(): defaultTestLoader()类, 通过该类下面的 discover()方法可自动更具测试目录 start_dir 匹配查找测试用例文件 (test*.py), 并将查找到的测试用例组装到测试套件, 因此可以直接通过 run() 方法执行 discover. 用法如下:
discover=unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
unittest.skip(): 装饰器, 当运行用例时, 有些用例可能不想执行等, 可用装饰器暂时屏蔽该条测试用例. 一种常见的用法就是比如说想调试某一个测试用例, 想先屏蔽其他用例就可以用装饰器屏蔽.
@unittest.skip(reason): skip(reason)装饰器: 无条件跳过装饰的测试, 并说明跳过测试的原因.
@unittest.skipIf(reason): skipIf(condition,reason)装饰器: 条件为真时, 跳过装饰的测试, 并说明跳过测试的原因.
@unittest.skipUnless(reason): skipUnless(condition,reason)装饰器: 条件为假时, 跳过装饰的测试, 并说明跳过测试的原因.
@unittest.expectedFailure(): expectedFailure()测试标记为失败.
2.TestCase 类的属性如下:
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_addSkip', '_baseAssertEqual', '_classSetupFailed', '_deprecate', '_diffThreshold', '_formatMessage', '_getAssertEqualityFunc', '_truncateMessage', 'addCleanup', 'addTypeEqualityFunc', 'assertAlmostEqual', 'assertAlmostEquals', 'assertDictContainsSubset', 'assertDictEqual', 'assertEqual', 'assertEquals', 'assertFalse', 'assertGreater', 'assertGreaterEqual', 'assertIn', 'assertIs', 'assertIsInstance', 'assertIsNone', 'assertIsNot', 'assertIsNotNone', 'assertItemsEqual', 'assertLess', 'assertLessEqual', 'assertListEqual', 'assertMultiLineEqual', 'assertNotAlmostEqual', 'assertNotAlmostEquals', 'assertNotEqual', 'assertNotEquals', 'assertNotIn', 'assertNotIsInstance', 'assertNotRegexpMatches', 'assertRaises', 'assertRaisesRegexp', 'assertRegexpMatches', 'assertSequenceEqual', 'assertSetEqual', 'assertTrue', 'assertTupleEqual', 'assert_', 'countTestCases', 'debug', 'defaultTestResult', 'doCleanups', 'fail', 'failIf', 'failIfAlmostEqual', 'failIfEqual', 'failUnless', 'failUnlessAlmostEqual', 'failUnlessEqual', 'failUnlessRaises', 'failureException', 'id', 'longMessage', 'maxDiff', 'run', 'setUp', 'setUpClass', 'shortDescription', 'skipTest', 'tearDown', 'tearDownClass']
说明:
setUp():setUp()方法用于测试用例执行前的初始化工作. 如测试用例中需要访问数据库, 可以在 setUp 中建立数据库连接并进行初始化. 如测试用例需要登录 Web, 可以先实例化浏览器.
tearDown():tearDown()方法用于测试用例执行之后的善后工作. 如关闭数据库连接. 关闭浏览器.
assert*(): 一些断言方法: 在执行测试用例的过程中, 最终用例是否执行通过, 是通过判断测试得到的实际结果和预期结果是否相等决定的.
assertEqual(a,b,[msg='测试失败时打印的信息']): 断言 a 和 b 是否相等, 相等则测试用例通过.
assertNotEqual(a,b,[msg='测试失败时打印的信息']): 断言 a 和 b 是否相等, 不相等则测试用例通过.
assertTrue(x,[msg='测试失败时打印的信息']): 断言 x 是否 True, 是 True 则测试用例通过.
assertFalse(x,[msg='测试失败时打印的信息']): 断言 x 是否 False, 是 False 则测试用例通过.
assertIs(a,b,[msg='测试失败时打印的信息']): 断言 a 是否是 b, 是则测试用例通过.
assertNotIs(a,b,[msg='测试失败时打印的信息']): 断言 a 是否是 b, 不是则测试用例通过.
assertIsNone(x,[msg='测试失败时打印的信息']): 断言 x 是否 None, 是 None 则测试用例通过.
assertIsNotNone(x,[msg='测试失败时打印的信息']): 断言 x 是否 None, 不是 None 则测试用例通过.
assertIn(a,b,[msg='测试失败时打印的信息']): 断言 a 是否在 b 中, 在 b 中则测试用例通过.
assertNotIn(a,b,[msg='测试失败时打印的信息']): 断言 a 是否在 b 中, 不在 b 中则测试用例通过.
assertIsInstance(a,b,[msg='测试失败时打印的信息']): 断言 a 是是 b 的一个实例, 是则测试用例通过.
assertNotIsInstance(a,b,[msg='测试失败时打印的信息']): 断言 a 是是 b 的一个实例, 不是则测试用例通过.
3.TestSuite 类的属性如下:(组织用例时需要用到)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_addClassOrModuleLevelException', '_get_previous_module', '_handleClassSetUp', '_handleModuleFixture', '_handleModuleTearDown', '_tearDownPreviousClass', '_tests', 'addTest', 'addTests', 'countTestCases', 'debug', 'run']
说明:
addTest(): addTest()方法是将测试用例添加到测试套件中, 如下方, 是将 test_baidu 模块下的 BaiduTest 类下的 test_baidu 测试用例添加到测试套件.
- suite = unittest.TestSuite()
- suite.addTest(test_baidu.BaiduTest('test_baidu'))
4.TextTextRunner 的属性如下:(组织用例时需要用到)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_makeResult', 'buffer', 'descriptions', 'failfast', 'resultclass', 'run', 'stream', 'verbosity']
说明:
run(): run()方法是运行测试套件的测试用例, 入参为 suite 测试套件.
- runner = unittest.TextTestRunner()
- runner.run(suite)
来源: https://www.cnblogs.com/du-hong/p/10754903.html