Как передать аргументы в pytest из командной строки

У меня есть код, и мне нужно передать аргументы, такие как имя из терминала. Вот мой код и как передать аргументы. Я получаю ошибку типа "Файл не найден", которую не понимаю.

Я попробовал команду в терминале: pytest <filename>.py -almondsЯ должен получить имя, напечатанное как "миндаль"

@pytest.mark.parametrize("name")
def print_name(name):
    print ("Displaying name: %s" % name)

10 ответов

В своем тесте pytest не используйте @pytest.mark.parametrize:

@pytest.mark.unit
def test_print_name(name):
    print ("Displaying name: %s" % name)

В conftest.py:

def pytest_addoption(parser):
    parser.addoption("--name", action="store", default="default name")


def pytest_generate_tests(metafunc):
    # This is called for every test. Only get/set command line arguments
    # if the argument is specified in the list of test "fixturenames".
    option_value = metafunc.config.option.name
    if 'name' in metafunc.fixturenames and option_value is not None:
        metafunc.parametrize("name", [option_value])

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

pytest -s tests/my_test_module.py --name abc

Использовать pytest_addoption функция крюка в conftest.py определить новый вариант.
Тогда используйте pytestconfig приспособление в приспособлении самостоятельно, чтобы захватить имя.
Вы также можете использовать pytestconfig от теста, чтобы избежать необходимости писать свой собственный прибор, но я думаю, что вариант с собственным именем немного чище.

# conftest.py

def pytest_addoption(parser):
    parser.addoption("--name", action="store", default="default name")
# test_param.py 

import pytest

@pytest.fixture()
def name(pytestconfig):
    return pytestconfig.getoption("name")

def test_print_name(name):
        print(f"\ncommand line param (name): {name}")

def test_print_name_2(pytestconfig):
    print(f"test_print_name_2(name): {pytestconfig.getoption('name')}")
# in action

$ pytest -q -s --name Brian test_param.py

test_print_name(name): Brian
.test_print_name_2(name): Brian
.

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

# test.py
def test_name(name):
    assert name == 'almond'


# conftest.py
def pytest_addoption(parser):
    parser.addoption("--name", action="store")

@pytest.fixture(scope='session')
def name(request):
    name_value = request.config.option.name
    if name_value is None:
        pytest.skip()
    return name_value

Примеры:

$ py.test tests/test.py
=========================== test session starts ============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/ipetrik/dev/pytest_test, inifile:
collected 1 item

tests/test.py s                                                      [100%]

======================== 1 skipped in 0.06 seconds =========================

$ py.test tests/test.py --name notalmond
=========================== test session starts ============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/ipetrik/dev/pytest_test, inifile:
collected 1 item

tests/test.py F                                                      [100%]

================================= FAILURES =================================
________________________________ test_name _________________________________

name = 'notalmond'

    def test_name(name):
>       assert name == 'almond'
E       AssertionError: assert 'notalmond' == 'almond'
E         - notalmond
E         ? ---
E         + almond

tests/test.py:5: AssertionError
========================= 1 failed in 0.28 seconds =========================

$ py.test tests/test.py --name almond
=========================== test session starts ============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/ipetrik/dev/pytest_test, inifile:
collected 1 item

tests/test.py .                                                      [100%]

========================= 1 passed in 0.03 seconds =========================

Все, что вам нужно сделать, это использовать pytest_addoption() в conftest.py и, наконец, используйте request приспособление:

# conftest.py

from pytest import fixture


def pytest_addoption(parser):
    parser.addoption(
        "--name",
        action="store"
    )

@fixture()
def name(request):
    return request.config.getoption("--name")

И теперь вы можете запустить свой тест

def my_test(name):
    assert name == 'myName'

с помощью:

pytest --name myName

Это немного обходной путь, но он получит параметры в тест. В зависимости от требований, этого может быть достаточно.

      def print_name():
    import os
    print(os.environ['FILENAME'])
    pass

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

      FILENAME=/home/username/decoded.txt python3 setup.py test --addopts "-svk print_name"

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

# content of test_sample.py
def test_answer(cmdopt):
    if cmdopt == "type1":
        print("first")
    elif cmdopt == "type2":
        print("second")
    assert 0  # to see what was printed

For this to work we need to add a command line option and provide the cmdopt through a fixture function:

# content of conftest.py
import pytest


def pytest_addoption(parser):
    parser.addoption(
        "--cmdopt", action="store", default="type1", help="my option: type1 or type2"
    )


@pytest.fixture
def cmdopt(request):
    return request.config.getoption("--cmdopt")

ref: https://docs.pytest.org/en/latest/example/simple.html

Тогда вы можете позвонить с помощью:

pytest --cmdopt type1

Согласно официальному документу, маркировка декоратора должна выглядеть следующим образом.

@pytest.mark.parametrize("arg1", ["Stackru"])
def test_mark_arg1(arg1):
    assert arg1 == "Stackru" #Success
    assert arg1 == "ServerFault" #Failed

Бежать

python -m pytest <filename>.py
  • Примечание 1: имя функции должно начинаться с test_
  • Примечание 2: Pytest будет перенаправлять stdout (print)Таким образом, прямой запуск stdout не сможет показать какой-либо результат на экране. Кроме того, нет необходимости печатать результат в вашей функции в тестовых случаях.
  • Примечание 3: pytest - это модуль, работающий на python, который не может получить sys.argv напрямую

Если вы действительно хотите получить внешние настраиваемые аргументы, вы должны реализовать это внутри своего скрипта. (Например, загрузка содержимого файла)

with open("arguments.txt") as f:
    args = f.read().splitlines()
...
@pytest.mark.parametrize("arg1", args)
...

Удалось заставить это работать с классом unittest.TestCaseиспользуя ответы здесь и https://docs.pytest.org/en/6.2.x/unittest.html

conftest.py :

      import pytest

my_params = {
    "name": "MyName",
    "foo": "Bar",
}


def pytest_addoption(parser):
    for my_param_name, my_param_default in my_params.items():
        parser.addoption(f"--{my_param_name}", action="store", default=my_param_default)


@pytest.fixture()
def pass_parameters(request):
    for my_param in my_params:
        setattr(request.cls, my_param, request.config.getoption(f"--{my_param}"))

test_param.py

      import unittest
import pytest


@pytest.mark.usefixtures("pass_parameters")
class TestParam(unittest.TestCase):
    def test_it(self):
        self.assertEqual(self.name, "MyName")

с использованием:

      pytest --name MyName

Я много читал об этом, и я был действительно сбит с толку. Я наконец понял это, и вот что я сделал:

Сначала создайте имя файла:conftest.pyВторой Добавьте к нему следующий код:

      # this is a function to add new parameters to pytest
def pytest_addoption(parser):
    parser.addoption(
        "--MyParamName", action="store", default="defaultParam", help="This is a help section for the new param you are creating"
    )
# this method here makes your configuration global
option = None
def pytest_configure(config):
    global option
    option = config.option

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

      @pytest.fixture
def myParam(request):
    return request.config.getoption('--MyParamName')

Вот как вы будете использовать новый параметр create, передаваемый при выполнении pytest.

      # command to run pytest with newly created param
$ pytest --MyParamName=myParamValue

Место, где будет использоваться новая фикстура param: Пример теста python, в котором будет использоваться param:

      Test_MyFucntion(myParam)

Если вы привыкли к argparse, вы можете подготовить его обычным способом на arparse

import argparse
import sys

DEFAULT_HOST = test99
#### for --host parameter ###
def pytest_addoption(parser):
    parser.addoption("--host")   # needed otherwhise --host will fail pytest

parser = argparse.ArgumentParser(description="run test on --host")
parser.add_argument('--host', help='host to run tests on (default: %(default)s)', default=DEFAULT_HOST)
args, notknownargs = parser.parse_known_args()
if notknownargs:
    print("pytest arguments? : {}".format(notknownargs))
sys.argv[1:] = notknownargs

#
then args.hosts holds you variable, while sys.args is parsed furhter with pytest.
Другие вопросы по тегам