пространство имен черного списка юниттестов и неудачные попытки ссылаться на него - PullRequest
0 голосов
/ 03 октября 2018

в случае модульного тестирования библиотеки-обертки, тестирование обертки без зависимости / работы с вышестоящей библиотекой является целью;В известном случае все вызовы вышестоящей библиотеки могут быть смоделированы, и это то, что я сделал, но я разочарован изменениями в оболочке, которые вводят больше обращений в вышестоящую библиотеку, пропущенные инструментами mock;

Как я могу лучше всего провалить любой тест, который пытается использовать данное пространство имен?

Моя идея в настоящее время состоит в том, чтобы изменить все методы unittest, чтобы иметь патч обезьяны, такой как

@unittest.mock.patch('wrapper_namespace.upsteam_namespace')

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

  • не нужно добавлять monkeypatch для каждого метода тестирования, хотя этот уровень детализации приемлем;но также не нужно утверждать, что макет никогда не использовался в тестовых методах (или сделать декоратор, чтобы сделать все это либо)
  • запрещает доступ к вышестоящей библиотеке из любой части программного обеспечения (например, Wrapper вызывает B вызовы в восходящем направлении, вызов B в восходящем направлении не может быть перехвачен)

1 Ответ

0 голосов
/ 03 октября 2018

Вам не нужно исправлять каждый метод тестирования.Вы можете легко пропатчить class, если используете unittest, или просто назначить модуль тому, с чем вы хотите пропатчить его.Вот работающий пример:

Ложная библиотека в some_lib.py:

def some_lib_func():
    raise ValueError("I've been called.")

def some_other_lib_func():
    raise ValueError("I've been called.")

class SomeClass:
    def __init__(self):
        raise ValueError("I've been constructed.")

wrapper.py:

import some_lib

def wrapper1():
    some_lib.some_lib_func()

def wrapper2():
    some_lib.some_other_lib_func()

def wrapper3():
    x = some_lib.SomeClass()

test.py:

from unittest.mock import patch, MagicMock
import unittest

import wrapper

# Alternative:                                                                                                                                            
# wrapper.some_lib = MagicMock()                                                                                                                                                                            

# Can patch an entire class                                                                                                                                                                                 
@patch('wrapper.some_lib', MagicMock())
class TestWrapper(unittest.TestCase):
    def test_wrapper1(self):
        wrapper.wrapper1()

    def test_wrapper2(self):
        wrapper.wrapper2()

    def test_wrapper3(self):
        wrapper.wrapper3()

if __name__ == "__main__":
    unittest.main()

Мы бы взорвались, если бы были вызваны функции / классы в some_lib, но это не так:

Matthews-MacBook-Pro:stackoverflow matt$ python test.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

Не стесняйтесь комментировать патч и комментировать в wrapper.some_lib = MagicMock().В этом примере с игрушкой вы получите тот же результат, но между этими двумя подходами есть существенная разница:

При использовании @patch('wrapper.some_lib', MagicMock()) патч только для этого активенКласс тестового примера.

Однако при использовании wrapper.some_lib = MagicMock() этот патч будет действовать в течение по всей длине вашей программы на Python , если только вы не сохраните исходный модуль и не исправите его вручную в какой-то момент.Все, что использует модуль wrapper, получит смоделированную версию.

Так что вы можете сделать что-то вроде:

original_lib = wrapper.some_lib
wrapper.some_lib = MagicMock()
...
# call some test suite, every call to the wrapper module will be mocked out
...
wrapper.some_lib = original_lib
...
# call some other test suite that actually needs the real thing
...

HTH.

РЕДАКТИРОВАТЬ: Немного неправильно прочитал ваш вопрос, но вы можете осмотреть MagicMock объекты, чтобы узнать, были ли они вызваны, и если это так, не пройти тест.Или просто исправьте что-то, что не срабатывает при вызове (вместо MagicMock).Я могу предоставить код для этого по запросу (просто оставьте комментарий), но, надеюсь, вышеописанное поможет вам начать.Я думаю, что суть вопроса была действительно о глобальном исправлении.Ура!

...