Исправить метод из модуля, импортированного в тестируемый метод - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь написать модульный тест (или назовите его интеграционным тестом, если хотите) для моего основного модуля и main() метода.

Это выглядит так:

# main.py in mymodule
# some imports...

def main() -> None:
    # args is a result of argparse parsing
    try:
        if args.type == 'a':
            from mymodule import a
            a.run()
        elif args.type == 'b'
            from mymodule import b
            b.run()
        # elif ...
        else:
            raise RuntimeError('Unknown type ' + args.type)
    except (RuntimeError, FileNotFoundError, ...) as e:
        # some logging
        sys.exit(1)

    # some other logging

Я попытался смоделировать / исправить модули следующим образом:

def dummy_run():
    # just do nothing here

def test_main_a(self):
    import mymodule.a
    mymodule.a.run = dummy_run
    os.system('python3 mymodule.main a')

и

def test_main_a(self):
    # patch is imported as from unittest.mock import patch
    with patch('mymodule.a.run', return_value=None):
        os.system('python3 mymodule.main a')

и

def test_main_a(self):
    # patch is imported as from unittest.mock import patch
    with patch('mymodule.a.run') as run_mocked:
        run_mocked.return_value = None
        os.system('python3 mymodule.main a')

и

@patch('mymodule.a.run')
def test_main_a(self, a_mock):
    a_mock.return_value = None
    os.system('python3 mymodule.main a')

Но все эти способы не допускают насмешки / исправления метода mymodule.a.run, заканчивающегося реальным вызванным методом.

Когда я пытался пропатчить mymodule.main.a.run или mymodule.main.mymodule.a.run, я получил только ModuleNotFoundError с. Я попробовал эти цели после прочтения Где патчить часть.

Честно говоря, я не совсем понимаю, где проблема с исправлениями, так как я исправляю исправления до того, как импортируется модуль mymodule.a и вызывается его run() (как это происходит только после os.system('...') участия в тесте) , Любая помощь высоко ценится!

1 Ответ

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

Патчирование и макетирование работают только в одном и том же интерпретаторе, но ваш вызов os.system('python [...]') запускает функцию main в новом интерпретаторе. Вместо этого вы, вероятно, хотите вызвать функцию main напрямую. Это может включать исправление некоторых sys объектов, таких как sys.exit и sys.argv.

Однако обычной практикой является предоставление необязательного аргумента args для функции main:

def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('type')
    namespace = parser.parse_args(args)
    if namespace.type == 'a':
        from mymodule import a
        a.run()
    sys.exit()

Таким образом, можно легко ввести и проверить аргументы командной строки:

def test_main_a():
    with patch('mymodule.a.run') as run_mocked:
        main(['a'])

Кроме того, контекст pytest.raises может использоваться для управления вызовом на sys.exit:

def test_main_a():
    with patch('mymodule.a.run') as run_mocked:
        with pytest.raises(SystemExit):
            main(['a'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...