нос носа - с дополнительным тестом - PullRequest
0 голосов
/ 26 октября 2019

Мне нужно отложить импорт некоторых библиотек, если они не нужны, поэтому я создал объект для отсрочки импорта.

class Importer(object):
    def __init__(self, name):
        self.name = name

    def __bool__(self):
        try:
            mod = importlib.import_module(self.name)
            return True
        except ImportError:
            return False

    def __getattr__(self, name):
        try:
            mod = importlib.import_module(self.name)
            attr = getattr(mod, name)
            setattr(self, name, attr)
            return attr
        except ImportError as e:
            msg = self.name + " must be installed"
            raise ImportError(msg)

Я запустил nose с моими тестами, и все прошло,Однако, когда я запускаю --with-doctest, он запускает дополнительный тест (который я не определил), который генерирует ошибку в любой среде, где данная библиотека не установлена.

Тестирование кода ниже воссоздает проблему Iиспытываю. В среде без numpy, nosetests --with-doctest выполняет второй тест, который я не определил.

numpy = Importer('numpy')

def mean(array):
    """
    Mean of an array.

    Examples
    --------
    >>> mean([1, 2, 3])
    2.0
    >>> mean([1, -1])
    0.0
    """
    if numpy:
        return numpy.mean(array)
    return float(sum(array) / len(array))

Ясно, что для тестирования доступен только один тест. Также, если установлена ​​numpy, выполняется только 1 проверка. Так почему же тогда, когда numpy не установлен, я получаю второй тест? Вот вывод.

.E
======================================================================
ERROR: Failure: ImportError (numpy must be installed)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/devin/Dropbox/Devin_S_+_Spark_Wave/nimble/zissue/issue.py", line 16, in __getattr__
    mod = importlib.import_module(self.name)
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'numpy'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/site-packages/nose/failure.py", line 39, in runTest
    raise self.exc_val.with_traceback(self.tb)
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/site-packages/nose/plugins/manager.py", line 154, in generate
    for r in result:
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/site-packages/nose/plugins/doctests.py", line 228, in loadTestsFromModule
    tests = self.finder.find(module)
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/doctest.py", line 933, in find
    self._find(tests, obj, name, module, source_lines, globs, {})
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/doctest.py", line 992, in _find
    if ((inspect.isroutine(inspect.unwrap(val))
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/inspect.py", line 512, in unwrap
    while _is_wrapper(func):
  File "/Users/devin/anaconda3/envs/issueEnv/lib/python3.6/inspect.py", line 503, in _is_wrapper
    return hasattr(f, '__wrapped__')
  File "/Users/devin/Dropbox/testing/issue/issue.py", line 22, in __getattr__
    raise ImportError(msg)
ImportError: numpy must be installed

----------------------------------------------------------------------
Ran 2 tests in 0.003s

1 Ответ

0 голосов
/ 26 октября 2019

Что ж, это весело!

Основная сложность заключается в том, что модуль doctest обманом заставил вас попытаться выполнить импровизированный импорт. То есть он исследовал на numpy.__wrapped__, и вы взяли наживку. Необходимо различать пробный вызов, для которого допустимо возвращение фиктивного значения, и реальный вызов, для которого вы должны импортировать или повысить.

Возможно, достаточно эвристики тестирования для __wrapped__. Но вы можете счесть необходимым проверить стек вызовов, чтобы найти вызывающего, заметить, что это, например, autodoc, и изменить поведение на его основе.

...