如何正确排序单元测试测试用例?
How to sort unittest TestCases properly?
例如,我希望这些 运行 按照它们在文件中出现的顺序排列。
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 上找到的答案是在搜索所有内容后通过调用/分组测试或说来避免问题
"don't do it, just write your tests differently" 或
"name your tests lexicographically!"
...除了 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 class,并且仅在 Python 2.
我想要 运行 我所有的 Python 3 unittest.TestCase
subclasses,并且我希望能够指定用于订购。
我可以在 unittest
中执行此操作吗?
在做了 很多 的研究之后,得到了 SO 和 Python 的 help
的极大帮助,而 unittest 根本没有帮助文档,我得到了 I 最初想要的答案,所以我想我会写这篇文章来帮助其他人,因为这是一个公平的(而且显然是常见的)请求。
为了运行一个特定的测试用例,我们需要为那个测试用例创建一个新的TestSuite
。 Let'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
非常简单:
定义一个函数来获取函数的行号。
在 Python 3 中,我们之后的属性从 func.im_func.func_code.co_firstlineno
更改为 func.__code__.co_firstlineno
,您可以使用 dir(anyFunction)
.
查看
定义一个函数,根据 cmp
行号对两个参数进行排序。由于 People Can Do Math,cmp
不在 Python 3 中,所以为了可读性,我完全按照它所做的去做。
将 new
空白 TestSuite()
,并给它一个 TestCase 或 10,然后告诉它使用第 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)
returns源代码,行号为索引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.
上找到更有趣的版本
例如,我希望这些 运行 按照它们在文件中出现的顺序排列。
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 上找到的答案是在搜索所有内容后通过调用/分组测试或说来避免问题
"don't do it, just write your tests differently" 或
"name your tests lexicographically!"
...除了 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 class,并且仅在 Python 2.
我想要 运行 我所有的 Python 3 unittest.TestCase
subclasses,并且我希望能够指定用于订购。
我可以在 unittest
中执行此操作吗?
在做了 很多 的研究之后,得到了 SO 和 Python 的 help
的极大帮助,而 unittest 根本没有帮助文档,我得到了 I 最初想要的答案,所以我想我会写这篇文章来帮助其他人,因为这是一个公平的(而且显然是常见的)请求。
为了运行一个特定的测试用例,我们需要为那个测试用例创建一个新的TestSuite
。 Let'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
非常简单:
定义一个函数来获取函数的行号。 在 Python 3 中,我们之后的属性从
func.im_func.func_code.co_firstlineno
更改为func.__code__.co_firstlineno
,您可以使用dir(anyFunction)
. 查看
定义一个函数,根据
cmp
行号对两个参数进行排序。由于 People Can Do Math,cmp
不在 Python 3 中,所以为了可读性,我完全按照它所做的去做。将
new
空白TestSuite()
,并给它一个 TestCase 或 10,然后告诉它使用第 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)
returns源代码,行号为索引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.
上找到更有趣的版本