zoukankan      html  css  js  c++  java
  • Selenium(十六):unittest单元测试框架(二) 初识unittest(续)

    1. 认识unittest(续)

    关于unittest单元测试框架,还有一些问题值得进一步探讨。你可能在前一章的学习过程中产生了一些疑问,也许你会在本节中找到答案。

    1.1 用例执行的顺序

    用例的执行顺序涉及多个层级,在多个测试目录的情况下,先执行哪个目录?在多个测试文件的情况下,先执行哪个文件?在多个测试类的情况下,先执行哪个测试类?在多个测试方法(用例)的情况下,先执行哪个测试方法?

    我们先来运行一个例子,再来解释unittest的执行策略。

    import unittest
    
    class TestBdd(unittest.TestCase):
    
        def setUp(self):
            print("test TestBdd:")
    
        def test_ccc(self):
            print("test ccc")
    
        def test_aaa(self):
            print("test aaa")
    
        def tearDown(self):
            pass
    
    class TestAdd(unittest.TestCase):
    
        def setUp(self):
            print("test TestAdd:")
    
        def test_bbb(self):
            print("test bbb")
    
        def tearDown(self):
            pass
    
    if __name__ == '__main__':
        unittest.main()

    运行结果:

    无论执行多少次,结果都是一样的,通过上面的结果,相信你已经找到了unittest执行测试用例的规律。

    unittest框架默认根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。所以,TestAdd类会优先于TestBdd类被执行,test_aaa()方法会有限与test_ccc()被执行,因而它并没有按照用例从上到下的顺序执行。

    对于测试目录与测试文件来说,unittest框架同样是按照这个规则来加载测试用例的。

    那么可不可以让test_ccc()先执行呢?答案是肯定的,只是不能使用默认的main()方法了,而是需要通过TestSuite类的addTest()按照一定的顺序来加载。

    import unittest
    
    class TestBdd(unittest.TestCase):
    
        def setUp(self):
            print("test TestBdd:")
    
        def test_ccc(self):
            print("test ccc")
    
        def test_aaa(self):
            print("test aaa")
    
        def tearDown(self):
            pass
    
    class TestAdd(unittest.TestCase):
    
        def setUp(self):
            print("test TestAdd:")
    
        def test_bbb(self):
            print("test bbb")
    
        def tearDown(self):
            pass
    
    if __name__ == '__main__':
        #构造测试集
        suite = unittest.TestSuite()
        suite.addTest(TestBdd("test_ccc"))
        suite.addTest(TestAdd("test_bbb"))
        suite.addTest(TestBdd("test_aaa"))
    
        #执行测试
        runner = unittest.TextTestRunner()
        runner.run(suite)

    运行结果:

     现在的执行顺序就是addTest()方法所加载的顺序。discover()的加载测试用例的规则与main()方法相同。所以,我们只能通过测试用例的命名来提高被执行的优先级。例如,将希望先被执行的测试用例命名为“test_a”,将希望最后执行的测试用例命名为“test_z”。

    1.2 执行多级目录的用例

    我们要控制Web用例的数量,但是当测试用例达到一定量级时,就要考虑划分目录。

    test_project/test_case/

      test_bbb/

        test_ccc/

          test_c.py

        test_b.py

      test_ddd/

        test_d.py

      test_a.py

    对于上面的目录结构,如果将discover()方法中的start_dir参数定义为“./test_case/”目录,那么只能加载test_a.py文件中的测试用例。怎样让unittest框架查找到test_case/的子目录中高端测试文件呢?方法很简单,在每个子目录下放一个__init__.py文件(在文件夹中包含一个__init__.py,Python就会把文件夹当作一个package,里面的py文件就能够在外面被import)。

    1.3 跳过测试和预期失败

    在运行测试时,有时需要直接跳过某些测试用例,或者当用例符合某个条件时跳过测试,又或者直接将测试用例设置为失败。unittest提供了实现这些需求的装饰器。

    unittest.skip(reason):无条件的跳过修饰的测试,说明跳过测试的原因。

    unittest.skipIf(condition,reason):跳过修饰的测试,如果条件为真时。

    unittest.skipUnless(condition,reason):跳过修饰的测试,除非条件为真。

    unittest.expectedFailure():测试标记为失败。不管执行结果是否失败,统一标记为失败。

    import unittest
    
    class MyTest(unittest.TestCase):
    
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
    
        @unittest.skip("直接跳过测试")
        def test_skip(self):
            print('test aaa')
    
        @unittest.skipIf(3>2,"当条件为True时跳过测试")
        def test_skip_if(self):
            print('test bbb')
    
        @unittest.skipUnless(3 > 2, "当条件为True时执行测试")
        def test_skip_unless(self):
            print('test ccc')
    
        @unittest.expectedFailure
        def test_expected_failure(self):
            assertEqual(2,3)
    
    
    if __name__ == '__main__':
        unittest.main()

    运行结果:

    上例中共创建了4条测试用例。第一条测试用例通过@unittest.skip()修饰,直接跳过不执行。第二条用例通过@unittest.skipIf()修饰,当条件为真时不执行,3>2条件为真(True),通过不执行。第三条用例通过@unittest.skipUnless装饰,当条件为真时执行,判断3>2条件为真(True),第三条用例执行。第四条用例通过@unittest.expectedFailure装饰,不管执行结果是否失败,统一标记为失败,但不会抛出错误信息。

    当然,这些方法同样可以作用于测试类,只需将它们定义在测试类上面即可。

    import unittest
    
    @unittest.skip("直接跳过测试该测试类")
    class MyTest(unittest.TestCase):

    1.4 fixtures

    fixtures的概念前面已经有过简单的介绍,可以形象的把它看作是夹心饼干外层的两片饼干,这两片饼干就是setUp/tearDown,中间的心就是测试用例。除此之外,unittest还提供了更大范围的fixtures,例如对于测试类和模块的fixtures。

    import unittest
    
    def setUpModule():
        print("test module start >>>>>>>>>>>>>>>>")
    
    def tearDownModule():
        print("test module end >>>>>>>>>>>>>>>>")
    
    class Test(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            print("test class start ==============>")
    
        @classmethod
        def setDownClass(cls):
            print("test class end ==============>")
    
        def setUp(self):
            print("test case start -->")
    
        def tearDown(self):
            print("test case end -->")
    
        def test_case(self):
            print("test case1")
    
        def test_case2(self):
            print("test case2")
    
    if __name__ == '__main__':
        unittest.main()

    运行结果:

    setUpModule/tearDownModule:在整个模块的开始与结束时被执行。

    setUpClass/tearDownClass:在测试类的开始与结束时被执行。

    setUp/tearDown:在测试用例的开始与结束时被执行。 

    需要注意的是, setUpClass/tearDownClass的写法稍微有些不同。首先,需要通过@classmethon进行修饰,其次方法的参数为cls。其实,cls与self并没有什么特别之处,都只表示类方法的第一个参数,只是大家约定俗成,习惯于这样来命名,当然也可以用abc来代替。

  • 相关阅读:
    Entity Framework 5.0运行.NET Framework 4.0之上在查询表达式中使用显示转换的一个问题
    How to get memcached all keys
    不同dll相同Type.FullName引发的问题
    WinDbg的cmdtree命令
    警惕缺省参数(Optional Parameters)对类型(Type)构造函数(Constructor)设计的影响
    如何解决Silverlight InitializeError #2103 Invalid or malformed application: Check manifest
    在北京拿5000.00元的工资
    分区表2
    C#操作config文件
    分区表1
  • 原文地址:https://www.cnblogs.com/liuhui0308/p/11972047.html
Copyright © 2011-2022 走看看