как передать аргумент командной строки из pytest в код - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь передать аргументы из тестового сценария pytest в тестируемый модуль. Например, используя main.py из Python шаблонов , я могу запустить его из командной строки как:

$ python3 main.py
usage: main.py [-h] [-f] [-n NAME] [-v] [--version] arg
main.py: error: the following arguments are required: arg
$ python3 main.py xx
hello world
Namespace(arg='xx', flag=False, name=None, verbose=0)

Теперь я пытаюсь сделать то же самое с pytest, со следующим test_sample.py

( ПРИМЕЧАНИЕ: main.py требует аргументов командной строки. Но эти аргументы должны быть жестко заданы в конкретном тесте, они не должны быть аргументами командной строки для pytest. Тестовый сценарий pytest должен только отправлять эти значения в качестве аргументов командной строки для main.main ().)

import main
def test_case01():
    main.main()
    # I dont know how to pass 'xx' to main.py,
    # so for now I just have one test with no arguments

и запуск теста как:

pytest -vs test_sample.py

Это не происходит с сообщениями об ошибках. Я пытался найти другие ответы для решения, но не мог их использовать. Например, 42778124 предлагает создать отдельный файл run.py, что нежелательно. И 48359957 и 40880259 , похоже, имеют дело больше с аргументами командной строки для pytest, вместо передачи аргументов командной строки в основной код.

Мне не нужен pytest для получения аргументов командной строки, аргументы могут быть жестко закодированы в определенном тесте. Но эти аргументы должны быть переданы в качестве аргументов в основной код. Можете ли вы дать мне test_sample.py, который вызывает main.main () с некоторыми аргументами?

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Если вы не можете изменить сигнатуру метода main, вы можете использовать метод monkeypatching , чтобы временно заменить аргументы тестовыми данными. Пример: представьте, что пишете тесты для следующей программы:

import argparse


def main():
    parser = argparse.ArgumentParser(description='Greeter')
    parser.add_argument('name')
    args = parser.parse_args()
    return f'hello {args.name}'


if __name__ == '__main__':
    print(main())

При запуске из командной строки:

$ python greeter.py world
hello world

Для проверки функции main с некоторыми пользовательскими данными, monkeypatch sys.argv:

import sys
import greeter

def test_greeter(monkeypatch):
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['greeter', 'spam'])
        assert greeter.main() == 'hello spam'

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

import sys
import pytest
import greeter

@pytest.mark.parametrize('name', ['spam', 'eggs', 'bacon'])
def test_greeter(monkeypatch, name):
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['greeter', name])
        assert greeter.main() == 'hello ' + name

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

$ pytest -v test_greeter.py

...

test_greeter.py::test_greeter[spam] PASSED
test_greeter.py::test_greeter[eggs] PASSED
test_greeter.py::test_greeter[bacon] PASSED
0 голосов
/ 07 января 2019

Хорошей практикой может быть использование такого рода кода вместо чтения аргументов из метода main.

# main.py
def main(arg1):
    return arg1

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='My awesome script')
    parser.add_argument('word', help='a word')
    args = parser.parse_args()
    main(args.word)

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

import main
def test_case01():
    main.main(your_hardcoded_arg)

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

...