Как передать аргументы в 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.