|
| 1 | +""" Lockable plugin for pytest """ |
| 2 | +import json |
| 3 | +import socket |
| 4 | +import tempfile |
| 5 | +from contextlib import contextmanager |
| 6 | +import pytest |
| 7 | +from lockable import parse_requirements, get_requirements, read_resources_list, lock |
| 8 | + |
| 9 | + |
| 10 | +def pytest_addoption(parser): |
| 11 | + """ |
| 12 | + register argparse-style options and ini-style config values, |
| 13 | + called once at the beginning of a test run |
| 14 | + """ |
| 15 | + group = parser.getgroup("lockable") |
| 16 | + group.addoption("--allocation_hostname", default=socket.gethostname(), help="Allocation host") |
| 17 | + group.addoption("--allocation_requirements", default=None, help="Resource requirements to be allocate") |
| 18 | + group.addoption("--allocation_timeout", default=10, help="Allocation timeout") |
| 19 | + group.addoption("--allocation_resource_list_file", default='resources.json', help="Available resorces list") |
| 20 | + group.addoption("--allocation_lock_folder", default=tempfile.gettempdir(), help="Allocation lockfiles folder") |
| 21 | + |
| 22 | + |
| 23 | +@pytest.fixture(scope="session", autouse=True) |
| 24 | +def lockable(pytestconfig, record_testsuite_property): |
| 25 | + """ |
| 26 | + pytest fixture that yields function for allocate any resource |
| 27 | + .. code-block:: python |
| 28 | + def test_foo(lockable_allocate): |
| 29 | + with lockable({my: "resource}) as resource: |
| 30 | + print(resource) |
| 31 | + """ |
| 32 | + resource_list = read_resources_list(pytestconfig.getoption('allocation_resource_list_file')) |
| 33 | + timeout_s = pytestconfig.getoption('allocation_timeout') |
| 34 | + lock_folder = pytestconfig.getoption('allocation_lock_folder') |
| 35 | + |
| 36 | + @contextmanager |
| 37 | + def _lock(requirements, prefix='resource'): |
| 38 | + nonlocal resource_list, timeout_s, lock_folder |
| 39 | + requirements = parse_requirements(requirements) |
| 40 | + predicate = get_requirements(requirements, pytestconfig.getoption('allocation_hostname')) |
| 41 | + print(f"Use lock folder: {lock_folder}") |
| 42 | + print(f"Requirements: {json.dumps(predicate)}") |
| 43 | + print(f"Resource list: {json.dumps(resource_list)}") |
| 44 | + with lock(predicate, resource_list, timeout_s, lock_folder) as resource: |
| 45 | + for key, value in resource.items(): |
| 46 | + record_testsuite_property(f'resource_{key}', value) |
| 47 | + if pytestconfig.pluginmanager.hasplugin('metadata'): |
| 48 | + # pylint: disable=protected-access |
| 49 | + pytestconfig._metadata[f'{prefix}_{key}'] = value |
| 50 | + yield resource |
| 51 | + |
| 52 | + yield _lock |
| 53 | + |
| 54 | + |
| 55 | +@pytest.fixture(scope="session", autouse=True) |
| 56 | +def lockable_resource(pytestconfig, lockable): # pylint: disable=redefined-outer-name |
| 57 | + """ |
| 58 | + pytest fixture that lock suitable resource and yield it |
| 59 | + .. code-block:: python |
| 60 | + def test_foo(lockable_resource): |
| 61 | + print(f'Testing with resource: {lockable_resource}') |
| 62 | + """ |
| 63 | + requirements = pytestconfig.getoption('allocation_requirements') |
| 64 | + with lockable(requirements) as resource: |
| 65 | + yield resource |
0 commit comments