Source code for stepler.third_party.idempotent_id
"""
------------------------------------------------------------
Pytest plugin to add mark `@pytest.mark.idempotent_id(<id>)`
------------------------------------------------------------
"""
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function
from collections import defaultdict
import pytest
# TODO(schipiga): This plugin should be refactored
[docs]def pytest_addoption(parser):
"""Add option to pytest."""
parser.addoption("--check-idempotent_id", action="store_true",
help="Check that all tests has uniq idempotent_id marker")
[docs]def get_item_id(item):
"""Return item (test) idempotent id."""
test_id = None
markers = item.get_marker('idempotent_id') or []
for marker in markers:
test_id = marker.args[0]
params = marker.kwargs.get('params', marker.kwargs)
if len(params) > 0:
if not hasattr(item, 'callspec'):
raise Exception("idempotent_id decorator with filter "
"parameters requires parametrizing "
"of test method")
params_in_callspec = all(param in item.callspec.params.items()
for param in params.items())
if not params_in_callspec:
continue
break
return test_id
@pytest.hookimpl(tryfirst=True)
[docs]def pytest_collection_modifyitems(session, items):
"""Add marker to test name, if test marked with `idempotent_id` marker.
If optional kwargs passed - test parameters should be a
superset of this kwargs to mark be applied.
Also kwargs can be passed as `params` argument.
"""
ids = defaultdict(list)
for item in items:
test_id = get_item_id(item)
ids[test_id].append(item)
if test_id is not None:
item.name += '[id-{}]'.format(test_id)
if session.config.option.check_idempotent_id:
errors = []
without_id = ids.pop(None, [])
if without_id:
errors += ["Tests without idempotent_id:"]
errors += [' ' + x.nodeid for x in without_id]
for test_id, items in ids.items():
if len(items) > 1:
errors += ["Single idempotent_id for many cases:"]
errors += [' ' + x.nodeid for x in items]
if errors:
print('')
print('\n'.join(errors))
pytest.exit('Errors with idempotent_id')
[docs]def pytest_runtestloop(session):
"""Check idempotent id presence."""
if session.config.option.check_idempotent_id:
return True