run - unittest python 3
Prueba de unidad de Python: ¿cómo ejecutar solo una parte de un archivo de prueba? (13)
Como usas unittest.main()
puedes ejecutar python tests.py --help
para obtener la documentación:
Usage: tests.py [options] [test] [...]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
-f, --failfast Stop on first failure
-c, --catch Catch control-C and display results
-b, --buffer Buffer stdout and stderr during test runs
Examples:
tests.py - run default set of tests
tests.py MyTestSuite - run suite ''MyTestSuite''
tests.py MyTestCase.testSomething - run MyTestCase.testSomething
tests.py MyTestCase - run all ''test*'' test methods
in MyTestCase
Es decir, puedes simplemente hacer
python tests.py TestClass.test_method
Tengo un archivo de prueba que contiene pruebas que llevan bastante tiempo (envían cálculos a un clúster y esperan el resultado). Todos estos están en una clase específica de TestCase.
Como toman tiempo y además no es probable que se rompan, me gustaría poder elegir si este subconjunto de pruebas se ejecuta o no (la mejor manera sería con un argumento de línea de comandos, es decir, " ./tests.py --offline
"o algo así), por lo que podría ejecutar la mayoría de las pruebas a menudo y rápidamente y todo el conjunto de vez en cuando, cuando tenga tiempo.
Por ahora, solo uso unittest.main()
para comenzar las pruebas.
Gracias.
Considera usar un testrunner dedicado, como py.test, nose o posiblemente incluso zope.testing. Todos ellos tienen opciones de línea de comando para seleccionar pruebas.
Busque, por ejemplo, Nose: https://pypi.python.org/pypi/nose/1.3.0
El unittest.main()
predeterminado usa el cargador de prueba predeterminado para hacer que TestSuite salga del módulo en el que se está ejecutando main.
No tiene que usar este comportamiento predeterminado.
Puede, por ejemplo, hacer tres instancias unittest.TestSuite .
El subconjunto "rápido".
fast = TestSuite() fast.addTests( TestFastThis ) fast.addTests( TestFastThat )
El subconjunto "lento".
slow = TestSuite() slow.addTests( TestSlowAnother ) slow.addTests( TestSlowSomeMore )
El conjunto "completo".
alltests = unittest.TestSuite([fast, slow])
Tenga en cuenta que he ajustado los nombres de TestCase para indicar Fast vs. Slow. Puede subclasificar unittest.TestLoader para analizar los nombres de las clases y crear varios cargadores.
Entonces su programa principal puede analizar argumentos de línea de comando con optparse o argparse (disponible desde 2.7 o 3.2) para elegir qué suite desea ejecutar, rápida, lenta o todas.
O bien, puede confiar en que sys.argv[1]
es uno de los tres valores y usar algo tan simple como esto
if __name__ == "__main__":
suite = eval(sys.argv[1]) # Be careful with this line!
unittest.TextTestRunner().run(suite)
En realidad, uno puede pasar los nombres del caso de prueba como sys.argv y solo esos casos serán probados.
Por ejemplo, supongamos que tiene
class TestAccount(unittest.TestCase):
...
class TestCustomer(unittest.TestCase):
...
class TestShipping(unittest.TestCase):
...
account = TestAccount
customer = TestCustomer
shipping = TestShipping
Puedes llamar
python test.py account
tener solo pruebas de cuenta, o incluso
$ python test.py account customer
tener ambos casos probados
Encontré otra solución, basada en cómo funciona el decorador unittest.skip
. Configurando __unittest_skip__
y __unittest_skip_why__
.
Basado en etiquetas
Quería aplicar un sistema de etiquetado para etiquetar algunas pruebas como quick
, slow
, glacier
, memoryhog
, cpuhog
, core
, etc.
A continuación, ejecute all ''quick'' tests
o run everything except ''memoryhog'' tests
, su configuración básica de lista blanca / lista negra
Implementación
Implementé esto en 2 partes:
- Primero agregue etiquetas a las pruebas (a través de un decorador de clases
@testlabel
personalizado) - Custom
unittest.TestRunner
para identificar qué pruebas omitir y modificar el contenido de la lista de prueba antes de ejecutar.
La implementación operativa está en esta esencia: https://gist.github.com/fragmuffin/a245f59bdcd457936c3b51aa2ebb3f6c
(Un ejemplo completamente funcional fue demasiado largo para ponerlo aquí)
El resultado es ...
$ ./runtests.py --blacklist foo
test_foo (test_things.MyTest2) ... ok
test_bar (test_things.MyTest3) ... ok
test_one (test_things.MyTests1) ... skipped ''label exclusion''
test_two (test_things.MyTests1) ... skipped ''label exclusion''
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK (skipped=2)
Todas las pruebas de la clase MyTests1
se omiten porque tienen la etiqueta foo
.
--whitelist
también funciona
Esto es lo único que funcionó para mí.
if __name__ == ''__main__'':
unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))
Cuando lo llamé, tuve que pasar el nombre de la clase y el nombre de la prueba. Un poco inconveniente ya que no tengo la combinación de nombre de clase y prueba memorizada.
python ./tests.py class_Name.test_30311
Al eliminar el nombre de clase y el nombre de prueba, se ejecutan todas las pruebas en su archivo. Encuentro esto MUCHO más fácil de tratar que el método integrado, ya que realmente no cambio mi comando en la CLI. Solo agrega el parámetro.
Disfruta, Keith
Estoy haciendo esto usando un skipIf
simple:
import os
SLOW_TESTS = int(os.getenv(''SLOW_TESTS'', ''0''))
@unittest.skipIf(not SLOW_TESTS, "slow")
class CheckMyFeature(unittest.TestCase):
def runTest(self):
…
De esta manera, solo necesito decorar un caso de prueba ya existente con esta única línea (no es necesario crear suites de prueba o similares, solo esa línea de llamada os.getenv()
al principio del archivo de prueba de mi unidad), y de manera predeterminada esto la prueba se omite.
Si quiero ejecutarlo a pesar de ser lento, simplemente llamo a mi script de esta manera:
SLOW_TESTS=1 python -m unittest …
He encontrado otra manera de seleccionar los métodos test_ * que solo quiero ejecutar agregando un atributo a ellos. Básicamente, utilizas una metaclase para decorar los callables dentro de la clase TestCase que tienen el atributo StepDebug con un decorador unittest.skip. Más información sobre
Saltarse todas las pruebas unitarias menos una en Python usando decoradores y metaclases
No sé si es una solución mejor que las anteriores, solo la estoy ofreciendo como una opción.
Intenté la respuesta de @ slott:
if __name__ == "__main__":
suite = eval(sys.argv[1]) # Be careful with this line!
unittest.TextTestRunner().run(suite)
Pero eso me dio el siguiente error:
Traceback (most recent call last):
File "functional_tests.py", line 178, in <module>
unittest.TextTestRunner().run(suite)
File "/usr/lib/python2.7/unittest/runner.py", line 151, in run
test(result)
File "/usr/lib/python2.7/unittest/case.py", line 188, in __init__
testMethod = getattr(self, methodName)
TypeError: getattr(): attribute name must be string
Lo siguiente funcionó para mí:
if __name__ == "__main__":
test_class = eval(sys.argv[1])
suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
unittest.TextTestRunner().run(suite)
No he encontrado una buena manera de hacer esto antes, así que comparto aquí.
Objetivo: obtener un conjunto de archivos de prueba para que puedan ejecutarse como una unidad, pero aún así podemos seleccionar cualquiera de ellos para que se ejecute solo.
Problema: el método de descubrimiento no permite la fácil selección de un solo caso de prueba para ejecutar.
Diseño: ver abajo. Esto aplana el espacio de nombres para que pueda seleccionar por nombre de clase TestCase, y deje el prefijo "tests1.test_core":
./run-tests TestCore.test_fmap
Código
test_module_names = [
''tests1.test_core'',
''tests2.test_other'',
''tests3.test_foo'',
]
loader = unittest.defaultTestLoader
if args:
alltests = unittest.TestSuite()
for a in args:
for m in test_module_names:
try:
alltests.addTest( loader.loadTestsFromName( m+''.''+a ) )
except AttributeError as e:
continue
else:
alltests = loader.loadTestsFromNames( test_module_names )
runner = unittest.TextTestRunner( verbosity = opt.verbose )
runner.run( alltests )
O puede hacer uso de la función unittest.SkipTest()
. Ejemplo, agregue un método skipOrRunTest
a su clase de prueba de esta manera:
def skipOrRunTest(self,testType):
#testsToRun = ''ALL''
#testsToRun = ''testType1, testType2, testType3, testType4,...etc''
#testsToRun = ''testType1''
#testsToRun = ''testType2''
#testsToRun = ''testType3''
testsToRun = ''testType4''
if ((testsToRun == ''ALL'') or (testType in testsToRun)):
return True
else:
print "SKIPPED TEST because:/n/t testSuite ''" + testType + "'' NOT IN testsToRun[''" + testsToRun + "'']"
self.skipTest("skipppy!!!")
A continuación, agregue una llamada a este método skipOrRunTest al comienzo de cada una de las pruebas de su unidad como esta:
def testType4(self):
self.skipOrRunTest(''testType4'')
Para ejecutar solo una prueba específica, puede usar:
$ python -m unittest test_module.TestClass.test_method
Más información here
Tienes básicamente dos formas de hacerlo:
- Define tu propio conjunto de pruebas para la clase
- Cree clases simuladas de la conexión del clúster que devolverá los datos reales.
Soy un fuerte defensor del segundo enfoque; una prueba unitaria debe probar solo una unidad de código y no sistemas complejos (como bases de datos o clusters). Pero entiendo que no siempre es posible; a veces, crear maquetas es simplemente demasiado caro, o el objetivo de la prueba es realmente el complejo sistema.
Volver a la opción (1), puede continuar de esta manera:
suite = unittest.TestSuite()
suite.addTest(MyUnitTestClass(''quickRunningTest''))
suite.addTest(MyUnitTestClass(''otherTest''))
y luego pasar la suite al corredor de prueba:
unittest.TextTestRunner().run(suite)
Más información sobre la documentación de python: http://docs.python.org/library/unittest.html#testsuite-objects