unit-testing - 如何正确排序单元测试测试用例?

标签 unit-testing python-3.x testing python-unittest

例如,我希望它们按照它们在文件中出现的顺序运行。

import unittest

class Test_MyTests(unittest.TestCase):

    def test_run_me_first(self): pass
    def test_2nd_run_me(self):   pass
    def test_and_me_last(self):  pass

class Test_AnotherClass(unittest.TestCase):

    def test_first(self):        pass
    def test_after_first(self):  pass
    def test_de_last_ding(self): pass

if __name__ == "__main__":
    unittest.main(verbosity=2)

运行这个给出

test_after_first (__main__.Test_AnotherClass) ... ok
test_de_last_ding (__main__.Test_AnotherClass) ... ok
test_first (__main__.Test_AnotherClass) ... ok
test_2nd_run_me (__main__.Test_MyTests) ... ok
test_and_me_last (__main__.Test_MyTests) ... ok
test_run_me_first (__main__.Test_MyTests) ... ok

不是我想要的。

在搜索所有内容后,我在 SO 上找到的答案要么四处走动,要么通过调用/分组测试或说来避免问题

  • “不要这样做,只需以不同的方式编写测试”或

  • “按字典顺序命名您的测试!”

...除了one ,这就是我想要的:

loader = unittest.TestLoader()
ln = lambda f: getattr(MyTestCase, f).im_func.func_code.co_firstlineno
lncmp = lambda a, b: cmp(ln(a), ln(b))
loader.sortTestMethodsUsing = lncmp
unittest.main(testLoader=loader, verbosity=2)

但仅适用于一个 TestCase 类,并且仅在 Python 2 中。

我想运行我所有的 Python 3 unittest.TestCase 子类,并且我希望能够指定用于排序的确切算法。

我可以在 unittest 中执行此操作吗?

最佳答案

在进行了大量研究后,借助 SO 和 Python 的help,而不是 unittest 的文档,我得到了答案I 最初想要,所以我想我会写这篇文章来帮助其他人,因为这是一个公平的(而且显然是常见的)请求。


要运行特定的测试用例,我们需要为该测试用例创建一个新的 TestSuiteLet's do that对于任意数量的测试用例:

def suiteFactory(*testcases):

    ln    = lambda f: getattr(tc, f).__code__.co_firstlineno
    lncmp = lambda a, b: ln(a) - ln(b)

    test_suite = unittest.TestSuite()
    for tc in testcases:
        test_suite.addTest(unittest.makeSuite(tc, sortUsing=lncmp))

    return test_suite

非常简单:

  1. 定义一个函数来获取函数的行号。 在 Python 3 中,我们之后的属性从 func.im_func.func_code.co_firSTLineno 更改为 func.__code__.co_firSTLineno,您可以使用 dir(任何函数)

  2. 定义一个函数,根据 cmp 行号对两个参数进行排序。由于 People Can Do Math,cmp 不在 Python 3 中,所以为了可读性,我完全按照它所做的去做。

  3. 创建一个 new 空白 TestSuite(),并给它一个或十个 TestCase,然后告诉它使用第 2 点对 TestCase 的方法进行排序:cmp他们的行号。


现在我们需要对文件的 TestCase 子类进行排序。

为此,我们可以查看 globals() 及其属性。

def caseFactory():

    from inspect import findsource

    g = globals().copy()

    cases = [
        g[obj] for obj in g
            if obj.startswith("Test")
            and issubclass(g[obj], unittest.TestCase)
    ]

    ordered_cases = sorted(cases, key=lambda f: findsource(f)[1])

    return ordered_cases

这将获取 unittest.TestCase 的所有以 Test 或您喜欢的命名约定开头的子类,然后按行号对它们进行排序:findsource(object) 返回源代码,行号为索引1,这是我们关心的。


将它包装成我们可以使用的东西:

if __name__ == "__main__":
    cases = suiteFactory(*caseFactory())
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(cases)

确实将输出分隔开来,但如果最低级别的测试位于文件的顶部(或底部,或某处)并且应该运行,这可能是一件好事更高级别的测试之前。

所以完整的输出是:

test_run_me_first (__main__.Test_MyTests) ... ok
test_2nd_run_me (__main__.Test_MyTests) ... ok
test_and_me_last (__main__.Test_MyTests) ... ok
test_first (__main__.Test_AnotherClass) ... ok
test_after_first (__main__.Test_AnotherClass) ... ok
test_de_last_ding (__main__.Test_AnotherClass) ... ok

----------------------------------------------------------------------
Ran 6 tests in 0.000s

OK

成功!


您可以在 Github gist. 上找到更有趣的版本

关于unit-testing - 如何正确排序单元测试测试用例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35930811/

相关文章:

Django 测试安装固定装置时出错 - 没有这样的表

python - 在 python3 下解开 python2 日期时间

python - 在 python 中计算嵌套总和

Python 3 - ValueError int()base 必须 >=2 且 <=36

laravel - 在 Laravel 中测试期间取消勾选复选框

c# - 断言没有方法被调用

python - Setuptools - 当测试不在主目录中时如何运行 unittest 测试套件?

unit-testing - 用于测试目的的假 http 服务器

google-chrome - 使用 chromedp 启动具有特定用户配置文件的浏览器

python-2.7 - 如何为 Falcon API python 执行单元测试