zoukankan      html  css  js  c++  java
  • unittest单元测试框架

    一、简介

      unittest是Python单元测试框架。unittest它支持自动化测试,在测试中使用setup(初始化)和shutdown(关闭销毁)操作,组织测试 用例为套件(批量运行),以及把测试和报告独立开来。

      测试脚手架(test fixture):为了开展一项或多项测试所需要进行的准备工作,以及所有相关的清理操作。

      测试用例(test case):一个测试用例是一个独立的测试单元。检查输入特定的数据时的响应。 unittest 提供一个基类: TestCase ,用于新建测试用例。

      测试套件(test suite):一系列的测试用例。用于归档需要一起执行的测试用例。

      测试运行器(test runner):一个用于执行和输出测试结果的组件

       综上,整个流程就是首先要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。

      官方文档:https://docs.python.org/zh-cn/3.7/library/unittest.html

    二、unittest类的属性

      unittest.TestCase: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。

      unittest.skip():装饰器,当运行用例时,有些用例可能不想执行等,可用装饰器暂时屏蔽该条测试用例。一种常见的用法就是比如说想调试某一个测试用例,想先屏蔽其他用例就可以用装饰器屏蔽。

    三、跳过测试与预计的失败

    @unittest.skip(reason)

      跳过被此装饰器装饰的测试。 reason 为测试被跳过的原因。

    @unittest.skipIf(condition, reason)

      当 condition 为真时,跳过被装饰的测试。

    @unittest.skipUnless(condition, reason)

      跳过被装饰的测试,除非 condition 为真。

    @unittest.expectedFailure

      把测试标记为预计失败。如果测试不通过,会被认为测试成功;如果测试通过了,则被认为是测试失败。

    四、常用的断言方法

     五、unittest实例

      我们就来上手,举个简单的例子来看看unittest里面的属性、函数与用例如何运行的。

     1 # 导入unittest模块
     2 import unittest
     3 
     4 # unittest.TestCase:TestCase类,所有测试用例类继承的基本类。
     5 class TestStringCase(unittest.TestCase):
     6     # TestCase基类方法,所有case执行之前自动执行
     7     @classmethod
     8     def setUpClass(self):
     9         print("这里是所有测试用例前的准备工作")
    10 
    11     # TestCase基类方法,所有case执行之后自动执行
    12     @classmethod
    13     def tearDownClass(self):
    14         print("这里是所有测试用例后的清理工作")
    15 
    16     # TestCase基类方法,每次执行case前自动执行
    17     def setUp(self):
    18         print("这里是一个测试用例前的准备工作")
    19 
    20     # TestCase基类方法,每次执行case后自动执行
    21     def tearDown(self):
    22         print("这里是一个测试用例后的清理工作")
    23 
    24     @unittest.skip("我想临时跳过这个测试用例.")
    25     # 测试用例1
    26     def test_case1(self):
    27         print('执行测试用例1')
    28         s = 'hello'
    29         self.assertEqual(s, "hello")
    30 
    31     # 测试用例2
    32     def test_case2(self):
    33         print('执行测试用例2')
    34         s = '测试'
    35         self.assertEqual(s, '测试')
    36 
    37     # 测试用例3
    38     def test_case3(self):
    39         print('执行测试用例3')
    40         s= 'ceshi'
    41         self.assertEqual(s, 'ceshi')
    42 
    43 #测试用例集合方法
    44 def suite():
    45     #实例化测试套件
    46     suite = unittest.TestSuite()
    47     #将用例加到用例集及运行顺序
    48     suite.addTest(TestStringCase('test_case3'))
    49     suite.addTest(TestStringCase('test_case2'))
    50     return suite
    51 
    52 #path= './' 定义测试集所在文件夹
    53 #pattern='unittest_Two.py' 规定测试集文件
    54 #discover方法找到path 目录下所有文件到的测试用例组装到测试套件
    55 def discover():
    56     path = './'
    57     rundiscover = unittest.defaultTestLoader.discover(path,pattern='unittest_Two.py')
    58     return rundiscover
    59     
    60 if __name__ == "__main__":
    61     #运行用例方法一:
    62     unittest.main()
    63     
    64     #运行用例方法二:
    65     #实例化TextTestRunner类
    66     #runner = unittest.TextTestRunner()
    67     #runner.run(suite())
    68 
    69     #运行用例方法三:
    70     #实例化TextTestRunner类
    71     #runner = unittest.TextTestRunner()
    72     #run()方法执行discover
    73     #runner.run(discover())

      unittest实例方法一运行的结果:

     

       打印中前面的实心点,表示用例断言成功并通过,s则表示跳转执行用例。

      unittest实例方法二运行的结果:

      unittest实例方法三运行的结果同方法一结果所示。

    六、生成测试报告

      知道了用例如何编写,那么我们来看看unittest的测试报告,这里我介绍的是经大神改进后的HTMLTestRunnerCN,由于HTMLTestRunner样式简陋,我们不做介绍。

      Github下载HTMLTestRunnerCN:https://github.com/findyou/HTMLTestRunnerCN

      我用的是python3.x,注意下载后用3.x下面的HTMLTestRunnerCN。Git上的文件名叫HTMLTestReportCN.py。

      下载文件然后存放到你的Python安装目录中:Libsite-packages目录下即可。代码中如何使用呢?在上面用例的基础上,修改为下面的代码。如下所示。

     1 if __name__ == "__main__":
     2     filePath ='D:\Report.html'       #确定生成报告的路径
     3     fp = open(filePath,'wb')
     4     runner = HTMLTestReportCN.HTMLTestRunner(
     5         stream=fp,
     6         title='自动化测试报告', 
     7         #description='测试用例结果描述',    #不传默认为空
     8         tester='wuwei'     #测试人员名字
     9         )
    10     runner.run(discover())

      正常运行py用例文件,python XX.py,系统会在D盘下自动创建一个文件名为Report.html的html测试报告。上述实例运行的测试报告结果如下图所示。

      备注:刚开始应用测试报告时,不知道有没有小伙伴发现。用例列表中的失败与通过的按钮展示都是红色,但是我想成功为绿色,失败为红色。我这里稍微修改了一下HTMLTestRunnerCN.py的源码。 
    原代码:

    1 tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL

    修改为:

    1 tmpl = (n == 0 and self.REPORT_TEST_NO_OUTPUT_TMPL or self.REPORT_TEST_WITH_OUTPUT_TMPL)

      找至成功按钮展示列表逻辑。
    修改为:

     1 # 通过 的样式,加标签效果
     2     REPORT_TEST_NO_OUTPUT_TMPL = r"""
     3 <tr id='%(tid)s' class='%(Class)s'>
     4     <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
     5     <td colspan='5' align='center'>
     6     <button id='btn_%(tid)s' type="button"  class="btn btn-success btn-xs" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
     7     <div id='div_%(tid)s' class="collapse in">
     8     <pre>
     9     %(script)s
    10     </pre>
    11     </div>
    12     </td>
    13 </tr>
    14 """ # variables: (tid, Class, style, desc, status)    

      大家可以根据自己的需求来修改HTMLTestRunnerCN.py的源码,来实现自己的需要的测试报告样式与需求。

    七、requests接口测试应用unittest实例

      上面的Demo实例不过瘾,我们来看看python requests接口测试如何来应用unittest实例的。下面我列举的是一个慕课网的搜索接口,普通的Get请求的实例,涉及应用到接口调用,上面说明两个简单的用例,断言及上述HTMLTestReportCN生成的测试报告。

     1 # 导入os、unittest、requests、HTMLTestReportCN模块
     2 import requests
     3 import unittest
     4 import os
     5 import HTMLTestReportCN
     6 
     7 # 发送Get请求方法
     8 def sendGet(url, paramData):
     9     result = requests.get(url=url, params=paramData).json()
    10     return result
    11 
    12 # unittest.TestCase:TestCase类,所有测试用例类继承的基本类。
    13 class TestRequestOne(unittest.TestCase):
    14     # 每次case执行前,调用接口地址
    15     def setUp(self):
    16         print("这里是一个测试用例前的准备工作")
    17         #接口地址
    18         self.url = 'https://www.imooc.com/search/history'
    19 
    20     def tearDown(self):
    21         print("这里是一个测试用例后的清理工作")
    22 
    23     # 测试用例1
    24     def test_api1(self):
    25         resultData = sendGet(url=self.url, paramData={'words': 'test'})
    26         # 用例断言
    27         self.assertEqual(resultData['data'][0]['word'], "testng")
    28 
    29     # 测试用例2
    30     def test_api2(self):
    31         resultData = sendGet(url=self.url, paramData={'words': '测试'})
    32         # 用例断言
    33         self.assertEqual(resultData['data'][0]['word'], "测试你好")
    34 
    35 #测试用例集合方法
    36 def suite():
    37     #实例化测试套件
    38     suite = unittest.TestSuite()
    39     #将用例加到用例集及运行顺序
    40     suite.addTest(TestRequestOne('test_api2'))
    41     suite.addTest(TestRequestOne('test_api1'))
    42     return suite
    43 
    44 if __name__ == "__main__":
    45     filePath = 'D:\Report.html'  # 确定生成报告的路径
    46     fp = open(filePath, 'wb')
    47     runner = HTMLTestReportCN.HTMLTestRunner(
    48         stream=fp,
    49         title='简单接口自动化测试报告',
    50         description='简单接口自动化测试用例结果',    #不传默认为空
    51         tester='wuwei'  # 测试人员名字,不传默认为QA
    52     )
    53     runner.run(suite())

      上述测试用例运行结果的测试报告如下:

    八、seleniumWeb自动化应用unittest实例

      上面我们用unittest进行了接口测试的实例应用,下面我们就来看看unittest如何在seleniumWeb自动化中应用的。我们以百度首页为例来进行web自动化测试,搜索并进行断言,生成对应的测试报告。

     1 # 导入os、unittest、requests、HTMLTestReportCN模块
     2 from selenium import webdriver
     3 import unittest
     4 import os
     5 import HTMLTestReportCN
     6 import time
     7 
     8 # unittest.TestCase:TestCase类,所有测试用例类继承的基本类。
     9 class TestSeleniumOne(unittest.TestCase):
    10     # 每次case执行前,调用接口地址
    11     def setUp(self):
    12         print("这里是一个测试用例前的准备工作")
    13         #chrome实例,打开浏览器网页
    14         self.driver = webdriver.Chrome()
    15         self.driver.get('https://www.baidu.com')
    16 
    17     def tearDown(self):
    18         print("这里是一个测试用例后的清理工作")
    19         #每个用例执行后关闭浏览器
    20         self.driver.quit()
    21 
    22     # 测试用例1
    23     def test_selenium1(self):
    24         # 利用find_element_by_id定位元素位置并模拟按键输入“博客园”,点击百度一下按钮搜索,断言
    25         self.driver.find_element_by_id("kw").send_keys("博客园")
    26         self.driver.find_element_by_id("su").click()
    27         time.sleep(5)
    28         resultTest = self.driver.find_element_by_xpath("//*[@id='1']/h3").text
    29         self.assertEqual(resultTest,"博客园 - 开发者的网上家园官方")
    30 
    31     # 测试用例2
    32     def test_selenium2(self):
    33         # 利用find_element_by_id定位元素位置并模拟按键输入“测试”,点击百度一下按钮搜索,断言
    34         self.driver.find_element_by_id("kw").send_keys("测试")
    35         self.driver.find_element_by_id("su").click()
    36         time.sleep(5)
    37         resultTest = self.driver.find_element_by_xpath("//*[@id='3001']/div[1]/h3").text
    38         self.assertEqual(resultTest,"ceshi_前景如何?博为峰16年专注软件测试培训")
    39 
    40 #测试用例集合方法
    41 def suite():
    42     #实例化测试套件
    43     suite = unittest.TestSuite()
    44     #将用例加到用例集及运行顺序
    45     suite.addTest(TestSeleniumOne('test_selenium1'))
    46     suite.addTest(TestSeleniumOne('test_selenium2'))
    47     return suite
    48 
    49 if __name__ == "__main__":
    50     filePath = 'D:\Report.html'  # 确定生成报告的路径
    51     fp = open(filePath, 'wb')
    52     runner = HTMLTestReportCN.HTMLTestRunner(
    53         stream=fp,
    54         title='简单Web自动化测试报告',
    55         description='简单Web自动化测试用例结果',    #不传默认为空
    56         tester='wuwei'  # 测试人员名字,不传默认为QA
    57     )
    58     runner.run(suite())

      上述测试用例运行结果的测试报告如下:

  • 相关阅读:
    mysql max_allowed_packet过小导致的prepare失败
    linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解
    mysql metadata lock锁
    velocity merge作为工具类从web上下文和jar加载模板的两种常见情形
    mysql 5.7.15发布
    mysql 5.6.33发布
    2016年09月编程语言排行榜
    postgresql 9.6 rc1发布
    www.97top10.com--做最好的技术交流网站
    nginx/ajax跨子域请求的两种现代方法以及403解决
  • 原文地址:https://www.cnblogs.com/wuweiblogs/p/13043588.html
Copyright © 2011-2022 走看看