носа не сканирует для испытаний статически, так что вы можете использовать метаклассом магию, чтобы сделать тесты, Нос находит.
Жесткая часть состоит в том, что стандартные методы метакласса не устанавливают атрибут func_name правильно, что и ищет Нос, проверяя, являются ли методы вашего класса испытаниями.
Вот простой метакласс. Он просматривает функцию 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 как часть набора тестов носа.
Кроме того, у меня было много проблем с получением надлежащего закрытия, работающего с новым.функция, поэтому в этом коде используется m(self, func)
, где func
считается аргументом по умолчанию. Естественно было бы использовать закрытие над value
, но это, похоже, не работает.
Вы пробовали мое решение? Он не основан на какой-либо магии, полученный пакет должен быть доступен для обнаружения. – muhuk 2008-12-07 15:50:19