ParserTesterMetaclassの__init__の実装読みメモ
https://github.com/python/cpython/blob/v3.10.5/Lib/test/test_argparse.py#L171-L266
__init__内で定義したAddTestsクラスを組合せ分呼び出している
add tests for each combination of an optionals adding method and an arg parsing method
3通り(no_groups, one_group, many_groups)× 2通り(listargs, sysargs)
AddTestsクラスの__init__でやっていること
setattr(tester_cls, test_name, wrapper)!
tester_clsのtest_name(メソッド名)にwrapper(関数)を代入している
Python 組み込み関数 setattr
つまり、tester_clsにテストメソッドを動的に生やしている
tester_clsとして渡されるのはcls(ParserTesterMetaclassをインスタンス化したクラス(ParserTestCase)を継承したクラス)
2種類のアサーションが生える
https://github.com/python/cpython/blob/v3.10.5/Lib/test/test_argparse.py#L227
test_failures
クラス属性failuresを用いたアサーション
https://github.com/python/cpython/blob/v3.10.5/Lib/test/test_argparse.py#L247-L252
test_successes
クラス属性successesを用いたアサーション
https://github.com/python/cpython/blob/v3.10.5/Lib/test/test_argparse.py#L254-L260
test_funcをラップする
test_funcはAddTestsクラスのメソッド test_failures または test_successes
test_nameは'test_{failures,successes}_...'となっている
setattrで生やすメソッドはtest_で始まる → unittest.TestCaseを継承したクラスで個々のテストとして機能する
wrapper関数
test_func引数のデフォルト値としてtest_funcが渡せている(クロージャー)
wrapperが呼び出されるとtest_func(self)の実行
setattrにより、selfがunittest.TestCaseを継承した個々のクラスということ?(動かしてみないと確証なし)
簡単な実装でParserTesterMetaclassの__init__を動かす