unittest的四大特点

  1. TestCase:测试用例。所有的用例都是直接继承与UnitTest.TestCase类。

  2. TestFixture:测试固件。setUp和tearDown分别作为前置条件和后置条件。主要用于初始化测试用例和管理用例执行结束后的资源释放。

  3. TestSuite和TestRunner:测试套件和测试运行器。

  4. 断言:在unittest中封装好了成熟的断言,可以直接调用。

unittest基本用法

  • 语法规则

    • unittest中,测试用例的名称,必须以“test_”开头。否则即便定义了测试用例也不会被执行。

    • 用例的执行顺序与定义的先后顺序无关,而是根据用例名称来排序执行的。如test_1会比test_2先执行。

  • 所有测试用例的运行

    • 在main代码块内调用unittest.main()

    

 1 import unittest
2
3
4 class TestDemo(unittest.TestCase):
5
6 def setUp(self) -> None:
7 print('执行每个测试用例前的准备工作')
8
9 def tearDown(self) -> None:
10 print('执行完每个测试用例后的收尾工作')
11
12 def test_1(self):
13 print('测试用例1')
14
15 def test_2(self):
16 print('测试用例2')
17
18 def a(self):
19 print('不按命名规则的测试用例')
20
21
22 if __name__ == '__main__':
23 unittest.main()
24
25
26
27 执行结果:
28
29 执行每个测试用例前的准备工作
30 测试用例1
31 执行完每个测试用例后的收尾工作
32 执行每个测试用例前的准备工作
33 测试用例2
34 执行完每个测试用例后的收尾工作
35 ..
36 ----------------------------------------------------------------------
37 Ran 2 tests in 0.000s
38
39 OK

数据驱动测试

  • ddt模块的使用

    • ddt模块的data装饰器可以给测试用例传入数据

    • 需要使用ddt模块给测试用例传入数据,需要先使用ddt装饰器给对应的测试用例的类进行装饰

 1 import unittest
2 from ddt import ddt, data
3
4
5 @ddt
6 class TestDemo(unittest.TestCase):
7
8 def setUp(self) -> None:
9 print('执行每个测试用例前的准备工作')
10
11 def tearDown(self) -> None:
12 print('执行完每个测试用例后的收尾工作')
13
14 @data('我是传入的数据')
15 def test_1(self, data):
16 print(data)
17
18
19 if __name__ == '__main__':
20 unittest.main()
  • 注意点

    • 如果data装饰器传入多条数据,表示该用例会被执行多少次,每次使用不同的数据来测试

     1 import unittest
    2 from ddt import ddt, data
    3
    4
    5 @ddt
    6 class TestDemo(unittest.TestCase):
    7
    8 def setUp(self) -> None:
    9 print('执行每个测试用例前的准备工作')
    10
    11 def tearDown(self) -> None:
    12 print('执行完每个测试用例后的收尾工作')
    13
    14 @data('我是传入的数据1', '我是传入的数据2')
    15 def test_1(self, data1):
    16 print(data1)
    17
    18
    19 if __name__ == '__main__':
    20 unittest.main()
    21
    22 执行结果:
    23 执行每个测试用例前的准备工作
    24 我是传入的数据1
    25 执行完每个测试用例后的收尾工作
    26 执行每个测试用例前的准备工作
    27 我是传入的数据2
    28 执行完每个测试用例后的收尾工作
    29 ..
    30 ----------------------------------------------------------------------
    31 Ran 2 tests in 0.000s
    32
    33 OK
    • 如果测试用例的函数需要接收多个参数,需要将每一组数据放在列表中传入

      • 需要特别注意的是,即便使用列表将多个参数对应的数据传入测试用例。整个列表还是会被当做是一个整体默认传给第一个参数,此时使用*[]语法是错误的,这样列表中的元素会被拆分成一个个独立的元素,作为每一次测试使用的测试数据。

      • 此时需要使用ddt模块中的例外一个装饰器—unpack。它会负责将列表内的元素对应的传给参数。

     1 import unittest
    2 from ddt import ddt, data, unpack
    3
    4
    5 @ddt
    6 class TestDemo(unittest.TestCase):
    7
    8 def setUp(self) -> None:
    9 print('执行每个测试用例前的准备工作')
    10
    11 def tearDown(self) -> None:
    12 print('执行完每个测试用例后的收尾工作')
    13
    14 @data(['我是传入的数据1', '我是传入的数据2'], ['第二组用例的数据1', '第二组用例的数据2'])
    15 @unpack
    16 def test_1(self, data1, data2):
    17 print(data1)
    18 print(data2)
    19
    20
    21 if __name__ == '__main__':
    22 unittest.main()
    23
    24
    25 执行结果:
    26 执行每个测试用例前的准备工作
    27 我是传入的数据1
    28 我是传入的数据2
    29 执行完每个测试用例后的收尾工作
    30 执行每个测试用例前的准备工作
    31 第二组用例的数据1
    32 第二组用例的数据2
    33 执行完每个测试用例后的收尾工作
    34 ..
    35 ----------------------------------------------------------------------
    36 Ran 2 tests in 0.000s
    37
    38 OK

断言

  • 断言就是一个测试用例预期结果与实际结果的对比(实际结果是否与预期符合)

  • unittest的常用的一些断言:

    # 判断 a == b,msg表示错误提示信息
    self.assertEqual(a, b, msg='a不等于b') # 判断 a != b
    self.assertNotEqual(a, b) # 判断 bool(x) is True
    self.assertTrue(x) # 判断 bool(x) is False
    self.assertFalse(x) # 判断 a is b
    self.assertIs(a, b) # 判断 a is not b
    self.assertIsNot(a, b) # 判断 x is None
    self.assertIsNone(x) # 判断 x is not None
    self.assertIsNotNone(x) # 判断 a in b
    self.assertIn(a, b) # 判断 a not in b
    self.assertNotIn(a, b) # 判断 isinstance(a, b)
    self.assertIsInstance(a, b) # 判断 not isinstance(a, b)
    self.assertNotIsInstance(a, b)
     

Skip操作

  • 将某些暂时不需要执行的测试用例跳过

    1 @unittest.skip('无条件跳过')
    2 def test_1(self, data1, data2):
    3 print(data1)
    4 print(data2)
    5 self.assertEqual(1, 2, msg='1不等于2')
  • 给指定测试用例加上skip装饰器,即可无条件跳过该测试用例

  • 有条件限制的跳过测试用例:

    • skipUnless装饰器

      • 当条件为False时会跳过当前测试用例

      1 @unittest.skipUnless(1 > 2, '条件为假跳过')
      2 def test_2(self):
      3 print(111)
    • skipIf装饰器

      • 当条件为True时会跳过当前测试用例

      1 @unittest.skipIf(2 > 1, '条件为真时跳过')
      2 def test_3(self):
      3 print(222)
  • 测试用例断言为假时(与预期结果不符)标记该测试用例

    • expectedFailure装饰器

      1 @unittest.expectedFailure
      2 def test_4(self):
      3 self.assertEqual(1, 2, '1不等于2')
      4
      5 该测试用例被标记为:
      6 expected failures=1
      7 注意:
      8 和skip不同,skip是根据条件或者无条件跳过不执行测试用例
      9 expectedFailure是执行完测试用例后,将与预期不符的测试用例标记出来

    使用了该装饰器的测试用例,断言结果必须是错误的。不允许成功

    否则会出现以下错误:

    Test should not succeed since it's marked with @unittest.expectedFailure

测试套件和测试运行器

  • 测试套件

    • 将想要执行的测试用例加入到一个测试套件内,然后通过运行器执行测试套件内的测试用例,即可实现执行部分测试用例。

    • 测试套件不能与测试用例在一个文件内,否则即使使用测试运行器运行测试套件,还是会执行所有用例。

       1 import unittest
      2 from test import TestDemo
      3
      4 # 实例化测试套件
      5 suite = unittest.TestSuite()
      6 # 添加测试用例
      7 suite.addTest(TestDemo('test_1'))
      8 suite.addTest(TestDemo('test_3'))
      9
      10 # 实例化测试运行器
      11 runner = unittest.TextTestRunner()
      12 runner.run(suite)
  • 往测试套件内添加测试用例的多种方式:

    • 上述例子中,直接通过指定测试用例类中的测试用例方法名,将测试用例添加至套件内。

      • 上述例子添加用例的方式可优化:

        1 cases = [TestDemo('test_1'), TestDemo('test_3')]
        2 suite.addTests(cases)
    • 通过正则匹配查询,将指定路径下所有匹配成功的测试用例全都加入测试套件内

      1 discover = unittest.defaultTestLoader.discover(start_dir='./', pattern='test*.py')
      2 ​
      3 # 实例化测试运行器
      4 runner = unittest.TextTestRunner()
      5 runner.run(discover)
      6 ​
      7 # 此时运行器执行的是从‘./’路径下,也就是当前路径下所有与‘test*.py’相匹配的测试用例文件内的测试用例的集合。
    • 直接将指定测试用例类对象中的所有测试用例添加至套件内

      1 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestDemo))
    • 将上述方式改为通过类名称方式将所有用例添加至套件内

      1 suite.addTests(unittest.TestLoader().loadTestsFromName('test.TestDemo'))
      2 ​
      3 # 注意类名称必须通过指定包/模块加‘.’的形式
  • 测试运行器

    • 主要用于执行测试套件

HTMLTestRunner

  • 用于生成测试报告

    • 报告内只记录通过的用例和失败的用例,没有跳过的用例。

  • HTMLTestRunner配置

    • 下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html

    • 由于下载的HTMLTestRunner.py文件是基于Python2的,若适用于Python3则进行如下修改:

      • 94行, import StringIO

      • 539行,self.outputBuffer = StringIO.StringIO()

      • 631行,print >>sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)

      • 642行,if not rmap.has_key(cls):

      • 766行,uo = o.decode('latin-1')

      • 772行,ue = e.decode('latin-1')

    • 将下载的文件保存到:PythonXX\Lib目录下。

  • 基本用法     

 1 import unittest
2 from HTMLTestRunner import HTMLTestRunner
3 from test import TestDemo
4 ​
5 # 实例化测试套件
6 suite = unittest.TestSuite()
7 ​
8 # 生成测试报告
9 report_name = '测试报告名称.html'
10 report_title = '测试报告标题'
11 report_desc = '测试报告描述'
12 report_path = './'
13 report_file = report_path + report_name
14 ​
15 with open(report_file, 'wb') as report:
16 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestDemo))
17 runner = HTMLTestRunner(stream=report, title=report_title, description=report_desc)
18 runner.run(suite)

unittest学习的更多相关文章

  1. Python unittest 学习

    import unittest class UTest(unittest.TestCase): def test_upper(self): self.assertEqual('foo'.upper() ...

  2. unittest学习5-断言

    unittest提供了以下断言方式: 方法 检查 新进 assertEqual(a, b) a == b   assertNotEqual(a, b) a != b   assertTrue(x) b ...

  3. unittest学习4-跳过用例执行

    unittest支持跳过单个测试方法,甚至整个测试用例,还支持将测试用例标记为“测试失败” 基本跳过如下: import unittestimport requests,sys class MyTes ...

  4. unittest学习3-测试组件setup、teardown

    unittest的测试用例执行时都可以设置setup.teardown,用来初始化测试开始和测试结束关闭,例如: import unittest class MyTestCase(unittest.T ...

  5. unittest学习笔记

    File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\errorhandler.py&quo ...

  6. ios UnitTest 学习笔记

    一.运行第一个单元测试: 1.在Xcode 5中新建一个工程默认自带一个单元测试的文件夹,IDE自动生成了一个实现XCTestCase的.m文件,里面有一个失败测试(早期版本中实现的是SenTestC ...

  7. ios UnitTest 学习笔记1

    一.运行第一个单元测试: 1.在Xcode 5中新建一个工程默认自带一个单元测试的文件夹,IDE自动生成了一个实现XCTestCase的.m文件,里面有一个失败测试(早期版本中实现的是SenTestC ...

  8. 12.unittest的学习

    unittest学习后的总结,记录各个主要内容

  9. appium学习记录2

    unittest 学习 每执行一次 testcase 就会调用一次 setUP 与teardown 类方法只会执行一次 开始 与结束时候执行 类似反射方法 __init__ 与 __del__ set ...

随机推荐

  1. node进阶| 解决表单enctype="multipart/form-data" 时获取不到Input值的问题

    今天在学习node踩到一个坑:form设置enctype="multipart/form-data"上传文件时,无法获取到表单其他input的值. 因为之前上传文件用的是 form ...

  2. php中用面向对象的思想编写mysql数据库操作类

    最近刚入门完mysql,正好学了一阵子php就想着如何把mysql的表信息用php打印页面上.现在就把代码贴出来,以便小伙伴们参考. 先是建立mysql连接: /*建立连接*/ class datab ...

  3. Docker多主机管理(八)

    docker多主机管理 前面我们的实验环境中只有一个 docker host,所有的容器都是运行在这一个 host 上的.但在真正的环境中会有多个 host,容器在这些 host 中启动.运行.停止和 ...

  4. Netty之ChannelOption的各种参数之EpollChannelOption.SO_REUSEPORT

    socket选项 SO_REUSEPORT 转 miffa 发布于 2015/03/24 17:21 字数 3383 阅读 6076 收藏 6 点赞 1 评论 0 开发十年,就只剩下这套Java开发体 ...

  5. hystrix(1) 概述

    首先我们来讲一下hystrix解决什么问题.在大型分布式系统中经常会存在下面的几类问题: 1.大型分布式系统中,服务之间相互依赖,如果依赖的服务发生异常,那么当前服务也会出现异常,这样将会导致联级的服 ...

  6. Spring系列 之数据源的配置 数据库 数据源 连接池的区别

    Spring系列之数据源的配置 数据源,连接池,数据库三者的区别 连接池:这个应该都学习过,比如c3p0,druid等等,连接池的作用是为了提高程序的效率,因为频繁的去创建,关闭数据库连接,会对性能有 ...

  7. 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)请自取

    最近在读,附上网盘链接 复制这段内容后打开百度网盘手机App,操作更方便哦 链接:https://pan.baidu.com/s/1U6yFeZxz9uD6sSiu-Br06g 提取码:3Wt4

  8. MyBatis学习(四)代码生成器MyBatis-Generator

    一.简介 前面写过一篇文章介绍了如何使用Mybatis,那么如果我门数据库中有许许多多的表的时候,每张表都手动去写对应的mapper的映射关系,会非常麻烦,那么我们可以使用代码生成器MyBatis-G ...

  9. 阿里内部推出Spring响应式微服务Boot2Cloud文档

    今天要给大家推荐的是Spring响应式微服务SpringBoot2+Spring5+SpringCloud实战的内容,将从目录.主要内容和面向的读者三部分给大家介绍,希望大家能够喜欢!!!(本文整理自 ...

  10. CentOS7的下载及虚拟机的创建

    一.CentOS的安装 1,首先打开开源镜像网站:www.mirrors.163.com(网易开源镜像网站),www.mirrors.aliyun.com(阿里云开源镜像网站) 以网易为例 2.点击进 ...