'Unit test for pytest_collection_modifyitems python hook
I've implemented a custom logic to the pytest_collection_modifyitems(config, items). Basically it will just filter out some of the items/tests and run the selected ones, based on the given config.getoption parameter.
from unittest import mock
import pytest
from conftest import pytest_collection_modifyitems
def pytest_collection_modifyitems(config, items):
selected_tests = config.getoption("selected_tests", default="")
if selected_tests != "":
tests_to_run = []
for item in items:
marker = item.get_closest_marker("test_case_id")
if marker and marker.args and str(marker.args[0]) in selected_tests:
tests_to_run.append(item)
items[:] = tests_to_run
This is fine and dandy and it does the job. But I want to properly unit test this behavior. I want to see that the items list is updated at the end. I have a working unit test, but I'm interested how to improve the solution. It seems for me that I could have reduced the amount of Mocks somehow. I'm fairly new to python.
# fmt: off
test_data = [
# selected_test_ids available_test_ids expected_test_ids
# valid cases
("123", [123, 456], [123]),
("123, 456", [123, 456, 789], [123, 456]),
# invalid cases
("", [321, 654], [321, 654]), # if there is no selection, run all tests by default
("564", [111, 222], [111, 222]), # if the selection is invalid, run all tests by default
]
# fmt: on
@pytest.mark.parametrize("selected_test_ids, available_test_ids, expected_test_ids", test_data)
def test_pytest_collection_modifyitems(selected_test_ids, available_test_ids, expected_test_ids):
def get_test_case_ids(items):
return [item.get_closest_marker.return_value.args[0] for item in items]
def get_mocked_items():
mocked_items = list()
for test_id in available_test_ids:
# each test has its own marker associated, where the arg[0] attribute holds the value of the test_case_id
mock_marker = mock.Mock()
mock_marker.args = [test_id]
# assign the created mock_marker to the get_closest_marker function
mock_item = mock.Mock()
mock_item.get_closest_marker.return_value = mock_marker
mocked_items.append(mock_item)
return mocked_items
# mock config parameter and set up the "--run_selection" value
mock_config = mock.Mock()
mock_config.getoption.return_value = selected_test_ids
# mock items parameter, which is a list of available tests
mock_items = get_mocked_items()
# Act.
pytest_collection_modifyitems(mock_config, mock_items)
# the pytest_collection_modifyitems updates the mocked items list, so
# we need to extract the test IDs from the updated list
assert get_test_case_ids(mock_items) == expected_test_ids
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
