美文网首页软件测试
[Py_18]Python单元测试(UnitTest)用例的管理

[Py_18]Python单元测试(UnitTest)用例的管理

作者: Fighting_001 | 来源:发表于2018-07-16 01:29 被阅读33次

    目录结构

    一、新增测试用例管理
    二、用例公共部分的合并
    三、用例执行的顺序
    四、用例综合框架的管理
    五、跳过测试和设置预期失败
    

    一、新增测试用例管理

    在前文UnitTest单元测试概述&案例实践是针对单个add方法进行单元测试,本文则是针对需要多个方法进行单元测试的场景。

    实践案例-流程:
    1)在A文件中创建一个Math类,在Math类中定义2个方法(add和sub方法)
    2)在B文件中导入A文件中的所有方法,然后分别创建2个测试类(Test_add和Test_sub),并在这两个类中定义各自的测试方法
    3)构造测试集,分别将2个测试类中测试方法加载到测试集中
    4)执行单元测试用例

    编写代码:

    • calculator2.py
    class Math:
        def __init__(self,a,b): # 初始化
            self.a = int(a)
            self.b = int(b)
    
        def add(self):
            return self.a+self.b
    
        def sub(self):
            return self.a-self.b
    
    • test_Math2.py
    from calculator2 import Math
    import unittest
    
    class Test_add(unittest.TestCase):
        def setUp(self):
            print("--Starting Test--")
    
        def test_add1(self):
            j = Math(5,5)
            self.assertEqual(j.add(),10)
    
        def test_add2(self):
            j = Math(10,20)
            self.assertEqual(j.add(),30)
    
        def tearDown(self):
            print("--End--")
    
    class Test_sub(unittest.TestCase):
        def setUp(self):
            print("--Starting Test--")
    
        def test_sub1(self):
            i = Math(8,8)
            self.assertEqual(i.sub(),0)
    
        def test_sub2(self):
            i = Math(5,3)
            self.assertEqual(i.sub(),2)
    
        def tearDown(self):
            print("--End--")
    
    if __name__=='__main__':
        suite = unittest.TestSuite()
        suite.addTest(Test_add("test_add1"))
        suite.addTest(Test_add("test_add2"))
        suite.addTest(Test_sub("test_sub1"))
        suite.addTest(Test_sub("test_sub2"))
    
        runner = unittest.TextTestRunner()
        runner.run(suite)
    

    执行结果:
    Ran 4 tests in 0.016s

    OK
    --Starting Test--
    --End--
    --Starting Test--
    --End--
    --Starting Test--
    --End--
    --Starting Test--
    --End--

    二、用例公共部分的合并

    以上代码中的每个测试类都有setUp()和tearDown()方法,且两个方法都是一样的,用于打印测试开始和结束的提示语.可以考虑将其合并在一个类中,作为每个测试类共同的父类来继承,就不需要每次单独去写。

    from calculator2 import Math
    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    class Test_add(Test_StartEnd):
        def test_add(self):
            j = Math(5,5)
            self.assertEqual(j.add(),10)
    
    class Test_sub(Test_StartEnd):
        def test_sub(self):
            i = Math(3,2)
            self.assertEqual(i.sub(),1)
    
    # 执行所有的2个测试用例
    if __name__=='__main__':
        unittest.main()
    

    执行结果:
    Ran 2 tests in 0.016s

    OK
    --Test Start--
    --Test End--
    --Test Start--
    --Test End--

    三、用例执行的顺序

    以下代码,在不作代码调控设置的前提下,执行过程是否是与常规认为的自上而下顺序执行呢?(C-->B-->A-->D ?)

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    class Test2(Test_StartEnd):
        def test_c(self):
            print("C")
    
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        def test_a(self):
            print("A")
    
    class Test3(Test_StartEnd):
        def test_d(self):
            print("D")
    

    实际执行结果:
    --Test Start--
    A
    --Test End--
    --Test Start--
    B
    --Test End--
    --Test Start--
    C
    --Test End--
    --Test Start--
    D
    --Test End--

    从执行结果中,可以分析出:
    对于PyCharm默认的runner为Unittests的情况
    1)代码执行顺序的优先级:测试类>>测试方法。即先根据测试类排序区分,然后再分别定位到每个测试类的不同测试方法的排序
    2)测试类or测试方法:根据字母or数字从小到大排序执行,如1-->2-->3、a-->b-->c-->d

    现在通过代码中调控按照设置的顺序来执行测试用例:

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    class Test2(Test_StartEnd):
        def test_c(self):
            print("C")
    
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        def test_a(self):
            print("A")
    
    class Test3(Test_StartEnd):
        def test_d(self):
            print("D")
    
    if __name__=='__main__':
        suite = unittest.TestSuite()
        suite.addTest(Test3("test_d"))
        suite.addTest(Test2("test_c"))
        suite.addTest(Test1("test_a"))
        suite.addTest(Test2("test_b"))
    
        runner = unittest.TextTestRunner()
        runner.run(suite)
    

    执行结果:

    1. 若按PyCharm默认的runner为Unittests执行,则可能依然还是没有按照设定的顺序执行
    2. 若修改PyCharm的默认的runner为py.test执行,则PyCharm中可按照测试类自上而下执行用例(具体修改方法,可参看设置PyCharm根据测试类自上而下顺序执行代码
    默认runner为py.test
    1. 若以cmd命令行执行,则执行效果可按照程序设定控制的顺序执行输出
    cmd命令方式操作

    四、用例综合框架的管理

    以上测试用例及用例执行都是卸载一个文件中,当用例数量不断增加,用例的执行与管理会变得非常冗杂和低效率,因此需要对用例根据具体的功能模块来使用单独的模块进行管理。

    案例:新建一个文件目录Test_Project,其下包含4个python文件进行用例的管理和执行分工
    ① StartEnd.py ==>setUp与tearDown的管理
    ② calculator.py ==>加减法运算方法的实现
    ③ test_add.py ==>加法测试模块
    ④ test_sub.py ==>减法测试模块
    ⑤ runtest.py ==>用例执行管理模块


    StartEnd.py

    import unittest
    
    class setUp_tearDown(unittest.TestCase):
        def setUp(self):
            print("--Start Test--")
    
        def tearDown(self):
            print("--Test End--")
    

    calculator.py

    class Math:
        def __init__(self,a,b):
            self.a = int(a)
            self.b = int(b)
    
        def add(self):
            return self.a+self.b
    
        def sub(self):
            return self.a-self.b
    

    test_add.py

    from calculator import *
    from StartEnd import *
    
    class Test_Add(setUp_tearDown):
        def test_add1(self):
            i = Math(5,5)
            self.assertEqual(i.add(),10)
    
        def test_add2(self):
            i = Math(1,2)
            self.assertEqual(i.add(),3)
    

    test_sub.py

    from calculator import *
    from StartEnd import *
    
    class Test_Sub(setUp_tearDown):
        def test_sub1(self):
            j = Math(6,6)
            self.assertEqual(j.sub(),0)
    
        def test_sub2(self):
            j = Math(7,6)
            self.assertEqual(j.sub(),1)
    

    runtest.py

    import unittest
    
    # 被测脚本的路径
    test_dir = './' # 此时表示当前目录
    # 使用discover可以一次调用多个脚本;pattern设置脚本名称的匹配规则
    discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py')
    
    if __name__ == '__main__':
        runner = unittest.TextTestRunner()
        runner.run(discover)
    

    在以上第⑤个python文件runtest.py执行代码,调用其他模块,执行的结果为:



    五、跳过测试和设置预期失败

    ① @unittest.skip("reason") ==>直接跳过测试
    ② @unittest.skipIf(condition,"reason") ==>条件为真,跳过测试
    ③ @unittest.skipUnless(condition,"reason") ==>条件为假,跳过测试
    ④ @unittest.expectedFailure ==>设置预期为失败


    @unittest.skip("reason")

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    @unittest.skip("skip Test2")
    class Test2(Test_StartEnd):
        def test_c(self):
            print("C")
    
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        def test_a(self):
            print("A")
    
    if __name__ == '__main__':
        unittest.main()
    

    执行结果:

    直接跳过测试类

    @unittest.skipIf(condition,"reason")

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    class Test2(Test_StartEnd):
        def test_c(self):
            print("C")
    
        @unittest.skipIf(1,"skip test_b")
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        def test_a(self):
            print("A")
    
    if __name__ == '__main__':
        unittest.main()
    

    执行结果:

    判断条件为真,跳过测试方法

    @unittest.skipUnless(condition,"reason")

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    class Test2(Test_StartEnd):
        @unittest.skipUnless(1>2,"skip test_c")
        def test_c(self):
            print("C")
    
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        def test_a(self):
            print("A")
    
    if __name__ == '__main__':
        unittest.main()
    

    执行结果:

    判断条件为假,跳过测试方法

    @unittest.expectedFailure

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):
            print("--Test Start--")
    
        def tearDown(self):
            print("--Test End--")
    
    class Test2(Test_StartEnd):
        def test_c(self):
            print("C")
    
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        @unittest.expectedFailure
        def test_a(self):
            print("A")
    
    if __name__ == '__main__':
        unittest.main()
    

    执行结果:

    设置预期失败

    【附】
    ⑤ @classmethod ==>实现对测试类运行前&后的处理

    import unittest
    
    class Test_StartEnd(unittest.TestCase):
        def setUp(self):    # 实现对每个测试方法执行前的处理
            print("--Test Start--")
    
        def tearDown(self): # 实现对每个测试方法执行后的处理
            print("--Test End--")
    
    class Test2(Test_StartEnd):
        def test_c(self):
            print("C")
    
        def test_b(self):
            print("B")
    
    class Test1(Test_StartEnd):
        @classmethod
        def setUpClass(cls):    # 实现对测试类Test1运行前的处理
            print("Class module start test>>>>>>>>>")
    
        @classmethod
        def tearDownClass(cls): # 实现对测试Test1运行后的处理
            print("Class module test end>>>>>>>>>>>")
    
        def test_a(self):
            print("A")
    
    if __name__ == '__main__':
        unittest.main()
    

    执行结果:

    测试类、测试方法-前&后的处理对比

    相关文章

      网友评论

        本文标题:[Py_18]Python单元测试(UnitTest)用例的管理

        本文链接:https://www.haomeiwen.com/subject/uhdppftx.html