• unittest单元测试笔记


    单元测试

      unittest单元测试是基于java的JUnit思想框架开发出来的测试框架

     使用示例1

    import  unittest
    class Mytest1(unittest.TestCase):
        def test_a(self):#用例必须已test开头
            self.assertEqual(1,1,msg='错误提示信息,如果校验失败,出现这个')
            print('a')
        def test_c(self):
            self.assertEqual(1,2,msg='失败')#如果校验结果不正确,不会执行后面的代码
            print('c')#这条代码不会执行
        def test_z(self):#函数执行优先级:按照函数的首字母顺序依次执行A-Z-a-z
            self.assertEqual(4,4)
            print('z')
        def test_G(self):
            self.assertEqual(3,3)
            print('G')
    if __name__ == "__main__":
        suite = unittest.TestSuite()
        #suite.addTest(Mytest1('test_a')) #添加一个测试类中的一个方法
        testlist = [Mytest1('test_c'),Mytest1('test_d')]
        suite.addTests(testlist) #加载多个测试类的方法
        unittest.TextTestRunner().run(suite)

     使用示例2

    import  unittest
    class Mytest1(unittest.TestCase):
        def test_a(self):#用例必须已test开头
            self.assertEqual(1,1,msg='错误提示信息,如果校验失败,出现这个')
            print('a')
        def test_c(self):
            self.assertEqual(1,2,msg='失败')#如果校验结果不正确,不会执行后面的代码
            print('c')#这条代码不会执行
        def test_z(self):#函数执行优先级:按照函数的首字母顺序依次执行A-Z-a-z
            self.assertEqual(4,4)
            print('z')
        def test_G(self):
            self.assertEqual(3,3)
            print('G')
    if __name__ == "__main__":
        #suite = unittest.TestLoader().loadTestsFromTestCase(Mytest1) #指定类的加载
        #suite = unittest.TestLoader().loadTestsFromName('a') #导入模块名
        #suite = unittest.TestLoader().loadTestsFromName('a.Mytest1.test_a') #也可以这样导入
    
        test_list = ['a.Mytest1.test_a','a.Mytest1.test_z']
        suite = unittest.TestLoader().loadTestsFromNames(test_list) #导入多个模块
        unittest.TextTestRunner().run(suite)

    跳过skip的使用

    import  unittest
    a = 1
    b = 2
    class Mytest1(unittest.TestCase):
        @unittest.skip('该函数已经弃用,跳过该方法') #表示跳过test_a函数,不会被执行
        def test_a(self):#用例必须已test开头
            self.assertEqual(1,1,msg='错误提示信息,如果校验失败,出现这个')
            print('a')
        @unittest.skipIf(b>a,'判断后执行') #如果b大于a,跳过执行,反之执行, skipUnless是skip相反的方法
        def test_c(self):
            self.assertEqual(1,2,msg='失败')#如果校验结果不正确,不会执行后面的代码
            print('c')#这条代码不会执行
        @unittest.expectedFailure #不用执行,直接为false
        def test_z(self):#函数执行优先级:按照函数的首字母顺序依次执行A-Z-a-z
            self.assertEqual(4,4)
            print('z')
        def test_G(self):
            self.assertEqual(3,3)
            print('G')
    if __name__ == "__main__":
        unittest.main() #运行所有测试用例
    
        #unittest命令行方式
        #python -m unittest a b 执行多个单元测试模块
        #python -m unitest  a.test_a b.test_b 执行模块类或者方法

     HTMLTestRunner以及美化报告

    import  unittest
    import HTMLTestRunner
    class Mytest1(unittest.TestCase):
        def test_a(self):#用例必须已test开头
            self.assertEqual(1,1,msg='错误提示信息,如果校验失败,出现这个')
            print('a')
        def test_c(self):
            self.assertEqual(1,2,msg='失败')#如果校验结果不正确,不会执行后面的代码
            print('c')#这条代码不会执行
        def test_z(self):#函数执行优先级:按照函数的首字母顺序依次执行A-Z-a-z
            self.assertEqual(4,4)
            print('z')
        def test_G(self):
            self.assertEqual(3,3)
            print('G')
    #unittest.main()#运行所有函数
    #unittest.defaultTestLoader.discover()#可以指定一个文件夹,在指定目录下找到测试用例
    f = open('a.html','wb')#创建文件
    runner = HTMLTestRunner.HTMLTestRunner(f,title='rainbol_test',description='这是一个接口测试用例')#实例化用例报告,并传入文件,title标题,description描述
    suite = unittest.makeSuite(Mytest1)#把要生成报告的类变成一个测试集合,
    runner.run(suite)#运行测试用例
    
    
    import BeautifulReport
    #美化报告
    class Mytest2(unittest.TestCase):
        def test_a(self):
            '''test_a用例'''#添加用例描述,可以在测试报告中显示
            self.assertEqual(1,1,msg='错误提示信息,如果校验失败,出现这个')
        def test_c(self):
            '''test_c用例'''
            self.assertEqual(1,2,msg='失败')
            print('c')
        def test_z(self):
            '''test_z用例'''
            self.assertEqual(4,4)
            print('z')
    
    
    new_suite= unittest.makeSuite(Mytest2)
    report = BeautifulReport.BeautifulReport(new_suite)
    report.report(filename='new_report.html',description='这个是新接口测试报告')
    
    
    class Mytest3(unittest.TestCase):
        def setUp(self):#每条用例前执行,比如检测接口连接是否正常
            print('setUp')
        def tearDown(self):#每条用例后执行,比如清理缓存,cookie,redis的信息
            print('tearDown')
    @classmethod  #注意加入装饰器
    def setUpClass(cls):#这个类里面的用例先执行,比如连接数据库 print('setUpClass') @classmethod  #注意加入装饰器 def tearDownClass(cls):#这个类里面的用例最后执行,比如关闭数据库 print('tearDownClass')
      def test_c(self): '''test_c用例''' self.assertEqual(1, 2, msg='失败') print('c') def test_z(self): '''test_z用例''' self.assertEqual(4,4) print('z') unittest.main() #执行顺序 setUpClass→setUp→test_c→tearDown→setUp→test_z→tearDown→tearDownClass

     

     注意点

    import unittest
    
    #python不支持多函数传参的方式用在unittest上
    class Mytest2(unittest.TestCase):
        def test_a(self):
            self.a = 2
            self.assertEqual(1, 1, msg='错误提示信息,如果校验失败,出现这个')
            print('1')
    
        def test_c(self):
            print(self.a)
            self.assertEqual(1, 2, msg='失败')
            print('2')
    #这样写运行就会报找不到self.a

      @classmethod  
      def setUpClass(cls):
      cls.res = '1'
      print('setUpClass')
      def test_d(self):
        print(self.res) #但是这些除外,可以找到

     数据驱动ddt  pip install ddt

    #数据驱动ddt
    import ddt
    import  unittest
    @ddt.ddt
    class Mytest1(unittest.TestCase):
        @ddt.data(*[x for x in range(2)])
        def test_a(self,value):
            self.assertEqual(10,value,'xx')
        #如上执行我们可以看到只要几行代码就可以把重复的测试用例,只是参数不同,把参数传递给一个方法中执行,运行的结果实现了多个用例的单元测试
    
        @ddt.data([1,2,3],[2,4,6])
        @ddt.unpack #一条以上数据要用unpack
        def test_b(self,value1,value2,value3):
            self.assertEqual(value1+value2,value3)
    if __name__ == "__main__":
        unittest.main()

    单元测试覆盖率

      度量的方式

        1.语句覆盖:被度量的代码中每个都执行到

        2.判定覆盖:被称为分支覆盖,即每个分支都会被测到

        3.条件覆盖:如果在判断覆盖中又存在多个表达式的情况,也要被测试到,如 if a = 1 and b = 2 

        其他等等...

      coverage的使用(语句覆盖)

        下载

          pip install coverage

        帮助

          coverage help

        运行

          coverage run

        demo实例

    #demo.py
    
    import unittest
    
    
    class Mytest1(unittest.TestCase):
        def test_a(self):  # 用例必须已test开头
            self.assertEqual(1, 1, msg='错误提示信息,如果校验失败,出现这个')
            print('a')
    
        def test_c(self):
            self.assertEqual(1, 1, msg='失败')  # 如果校验结果不正确,不会执行后面的代码
            print('c')  # 这条代码不会执行
    
        def test_z(self):  # 函数执行优先级:按照函数的首字母顺序依次执行A-Z-a-z
            self.assertEqual(4, 4)
            print('z')
    
        def test_G(self):
            self.assertEqual(3, 3)
            print('G')
    
        def other1(self):
            print('其他的方法')
    
        def other2(self):
            print('其他的方法')
    
        def other3(self):
            print('其他的方法')
    
        def other4(self):
            print('其他的方法')
    
    
    class Mytest2(unittest.TestCase):
        def test_a(self):  # 用例必须已test开头
            self.assertEqual(1, 1, msg='错误提示信息,如果校验失败,出现这个')
            print('a')
    
        def test_c(self):
            self.assertEqual(1, 1, msg='失败')  # 如果校验结果不正确,不会执行后面的代码
            print('c')  # 这条代码不会执行
    
        def test_z(self):  # 函数执行优先级:按照函数的首字母顺序依次执行A-Z-a-z
            self.assertEqual(4, 4)
            print('z')
    
        def test_G(self):
            self.assertEqual(3, 3)
            print('G')
    
    
    if __name__ == '__main__':
        unittest.main()

        coverage run demo.py #运行单测代码

        coverage report #生成命令行结果

         coverage html -d xxx.html        #生成html文件   -d 指定html名称

     可以看到没有执行的代码被高亮出来

        coverage xml #生成xml文件

    # 封装api的方式
    import unittest
    import coverage
    
    cover = coverage.coverage(source=['test_demo'])
    cover.start()
    suite = unittest.defaultTestLoader.discover(start_dir='.', pattern='test_*.py')
    unittest.TextTestRunner().run(suite)
    
    cover.stop()
    cover.report()
    cover.html_report(directory='report')

    版权声明:本文原创发表于 博客园,作者为 RainBol 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

  • 相关阅读:
    HTML5
    js实现查找字符串中最多的字符的个数
    get和post的区别
    第十七篇 类的特殊成员
    第十八篇 面向对象修饰符
    MariaDB+Keepalived双主高可用配置MySQL-HA
    linux命令详解——crontab
    Java的内存泄漏
    jvm监控工具jconsole进行远程监控配置
    loadrunner执行场景时报Error -27040: Data Format Extension: Init: Internal error问题解决
  • 原文地址:https://www.cnblogs.com/RainBol/p/10055800.html
Copyright © 2020-2023  润新知