zoukankan      html  css  js  c++  java
  • unittest单元测试(转载)

    java的单元测试框架Junit和TestNG,python里面也有单元测试框架-unittest,相当于是一个python版的junit。python里面的单元测试框架除了unittest,还有一个pytest框架,但是用的比较少

    unittest注意点:
    导入unittest模块
    类名的第一个字母大写;
    类要继承unittest.TestCase;
    测试函数前必须加test,否则不会被当作测试用例来执行;
    setUp()和tearDown()方法每个测试用例都会执行;
     

    代码示例1:简单用法

    #encoding=utf-8
    
    import unittest
    import random
    
    class TestSequenceFunctions(unittest.TestCase):
        def setUp(self):
            # 初始化一个递增序列
            self.seq = range(10)
            print ("setup completed!")
    
    
        def test_run(self):
            # 从序列seq中随机选取一个元素
            element = random.choice(self.seq)
            # 验证随机元素确实属于列表中
            self.assertTrue(element in self.seq)
    
        def test_sth(self):
            assert 1==1
    
        def tearDown(self):
            print ("tearDown completed")
    
    
    class TestDictValueFormatFunctions(unittest.TestCase):
        def setUp(self):
            self.seq = list(range(10))
    
        def test_shuffle(self):
            # 随机打乱原seq的顺序
            random.shuffle(self.seq)
            self.seq.sort()
            self.assertEqual(self.seq, list(range(10)))
            # 验证执行函数时抛出了TypeError异常
            self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
    
    
    if __name__ == '__main__':
    unittest.main()


    说明:

    setUp:做初始化的工作,不是必须有这个函数

    tearDown:清理的工作,不是必须有这个函数

    unittest.main():将所有继承自unittest.TestCase的子类中的方法都执行

    assertRaises();第一个参数表示抛出的异常类型,第二个参数是要执行的函数,第三个参数是函数传入的参数

    代码示例2:初始化只执行一次的方法

    #encoding=utf-8
    import unittest
    
    # 被测试类
    class myclass(object):
        @classmethod
        def sum(self, a, b):
            return a + b #将两个传入参数进行相加操作
    
        @classmethod
        def sub(self, a, b):
            return a - b #将两个传入参数进行相减操作
    
    
    class mytest(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            "初始化类固件"
            print ("----setUpClass")
    
        @classmethod
        def tearDownClass(cls):
            "重构类固件"
            print ("----tearDownClass")
    
        # 初始化工作
        def setUp(self):
            self.a = 3
            self.b = 1
            print ("--setUp")
    
        # 具体的测试用例,一定要以test开头
        def testsum(self):
            # 断言两数之和的结果是否是4
            self.assertEqual(myclass.sum(self.a, self.b), 4, 'test sum fail')
    
        def testsub(self):
            # 断言两数之差的结果是否是2
            self.assertEqual(myclass.sub(self.a, self.b), 2, 'test sub fail')
    
    
    if __name__ == '__main__':
    unittest.main() # 启动单元测试



    说明:setUpClass()和tearDownClass()在每个类中只执行一次

    代码示例3:按数字或字母顺序执行测试case

    #encoding=utf-8
    
    import unittest
    from Calc import Calc
    
    class MyTest(unittest.TestCase):
        @classmethod
        def setUpClass(self):
            print ("单元测试前,创建Calc类的实例")
            self.c = Calc()
    
        # 具体的测试用例,一定要以test开头,执行顺序按照字母顺序开头
        def test_0add(self):
            print ("run add()")
            self.assertEqual(self.c.add(1, 2, 12), 15, 'test add fail')
    
        def test_1sub(self):
            print ("run sub()")
            self.assertEqual(self.c.sub(2, 1, 3), -2, 'test sub fail')
    
        def test_2mul(self):
            print ("run mul()")
            self.assertEqual(Calc.mul(2, 3, 5), 30, 'test mul fail')
    
        def test_3div(self):
            print ("run div()")
            self.assertEqual(Calc.div(8, 2, 4), 1, 'test div fail')
    
    
        def test4(self):
            print('not start with test')
    
    if __name__ == '__main__':
    unittest.main()# 启动单元测试

    说明:

    测试用例(test_*)的执行顺序是根据1-2-3执行的,也就是说根据用例名称来顺序执行的,如果是字母开头的话同理
    test4这个方法没有执行,说明测试用例只能以test开头
    代码示例4:根据实际需要有跳过某些测试case

    #encoding=utf-8
    
    import random,sys,unittest
    
    class TestSeqFunctions(unittest.TestCase):
    
          a = 1
          def setUp(self):
                self.seq = list(range(20)) 
    
          @unittest.skip("skipping")#无条件忽略此测试方法
          def test_shuffle(self):
                random.shuffle(self.seq)
                self.seq.sort()
                self.assertEqual(self.seq,list(range(20)))
                self.assertRaises(TypeError,random.shuffle,(1,2,3))
    
          @unittest.skipIf(a>5,"condition is not satisfied!")#如果a>5忽略此测试方法
          def test_choice(self):
                element = random.choice(self.seq)
                self.assertTrue(element in self.seq)
    
          #除非是linux平台,否则忽略此方法,win32是windows平台
          @unittest.skipUnless(sys.platform.startswith("linux"),"requires Linux")
          def test_sample(self):
                with self.assertRaises(ValueError):
                      random.sample(self.seq, 20)
                for element in random.sample(self.seq, 5):
                      self.assertTrue(element in self.seq)
    
    if __name__=="__main__":
    # unittest.main()
    suite = unittest.TestLoader().loadTestsFromTestCase(TestSeqFunctions)
        suite = unittest.TestSuite(suite)
        unittest.TextTestRunner(verbosity = 2).run(suite)

    说明:

    @unittest.skip("skipping")#无条件忽略此测试方法
    @unittest.skipIf(a > 5, "condition is not satisfied!"):满足第1个参数指定的条件,则忽略该测试方法
    @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux"):除非是第1个参数指定的条件,否则忽略此方法
    没有使用unittest.main()是因为此种方式会将所有的测试类都执行,用unittest.TestLoader().loadTestsFromTestCase(TestSeqFunctions)指定执行的测试类
     

    代码示例5:测试集组合
     

    TestCalc.py:

    #encoding=utf-8
    
    import unittest
    import random
    from Calc import Calc
    
    class TestCalcFunctions(unittest.TestCase):
    
        def setUp(self):
            self.c=Calc()
            print ("setup completed!")
    
        def test_sum(self):
            self.assertTrue(self.c.add(1,2,3,4)==10)
    
        def test_sub(self):
            self.assertTrue(self.c.sub(100,20,30,40)==10)
    
        def test_mul(self):
            self.assertTrue(self.c.mul(1,2,3,40)==240)
    
        def test_div(self):
            self.assertTrue(self.c.div(100,10,2)==5)
    
        def tearDown(self):
            print ("test completed!")
    
        def tearDown(self):
            print ("tearDown completed")
    
    if __name__ == '__main__':
        unittest.main()

    unittest_suite.py

    #encoding=utf-8
    
    import random
    import unittest
    from TestCalc import TestCalcFunctions
    
    class TestSequenceFunctions(unittest.TestCase):
        def setUp(self):
            self.seq = list(range(10))
    
        def tearDown(self):
            pass
    
        def test_choice(self):
            # 从序列seq中随机选取一个元素
            element = random.choice(self.seq)
            # 验证随机元素确实属于列表中
            self.assertTrue(element in self.seq)
    
        def test_sample(self):
            # 验证执行的语句是否抛出了异常
            with self.assertRaises(ValueError):
                random.sample(self.seq, 20)
    
            for element in random.sample(self.seq, 5):
                self.assertTrue(element in self.seq)
    
    class TestDictValueFormatFunctions(unittest.TestCase):
        def setUp(self):
            self.seq = list(range(10))
    
        def tearDown(self):
            pass
    
        def test_shuffle(self):
            # 随机打乱原seq的顺序
            random.shuffle(self.seq)
            self.seq.sort()
            self.assertEqual(self.seq, list(range(10)))
            # 验证执行函数时抛出了TypeError异常
            self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
    
    
    if __name__ == '__main__':
        # 根据给定的测试类,获取其中所有以“test”开头的测试方法,并返回一个测试套件
        suite1 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
        suite2 = unittest.TestLoader().loadTestsFromTestCase(TestDictValueFormatFunctions)
        suite3 = unittest.TestLoader().loadTestsFromTestCase(TestCalcFunctions)


    # 将多个测试类加载到测试套件中
    #通过调整suit2和suite1的顺序,可以设定执行顺序
    suite = unittest.TestSuite([suite2, suite1,suite3])      
    # 设置verbosity = 2,可以打印出更详细的执行信息
        unittest.TextTestRunner(verbosity = 2).run(suite)


     

    代码示例6:unittest中的断言方法

    #encoding=utf-8
    
    import unittest,random
    
    # 被测试类
    class MyClass(object):
    
        @classmethod
        def sum(self, a, b):
            return a + b
    
        @classmethod
        def div(self, a, b):
            return a / b
    
        @classmethod
        def retrun_None(self):
            return None
    
    # 单元测试类
    class MyTest(unittest.TestCase):
        # assertEqual()方法实例
        def test_assertEqual(self):
            # 断言两数之和的结果
            try:
                a, b = 1, 2
                sum = 3
                self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
            except AssertionError as e:
                print (e)
    
        # assertNotEqual()方法实例
        def test_assertNotEqual(self):
            # 断言两数之差的结果
            try:
                a, b = 5, 2
                res = 1
                self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
            except AssertionError as e:
                print (e)
    
        # assertTrue()方法实例
        def test_assertTrue(self):
            # 断言表达式的为真
            try:
                self.assertTrue(1 == 1, "表达式为假")
            except AssertionError as e:
                print (e)
    
        # assertFalse()方法实例
        def test_assertFalse(self):
            # 断言表达式为假
            try:
                self.assertFalse(3 == 2, "表达式为真")
            except AssertionError as e:
                print (e)
    
        # assertIs()方法实例
        def test_assertIs(self):
            # 断言两变量类型属于同一对象
            try:
                a = 12
                b = a
                self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
            except AssertionError as e:
                print (e)
    
        # test_assertIsNot()方法实例
        def test_assertIsNot(self):
            # 断言两变量类型不属于同一对象
            try:
                a = 12
                b = "test"
                self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
            except AssertionError as  e:
                print (e)
    
        # assertIsNone()方法实例
        def test_assertIsNone(self):
            # 断言表达式结果为None
            try:
                result = MyClass.retrun_None()
                self.assertIsNone(result, "not is None")
            except AssertionError as e:
                print (e)
    
        # assertIsNotNone()方法实例
        def test_assertIsNotNone(self):
            # 断言表达式结果不为None
            try:
                result = MyClass.sum(2, 5)
                self.assertIsNotNone(result, "is None")
            except AssertionError as e:
                print (e)
    
        # assertIn()方法实例
        def test_assertIn(self):
            # 断言对象A是否包含在对象B中
            try:
                strA = "this is a test"
                strB = "is"
                self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
            except AssertionError as e:
                print (e)
    
        # assertNotIn()方法实例
        def test_assertNotIn(self):
            # 断言对象A不包含在对象B中
            try:
                strA = "this is a test"
                strB = "Selenium"
                self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
            except AssertionError as e:
                print (e)
    
        # assertIsInstance()方法实例
        def test_assertIsInstance(self):
            # 测试对象A的类型是否值指定的类型
            try:
                x = MyClass
                y = object
                self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
            except AssertionError as e:
                print (e)
    
        # assertNotIsInstance()方法实例
        def test_assertNotIsInstance(self):
            # 测试对象A的类型不是指定的类型
            try:
                a = 123
                b = str
                self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
            except AssertionError as e:
                print (e)
    
    
    
        # assertRaises()方法实例
        def test_assertRaises(self):
    
            # 测试抛出的指定的异常类型
            # assertRaises(exception)
            with self.assertRaises(ValueError) as cm:
                random.sample([1,2,3,4,5], 6)
    
            # 打印详细的异常信息
            #print ("===", cm.exception)
            # assertRaises(exception, callable, *args, **kwds)
            try:
                self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
            except ZeroDivisionError as e:
                print (e)
    
        # assertRaisesRegexp()方法实例
        def test_assertRaisesRegexp(self):
            # 测试抛出的指定异常类型,并用正则表达式具体验证
            # assertRaisesRegexp(exception, regexp)
            with self.assertRaisesRegexp(ValueError, 'literal') as ar:
                int("xyz")
            # 打印详细的异常信息
            #print (ar.exception)
            # 打印正则表达式
            #print( "re:",ar.expected_regexp)
            # assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
            try:
                self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
            except AssertionError as e:
                print (e)
    
    if __name__ == '__main__':
        # 执行单元测试
        unittest.main()


    说明:

    assertEqual(first, second, msg=None):如果两个对象不相等,返回False,第三个参数个msg是遇到异常后自定义输出信息

    常用方法:

    assertEqual(first, second, msg=None):判断两个对象相等,first == second
    assertNotEqual(first, second, msg=None):判断两个对象不相等,first != second
    assertIn(member, container, msg=None):判断字符串是否包含,member in container
    assertNotIn(member, container, msg=None):判断字符串不包含,member not in container
    assertTrue(expr, msg=None):判断是否为真,expr is True
    assertFalse(expr, msg=None):判断是否为假,expr is False
    assertIsNone(self, obj, msg=None):判断是否为None, obj is None
    assertIsNotNone(self, obj, msg=None):判断不为None, obj is not  None
     

    代码示例7:生成HTMLTestRunner测试报告
    HTMLTestRunner用来生成HTML测试报告,是对python标准库unittest的一个扩展,使用前需要下载HTMLTestRunner.py文件,下载成功后放到…pythonLib目录下:

    python2下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html 
    python3下载地址:http://pan.baidu.com/s/1dEZQ0pz

    代码:

    # coding=utf-8
    import unittest
    import HTMLTestRunner
    import math
    
    class Calc(object):
    
    def add(self, x, y, *d):
    # 加法计算
    result = x + y
    for i in d:
    result += i
    return result
    
    def sub(self, x, y, *d):
    # 减法计算
    result = x - y
    for i in d:
    result -= i
    return result
    
    class SuiteTestCalc(unittest.TestCase):
    def setUp(self):
    self.c = Calc()
    
    @unittest.skip("skipping")
    def test_Sub(self):
    print ("sub")
    self.assertEqual(self.c.sub(100, 34, 6), 61, u'求差结果错误!')
    
    def testAdd(self):
    print ("add")
    self.assertEqual(self.c.add(1, 32, 56), 89, u'求和结果错误!')
    
    
    class SuiteTestPow(unittest.TestCase):
    def setUp(self):
    self.seq = range(10)
    
    # @unittest.skipIf()
    def test_Pow(self):
    print ("Pow")
    self.assertEqual(pow(6, 3), 2161, u'求幂结果错误!')
    
    def test_hasattr(self):
    print ("hasattr")
    # 检测math模块是否存在pow属性
    self.assertTrue(hasattr(math, 'pow1'), u"检测的属性不存在!")
    
    if __name__ == "__main__":
    suite1 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestCalc)
    suite2 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestPow)
    suite = unittest.TestSuite([suite1, suite2])
    #unittest.TextTestRunner(verbosity=2).run(suite)
    filename = "test.html" # 定义个报告存放路径,支持相对路径。
    # 以二进制方式打开文件,准备写
    fp = open(filename, 'wb')
    # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
    runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
    title = u'测试报告', description = u'测试报告内容')
    # 运行测试集合
    runner.run(suite)

    说明:

    import HTMLTestRunner:将模块导入
    HTMLTestRunner.HTMLTestRunner(stream = fp,title = u'测试报告', description = u'测试报告内容'):使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述
    runner.run(suite):运行测试集合
     

    代码示例8:运行当前目录下所有的测试模块
    以文本方式运行:

    以文本方式运行:

    #encoding=utf-8
    import unittest
    
    if __name__ == '__main__' :
    # 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
    testSuite = unittest.TestLoader().discover('.')
    unittest.TextTestRunner(verbosity = 2).run(testSuite)


    生成html报告:

    #encoding=utf-8
    import unittest
    import HTMLTestRunner
    
    if __name__ == '__main__' :
    # 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
    testSuite = unittest.TestLoader().discover('.')
    filename = "test.html" # 定义个报告存放路径,支持相对路径。
    # 以二进制方式打开文件,准备写
    fp = open(filename, 'wb')
    # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
    runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
    title = 'Report_title', description = 'Report_description')
    # 运行测试集合
    runner.run(testSuite)


     

     
    ————————————————
    原文链接:https://blog.csdn.net/kongsuhongbaby/article/details/84111435

  • 相关阅读:
    2019-2020-1 20199325《Linux内核原理与分析》第十二周作业
    2019-2020-1 20199325《Linux内核原理与分析》第十一周作业
    2019-2020-1 20199325《Linux内核原理与分析》第九周作业
    2019-2020-1 20199325《Linux内核原理与分析》第八周作业
    20199328 2019-2020-2 《网络攻防实践》第3周作业
    20199328 2019-2020-2 《网络攻防实践》第2周作业
    20199328 2019-2020-2 《网络攻防实践》第1周作业
    20199328《网络攻防实践》假期作业
    2019-2020-1 20199328《Linux内核原理与分析》第十二周作业
    2019-2020-1 20199328《Linux内核原理与分析》第十一周作业
  • 原文地址:https://www.cnblogs.com/keima/p/14858768.html
Copyright © 2011-2022 走看看