2009-11-30 2 views
7

En las herramientas de configuración de python, la prueba de python setup.py ejecuta el conjunto de pruebas. Sin embargo, si tengo un error de importación en mi suite de pruebas, el único mensaje de error que obtengo es un AttributeError quejándose de que falta mi clase de prueba. ¿Hay alguna manera de obtener un mensaje de error más detallado, para que pueda reparar la suite de pruebas?prueba de instalación oculta errores de importación. ¿Cómo tener mejor información?

Me explicaré mejor con el siguiente ejemplo. Supongamos que tengo un paquete llamado foo, creado de nuevo con paster. Luego agregar la prueba

./foo 
./foo/__init__.py 
./foo/tests 
./foo/tests/__init__.py 
./foo/tests/mytest.py 
./setup.cfg 
./setup.py 

Ahora, supongamos que mytest.py contiene el siguiente código

import unittest 
class MyTestClass(unittest.TestCase): 
    def testFoo(self): 
     self.assertEqual(1,1) 

Esto funciona. Sin embargo, si intento importar un módulo unexistent

import unittest 
import frombiz 
class MyTestClass(unittest.TestCase): 
    def testFoo(self): 
     self.assertEqual(1,1) 

Este es el error que obtengo

Traceback (most recent call last): 
    File "setup.py", line 26, in <module> 
    test_suite = "foo.tests" 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/distutils/core.py", line 152, in setup 
    dist.run_commands() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/distutils/dist.py", line 975, in run_commands 
    self.run_command(cmd) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/distutils/dist.py", line 995, in run_command 
    cmd_obj.run() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/setuptools/command/test.py", line 121, in run 
    self.with_project_on_sys_path(self.run_tests) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/setuptools/command/test.py", line 101, in with_project_on_sys_path 
    func() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/setuptools/command/test.py", line 130, in run_tests 
    testLoader = loader_class() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 816, in __init__ 
    self.parseArgs(argv) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 843, in parseArgs 
    self.createTests() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 849, in createTests 
    self.module) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 613, in loadTestsFromNames 
    suites = [self.loadTestsFromName(name, module) for name in names] 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 587, in loadTestsFromName 
    return self.loadTestsFromModule(obj) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/setuptools/command/test.py", line 34, in loadTestsFromModule 
    tests.append(self.loadTestsFromName(submodule)) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 584, in loadTestsFromName 
    parent, obj = obj, getattr(obj, part) 
AttributeError: 'module' object has no attribute 'mytest' 

En otras palabras, no hay ninguna referencia a la importación fallado.

+1

Mi conjetura es que no hay manera de conseguir lo que quiere sin cambiar el código fuente de setuptool. – codeape

+0

@codeape - y buena suerte con eso.:-) –

Respuesta

1

El problema es que el primer argumento de __import__() debe ser módulo. Cuando necesita llegar a un objeto con un nombre punteado, nunca se sabe qué parte es el módulo y qué no. La única manera de conseguir module.subname objeto es tratar de importación como submódulo primero y cuando no utilice getattr(module, subname), como unittest hace. Esto a veces le dará AttributeError en lugar de ImportError. Otra forma de hacerlo es probar primero el getattr(module, subname) y solo cuando lo intente, intente importarlo. De esta manera no es mejor: a veces le dará ImportError cuando sea más apropiado sería AttributeError.

Probablemente la mejor unittest puede hacer en este caso es para elevar su propia excepción diciendo que tanto la importación y atribuir fallaron las operaciones de búsqueda. Intenta enviar un informe de errores para este problema.

+1

¿Se ha registrado un informe de error? –

0

Es posible que también desee probar su código con Distribute (una bifurcación de setuptools ya que las herramientas de configuración no se están manteniendo de forma muy activa). No sé si hará algo diferente, pero vale la pena intentarlo.

+0

distribuir 0.6.24 tiene el mismo problema. –

0

El problema aquí es que un ImportError Python no le dice lo que el módulo del error de hecho se produjo en, a menos que inspeccione cuidadosamente el rastreo - la cual el módulo unittest no hace. Tendrá el mismo problema con el módulo unittest, independientemente de la herramienta que utilice para ejecutarlo.

Es posible que desee probar el paquete de "nariz" - tiene un plugin setuptools, por lo que puede añadirlo a su setup.py y se deja encontrar e importar las pruebas, en lugar de utilizar el buscador de prueba predeterminado setuptools'. Si recuerdo correctamente, carga el código de prueba de una manera diferente a la que hace unittest, y es posible que pueda dar un mejor mensaje de error en este caso. ¡Y aunque no lo haga, probablemente sería más fácil agregarlo a la nariz que a la prueba unitaria!

3

Uso nose. No es necesario modificar su código. Acaba de hacer:

$ pip install nose 
$ nosetests 

Si hay un ImportError, verá que:

ERROR: Failure: ImportError (cannot import name MyModel) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/home/garyvdm/bwreport/ve/lib/python3.2/site-packages/nose/failure.py", line 37, in runTest 
    raise self.exc_class(self.exc_val).with_traceback(self.tb) 
    File "/home/garyvdm/bwreport/ve/lib/python3.2/site-packages/nose/loader.py", line 390, in loadTestsFromName 
    addr.filename, addr.module) 
    File "/home/garyvdm/bwreport/ve/lib/python3.2/site-packages/nose/importer.py", line 39, in importFromPath 
    return self.importFromDir(dir_path, fqname) 
    File "/home/garyvdm/bwreport/ve/lib/python3.2/site-packages/nose/importer.py", line 86, in importFromDir 
    mod = load_module(part_fqname, fh, filename, desc) 
    File "/home/garyvdm/bwreport/bwreport/daemon/__init__.py", line 11, in <module> 
    from bwreport.models import (
ImportError: cannot import name MyModel 
+0

La versión Python3 de la nariz me dio un error explícito acerca de los problemas de importación en lugar de AttributeError vago como en la pregunta original. ¡Bonito! – mlt

+1

Debe ser 'nosetests' – dvim

+0

@Martynas editado – Aliostad

Cuestiones relacionadas