如何按照声明的顺序运行单元测试测试用例

Pau*_*McG 7 python python-3.x python-unittest

我完全意识到单元测试的顺序应该无关紧要。但是这些单元测试与实际单元测试一样多用于教学,所以我希望测试输出与测试用例源代码相匹配。

我看到有一种方法可以通过sortTestMethodsUsing在测试加载器上设置属性来设置排序顺序。默认值是cmp()对名称进行词法比较的简单调用。因此,我尝试编写一个cmp-like 函数,该函数将采用两个名称,找到它们的声明行号并返回它们的 -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()
Run Code Online (Sandbox Code Playgroud)

当我运行这个时,我得到这个输出:

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

OK
Run Code Online (Sandbox Code Playgroud)

表明测试用例没有按照声明顺序运行。

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

Pau*_*McG 3

解决方案是显式创建 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)
Run Code Online (Sandbox Code Playgroud)

这给出了所需的输出:

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

OK
Run Code Online (Sandbox Code Playgroud)

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