Nose はテストを静的にスキャンしないため、メタクラス マジックを使用して、Nose が検出するテストを作成できます。
難点は、標準のメタクラス手法では func_name 属性が正しく設定されないことです。これは、クラスのメソッドがテストであるかどうかをチェックするときに Nose が探すものです。
これは単純なメタクラスです。func dict を調べて、見つかったすべてのメソッドに新しいメソッドを追加し、見つかったメソッドに docstring があることをアサートします。これらの新しい合成メソッドには名前が付けられています"test_%d" %i
。
import new
from inspect import isfunction, getdoc
class Meta(type):
def __new__(cls, name, bases, dct):
newdct = dct.copy()
for i, (k, v) in enumerate(filter(lambda e: isfunction(e[1]), dct.items())):
def m(self, func):
assert getdoc(func) is not None
fname = 'test_%d' % i
newdct[fname] = new.function(m.func_code, globals(), fname,
(v,), m.func_closure)
return super(Meta, cls).__new__(cls, 'Test_'+name, bases, newdct)
それでは、このメタクラスを使用する新しいクラスを作成しましょう
class Foo(object):
__metaclass__ = Meta
def greeter(self):
"sdf"
print 'Hello World'
def greeter_no_docstring(self):
pass
実行時に、Foo
実際には名前が付けられ、そのメソッドとして、、、およびがTest_Foo
含まれます。このファイルで実行すると、出力は次のようになります。greeter
greeter_no_docstring
test_1
test_2
nosetests
$ nosetests -v test.py
test.Test_Foo.test_0 ... FAIL
test.Test_Foo.test_1 ... ok
======================================================================
FAIL: test.Test_Foo.test_0
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/Users/rmcgibbo/Desktop/test.py", line 10, in m
assert getdoc(func) is not None
AssertionError
----------------------------------------------------------------------
Ran 2 tests in 0.002s
FAILED (failures=1)
このメタクラスはそのままではあまり役に立ちませんが、代わりにMeta
適切なメタクラスとしてではなく、より機能的なメタクラスとして使用する場合 (つまり、クラスを引数として取り、新しいクラスを返します。名前が変更されたクラスは、ノーズが動作するように名前が変更されます)それを見つけてください)、それは役に立ちます。私はこのアプローチを使用して、docstrings が Numpy 標準に準拠していることをノーズ テスト スイートの一部として自動的にテストしました。
また、私は new.function で適切なクロージャーを動作させるのに多くの問題を抱えていました。そのため、このコードではm(self, func)
wherefunc
をデフォルトの引数として使用しています。よりもクロージャーを使用する方が自然value
ですが、それはうまくいかないようです。