Python unittest の load_tests プロトコルにおけるテストの削除方法について
解決したいこと
Python の unittest について、モジュールやパッケージレベルで
テストディスカバリのロードをカスタマイズできる load_tests プロトコル があります。
このプロトコルにおいて、自動的に発見されたテスト群から任意のテストを除去するベストプラクティスを知りたいと考えています。
load_tests プロトコル
モジュールやパッケージには、load_tests と呼ばれる関数を実装できます。これにより、通常のテスト実行時やテストディスカバリ時のテストのロードされ方をカスタマイズできます。
テストモジュールが load_tests を定義していると、それが TestLoader.loadTestsFromModule() から呼ばれます。引数は以下です:
load_tests(loader, standard_tests, pattern)
pattern は loadTestsFromModule からそのまま渡されます。デフォルトは None です。
これは TestSuite を返すべきです。
loader はローディングを行う TestLoader のインスタンスです。 standard_tests は、そのモジュールからデフォルトでロードされるテストです。これは、テストの標準セットのテストの追加や削除のみを行いたいテストモジュールに一般に使われます。第三引数は、パッケージをテストディスカバリの一部としてロードするときに使われます。
発生している問題・エラー
standard_tests
として受け取り、かつ、 load_tests
が返すべき TestSuite
クラスは、
すでに自分が保持している任意のテストを削除する方法を公開していないように思えます。
In [1]: from unittest import TestSuite
In [2]: dir(TestSuite)
Out[2]:
['__call__',
(中略)
'_addClassOrModuleLevelException',
'_cleanup',
'_createClassOrModuleLevelException',
'_get_previous_module',
'_handleClassSetUp',
'_handleModuleFixture',
'_handleModuleTearDown',
'_removeTestAtIndex',
'_tearDownPreviousClass',
'addTest',
'addTests',
'countTestCases',
'debug',
'run']
load_tests プロトコルにおいて、任意のテストを削除するにはどのようにするのがベストプラクティスでしょうか?
自分で試したこと(案)
案1: 内部変数を直接いじる、あるいは、内部メソッドを呼ぶ
TestSuite は 内部変数 _tests
リストとしてテストを保持し、
また、_removeTestAtIndex
メソッドを持っているので、これを直接いじる案があるとは思います。
class BaseTestSuite(object):
def __init__(self, tests=()):
self._tests = []
self._removed_tests = 0
self.addTests(tests)
def _removeTestAtIndex(self, index):
"""Stop holding a reference to the TestCase at index."""
class TestSuite(BaseTestSuite):
...
しかし、これらは内部変数または内部メソッドであるため、直接いじるのは望ましくないと考えています。
案2: TestSuiteを自前で再作成する
これがベストプラクティスな気はしているのですが、あまり直感的ではないと感じています。
def load_tests(loader, standard_tests, pattern):
return TestSuite([
test
for test
in standard_tests
if check_to_run(loader, test, pattern)
])
def check_to_run(loader, test, pattern) -> bool:
"""テストを実行すべきか判定する"""
...
ただ、ここまで書いて思いましたが、 standard_tests
というのは名前の通り、
標準的にロードされるテストを格納している変数であるべきで、
任意のテストをそこから削除するのは好ましくないでは、
よって、やはり案2が自然なのでは、と考えています。
お知恵を拝借できれば幸いです。