Параметризовать тест на основе списка тестовых данных из файла json - PullRequest
0 голосов
/ 12 июня 2018

Есть ли способ параметризации теста, когда у теста есть список разных / нескольких тестовых данных?

example_test_data.json

{ "test_one" : [1,2,3], # this is the case, where the `test_one` test need to be parametrize.
  "test_two" : "split",
  "test_three" : {"three":3},
  "test_four" : {"four":4},
  "test_set_comparison" : "1234"
}

Структура каталогов:

  • main -
    • conftest.py # файл conftest для моих приборов
    • testcases
      • project_1 (содержит эти файлы - test_suite_1.py, config.json)
      • project_2 (содержит эти файлы - test_suite_2.py, config.json)
    • рабочие процессы
      • libs

Используя приведенный ниже код в conftest.py на верхнем уровне каталога, можно получить / отобразить данные теста из файла json для конкретного теста.

@pytest.yield_fixture(scope="class", autouse=True)
def test_config(request):
  f = pathlib.Path(request.node.fspath.strpath)
  print "File : %s" % f
  config = f.with_name("config.json")
  print "Config json file : %s" % config
  with config.open() as fd:
    testdata = json.loads(fd.read())
  print "test data :", testdata
  yield testdata


@pytest.yield_fixture(scope="function", autouse=True)
def config_data(request, test_config):
  testdata = test_config
  test = request.function.__name__
  print "Class Name : %s" % request.cls.__name__
  print "Testcase Name : %s" % test
  if test in testdata:
    test_args = testdata[test]
    yield test_args
  else:
    yield {} 

В моем случае:

@pytest.yield_fixture(scope="function", autouse=True)
def config_data(request, test_config):
  testdata = test_config
  test = request.function.__name__
  print "Class Name : %s" % request.cls.__name__
  print "Testcase Name : %s" % test
  if test in testdata:
    test_args = testdata[test]
    if isinstance(test_args, list):
       # How to parametrize the test 
       # yield test_args
  else:
    yield {} 

1 Ответ

0 голосов
/ 12 июня 2018

Я бы обработал специальный случай параметризации в pytest_generate_tests hook:

# conftest.py
import json
import pathlib
import pytest


@pytest.fixture(scope="class")
def test_config(request):
    f = pathlib.Path(request.node.fspath.strpath)
    config = f.with_name("config.json")
    with config.open() as fd:
        testdata = json.loads(fd.read())
    yield testdata


@pytest.fixture(scope="function")
def config_data(request, test_config):
    testdata = test_config
    test = request.function.__name__
    if test in testdata:
        test_args = testdata[test]
        yield test_args
    else:
        yield {}


def pytest_generate_tests(metafunc):
    if 'config_data' not in metafunc.fixturenames:
        return
    config = pathlib.Path(metafunc.module.__file__).with_name('config.json')
    testdata = json.loads(config.read_text())
    param = testdata.get(metafunc.function.__name__, None)
    if isinstance(param, list):
        metafunc.parametrize('config_data', param)

Некоторые примечания: yield_fixture устарел , поэтому я заменил его на обычный fixture.Кроме того, вам не нужно autouse=True в приборах, которые возвращают значения - вы все равно их вызываете.

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

# testcases/project_1/config.json
{
    "test_one": [1, 2, 3],
    "test_two": "split"
}

# testcases/project_1/test_suite_1.py
def test_one(config_data):
    assert config_data >= 0

def test_two(config_data):
    assert config_data == 'split'


# testcases/project_2/config.json
{
    "test_three": {"three": 3},
    "test_four": {"four": 4}
}

# testcases/project_2/test_suite_2.py
def test_three(config_data):
    assert config_data['three'] == 3

def test_four(config_data):
    assert config_data['four'] == 4

Запуск тестов дает:

$ pytest -vs
============================== test session starts ================================
platform linux -- Python 3.6.5, pytest-3.4.1, py-1.5.3, pluggy-0.6.0 --
/data/gentoo64/usr/bin/python3.6
cachedir: .pytest_cache
rootdir: /data/gentoo64/home/u0_a82/projects/stackoverflow/so-50815777, inifile:
plugins: mock-1.6.3, cov-2.5.1
collected 6 items

testcases/project_1/test_suite_1.py::test_one[1] PASSED
testcases/project_1/test_suite_1.py::test_one[2] PASSED
testcases/project_1/test_suite_1.py::test_one[3] PASSED
testcases/project_1/test_suite_1.py::test_two PASSED
testcases/project_2/test_suite_2.py::test_three PASSED
testcases/project_2/test_suite_2.py::test_four PASSED

============================ 6 passed in 0.12 seconds =============================
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...