本当に複数の unitttest が必要な場合は、複数のメソッドが必要です。これを取得する唯一の方法は、ある種のコード生成を使用することです。これは、メタクラスを使用するか、クラス デコレータを使用して (Python 2.6 を使用している場合) など、定義後にクラスを微調整することによって行うことができます。
これは、特別な「multitest」および「multitest_values」メンバーを探し、それらを使用してその場でテスト メソッドを構築するソリューションです。エレガントではありませんが、大まかにあなたが望むことをします:
import unittest
import inspect
class SomeValue(object):
def __eq__(self, other):
return other in [1, 3, 4]
class ExampleTestCase(unittest.TestCase):
somevalue = SomeValue()
multitest_values = [1, 2, 3, 4]
def multitest(self, n):
self.assertEqual(self.somevalue, n)
multitest_gt_values = "ABCDEF"
def multitest_gt(self, c):
self.assertTrue(c > "B", c)
def add_test_cases(cls):
values = {}
functions = {}
# Find all the 'multitest*' functions and
# matching list of test values.
for key, value in inspect.getmembers(cls):
if key.startswith("multitest"):
if key.endswith("_values"):
values[key[:-7]] = value
else:
functions[key] = value
# Put them together to make a list of new test functions.
# One test function for each value
for key in functions:
if key in values:
function = functions[key]
for i, value in enumerate(values[key]):
def test_function(self, function=function, value=value):
function(self, value)
name ="test%s_%d" % (key[9:], i+1)
test_function.__name__ = name
setattr(cls, name, test_function)
add_test_cases(ExampleTestCase)
if __name__ == "__main__":
unittest.main()
これは、実行したときの出力です
% python stackoverflow.py
.F..FF....
======================================================================
FAIL: test_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 13, in multitest
self.assertEqual(self.somevalue, n)
AssertionError: <__main__.SomeValue object at 0xd9870> != 2
======================================================================
FAIL: test_gt_1 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: A
======================================================================
FAIL: test_gt_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: B
----------------------------------------------------------------------
Ran 10 tests in 0.001s
FAILED (failures=3)
コード生成で発生するいくつかの問題をすぐに確認できます。「test_gt_1」はどこから来たのですか? 名前をより長い「test_multitest_gt_1」に変更できますが、どのテストが 1 ですか? ここでは、_1 ではなく _0 から開始することをお勧めします。おそらく、あなたのケースでは、値を Python 関数名として使用できることがわかっています。
私はこのアプローチが好きではありません。私は、テスト メソッドを自動生成するコード ベース (ある場合はメタクラスを使用) に取り組みましたが、有用というよりも理解するのがはるかに難しいことがわかりました。テストが失敗した場合、失敗の原因を突き止めるのは難しく、失敗の原因を突き止めるためにコードをデバッグするのは困難でした。
(ここに書いた例の失敗をデバッグすることは、私が使用しなければならなかった特定のメタクラス アプローチほど難しくありません。)