代码之家  ›  专栏  ›  技术社区  ›  PaulMcG

如何按声明的顺序运行unittest测试用例

  •  2
  • PaulMcG  · 技术社区  · 6 年前

    我发现有一种方法可以通过设置 sortTestMethodsUsing 属性。默认值是一个简单的 cmp() 调用进行词汇比较。所以我试着写了一封信 cmp cmp() -相当于:

    import unittest
    
    class TestCaseB(unittest.TestCase):
        def test(self):
            print("running test case B")
    
    class TestCaseA(unittest.TestCase):
        def test(self):
            print("running test case A")
    
    import inspect
    def get_decl_line_no(cls_name):
        cls = globals()[cls_name]
        return inspect.getsourcelines(cls)[1]
    
    def sgn(x):
        return -1 if x < 0 else 1 if x > 0 else 0
    
    def cmp_class_names_by_decl_order(cls_a, cls_b):
        a = get_decl_line_no(cls_a)
        b = get_decl_line_no(cls_b)
        return sgn(a - b)
    
    unittest.defaultTestLoader.sortTestMethodsUsing = cmp_class_names_by_decl_order
    unittest.main()
    

    running test case A
    .running test case B
    .
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    

    指示测试用例未按声明顺序运行。

    我的sort函数只是没有被调用,所以我怀疑main()正在构建一个新的测试加载程序,它正在清除我的sort函数。

    2 回复  |  直到 6 年前
        1
  •  2
  •   PaulMcG    6 年前

    解决方案是显式创建一个TestSuite,而不是让unittest.main()遵循其所有默认的测试发现和排序行为。我是这样做的:

    import unittest
    
    class TestCaseB(unittest.TestCase):
        def runTest(self):
            print("running test case B")
    
    class TestCaseA(unittest.TestCase):
        def runTest(self):
            print("running test case A")
    
    
    import inspect
    def get_decl_line_no(cls):
        return inspect.getsourcelines(cls)[1]
    
    # get all test cases defined in this module
    test_case_classes = list(filter(lambda c: c.__name__ in globals(), 
                                    unittest.TestCase.__subclasses__()))
    
    # sort them by decl line no
    test_case_classes.sort(key=get_decl_line_no)
    
    # make into a suite and run it
    suite = unittest.TestSuite(cls() for cls in test_case_classes)
    unittest.TextTestRunner().run(suite)
    

    running test case B
    .running test case A
    .
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    

    需要注意的是,每个类中的测试方法都必须命名 runTest

        2
  •  2
  •   ghost    4 年前

    您可以手动构建一个TestSuite,其中您的测试用例和其中的所有测试按行号运行:

    # Python 3.8.3
    import unittest
    import sys
    import inspect
    
    
    def isTestClass(x):
        return inspect.isclass(x) and issubclass(x, unittest.TestCase)
    
    
    def isTestFunction(x):
        return inspect.isfunction(x) and x.__name__.startswith("test")
    
    
    class TestB(unittest.TestCase):
        def test_B(self):
            print("Running test_B")
            self.assertEqual((2+2), 4)
    
        def test_A(self):
            print("Running test_A")
            self.assertEqual((2+2), 4)
    
        def setUpClass():
            print("TestB Class Setup")
    
    
    class TestA(unittest.TestCase):
        def test_A(self):
            print("Running test_A")
            self.assertEqual((2+2), 4)
    
        def test_B(self):
            print("Running test_B")
            self.assertEqual((2+2), 4)
    
        def setUpClass():
            print("TestA Class Setup")
    
    
    def suite():
    
        # get current module object
        module = sys.modules[__name__]
    
        # get all test className,class tuples in current module
        testClasses = [
            tup for tup in
            inspect.getmembers(module, isTestClass)
        ]
    
        # sort classes by line number
        testClasses.sort(key=lambda t: inspect.getsourcelines(t[1])[1])
    
        testSuite = unittest.TestSuite()
    
        for testClass in testClasses:
            # get list of testFunctionName,testFunction tuples in current class
            classTests = [
                tup for tup in
                inspect.getmembers(testClass[1], isTestFunction)
            ]
    
            # sort TestFunctions by line number
            classTests.sort(key=lambda t: inspect.getsourcelines(t[1])[1])
    
            # create TestCase instances and add to testSuite;
            for test in classTests:
                testSuite.addTest(testClass[1](test[0]))
    
        return testSuite
    
    
    if __name__ == '__main__':
    
        runner = unittest.TextTestRunner()
        runner.run(suite())
    
    

    输出:

    TestB Class Setup
    Running test_B
    .Running test_A
    .TestA Class Setup
    Running test_A
    .Running test_B
    .
    ----------------------------------------------------------------------
    Ran 4 tests in 0.000s
    
    OK
    
        3
  •  1
  •   user2357112    6 年前

    sortTestMethodsUsing 方法

    如果你在同一个班级里有两个测试方法, 用来决定他们的顺序(此时,会出现异常,因为函数需要类名。)