Тест setuptools скрывает ошибки импорта. Как получить лучшую информацию? - PullRequest
7 голосов
/ 30 ноября 2009

В python setuptools тест python setup.py запускает тестовый набор. Однако, если у меня есть ошибка импорта в моем тестовом комплекте, единственное сообщение об ошибке, которое я получаю, - это AttributeError, сообщающий, что мой тестовый класс отсутствует. Есть ли способ получить более подробное сообщение об ошибке, чтобы я мог исправить тестовый набор?

Я объясню лучше на следующем примере. Предположим, у меня есть пакет под названием foo, созданный заново с помощью paster. Я тогда добавляю тест

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

Теперь предположим, что mytest.py содержит следующий код

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

Это работает. Однако, если я пытаюсь импортировать несуществующий модуль

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

Это ошибка, которую я получаю

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'

Другими словами, нет ссылки на неудачный импорт.

Ответы [ 4 ]

3 голосов
/ 01 марта 2012

Используйте нос . Никаких изменений в вашем коде не требуется. Просто сделай:

$ pip install nose
$ nosetests

Если есть ошибка ImportError, вы увидите ее:

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
1 голос
/ 30 ноября 2009

Проблема в том, что первый аргумент __import__() должен быть модулем. Когда вам нужно добраться до какого-либо объекта с точечным именем, вы никогда не знаете, какая часть является модулем, а какая нет. Один из способов получить объект module.subname - сначала попытаться импортировать его как подмодуль, а в случае неудачи использовать getattr(module, subname), как это делает unittest. Иногда это даст вам AttributeError вместо ImportError. Другой способ сделать это - сначала попробовать getattr(module, subname) и только в случае неудачи попробовать импортировать. Этот способ не лучше: иногда он дает ImportError, когда более подходящим будет AttributeError.

Вероятно, лучшее, что может unittest сделать в этом случае, - это вызвать собственное исключение, сообщающее, что импорт и поиск атрибутов не пройдены. Попробуйте отправить отчет об ошибке для этой проблемы.

0 голосов
/ 29 января 2010

Проблема здесь в том, что Python ImportError не сообщает вам, в каком модуле действительно произошла ошибка, если вы не внимательно осмотрите трассировку - чего не делает модуль unittest. У вас будет такая же проблема с модулем unittest, независимо от того, какой инструмент вы используете для его запуска.

Возможно, вы захотите попробовать пакет "nose" - в нем есть плагин setuptools, так что вы можете добавить его в файл setup.py и позволить ему находить и импортировать ваши тесты вместо использования поиска по умолчанию в setuptools Если я правильно помню, он загружает тестовый код не так, как это делает unittest, и в этом случае он может дать лучшее сообщение об ошибке. И даже если этого не произойдет, было бы легче добавить его в нос, чем в unittest!

0 голосов
/ 30 ноября 2009

Вы также можете попробовать свой код с помощью Distribute (ветвь setuptools, поскольку setuptools не очень активно поддерживается). Я не знаю, будет ли это что-то другое, но стоит попробовать.

...