nariz no busca pruebas de forma estática, por lo que puede uso magia metaclase para hacer pruebas de que la nariz se encuentra.
La parte difícil es que las técnicas estándar de metaclases no configuran el atributo func_name correctamente, que es lo que busca Nose cuando comprueba si los métodos de su clase son pruebas.
Aquí hay una metaclase simple. Se ve a través de la función y agrega un nuevo método para cada método que encuentra, afirmando que el método que encontró tiene una docstring. Estos nuevos métodos sintéticos reciben los nombres "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)
Ahora, vamos a crear una nueva clase que utiliza este metaclase
class Foo(object):
__metaclass__ = Meta
def greeter(self):
"sdf"
print 'Hello World'
def greeter_no_docstring(self):
pass
En tiempo de ejecución, Foo
en realidad será nombrado Test_Foo
y tendrá greeter
, greeter_no_docstring
, test_1
y test_2
como sus métodos. Cuando corro nosetests
en este archivo, aquí está la salida:
$ 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)
Este metaclase no es realmente útil como es, pero si en lugar de utilizar el Meta
no como una metaclase adecuada, pero más como una metaclase funcional (es decir, toma una clase como argumento y devuelve una nueva clase, una que se renombró para que la nariz la encuentre), entonces es útil. He utilizado este enfoque para probar automáticamente que las cadenas de documentos se adhieren al estándar Numpy como parte de un conjunto de pruebas de nariz.
Además, he tenido muchos problemas para lograr el cierre adecuado trabajando con los nuevos.función, razón por la cual este código usa m(self, func)
donde func
está hecho para ser un argumento predeterminado. Sería más natural usar un cierre sobre value
, pero eso no parece funcionar.
¿Has probado mi solución? No se basa en ninguna magia, la suite resultante debe ser reconocible. – muhuk
Tengo, ver comentario en el hilo original. Tal vez hay una opción de configuración para ello, o alguna forma de configurar un "objetivo ficticio" para la nariz? – saffsd
Por cierto, he resuelto este problema sin recurrir al generador de prueba de la nariz (está limitado que no se puede usar para las subclases de 'unittest.TestCase'). Ver: http://stackoverflow.com/questions/5176396/nose-unittest-testcase-and-metaclass-auto-generated-test-methods-not-discover/5177625#5177625 – Santa