diff options
Diffstat (limited to 'conftest.py')
-rw-r--r-- | conftest.py | 116 |
1 files changed, 102 insertions, 14 deletions
diff --git a/conftest.py b/conftest.py index faf13804..76e9000a 100644 --- a/conftest.py +++ b/conftest.py @@ -1,24 +1,64 @@ +import os from unittest import mock import pytest +import httpretty as _httpretty -from cloudinit import subp +from cloudinit import helpers, subp -def _closest_marker_args_or(request, marker_name: str, default): - """Get the args for the closest ``marker_name`` or return ``default``""" - try: - marker = request.node.get_closest_marker(marker_name) - except AttributeError: - # Older versions of pytest don't have the new API - marker = request.node.get_marker(marker_name) - if marker is not None: - return marker.args - return default +class _FixtureUtils: + """A namespace for fixture helper functions, used by fixture_utils. + + These helper functions are all defined as staticmethods so they are + effectively functions; they are defined in a class only to give us a + namespace so calling them can look like + ``fixture_utils.fixture_util_function()`` in test code. + """ + + @staticmethod + def closest_marker_args_or(request, marker_name: str, default): + """Get the args for closest ``marker_name`` or return ``default`` + + :param request: + A pytest request, as passed to a fixture. + :param marker_name: + The name of the marker to look for + :param default: + The value to return if ``marker_name`` is not found. + + :return: + The args for the closest ``marker_name`` marker, or ``default`` + if no such marker is found. + """ + try: + marker = request.node.get_closest_marker(marker_name) + except AttributeError: + # Older versions of pytest don't have the new API + marker = request.node.get_marker(marker_name) + if marker is not None: + return marker.args + return default + + @staticmethod + def closest_marker_first_arg_or(request, marker_name: str, default): + """Get the first arg for closest ``marker_name`` or return ``default`` + + This is a convenience wrapper around closest_marker_args_or, see there + for full details. + """ + result = _FixtureUtils.closest_marker_args_or( + request, marker_name, [default] + ) + if not result: + raise TypeError( + "Missing expected argument to {} marker".format(marker_name) + ) + return result[0] @pytest.yield_fixture(autouse=True) -def disable_subp_usage(request): +def disable_subp_usage(request, fixture_utils): """ Across all (pytest) tests, ensure that subp.subp is not invoked. @@ -53,10 +93,14 @@ def disable_subp_usage(request): tests, CiTestCase's allowed_subp does take precedence (and we have TestDisableSubpUsageInTestSubclass to confirm that). """ - allow_subp_for = _closest_marker_args_or(request, "allow_subp_for", None) + allow_subp_for = fixture_utils.closest_marker_args_or( + request, "allow_subp_for", None + ) # Because the mark doesn't take arguments, `allow_all_subp` will be set to # [] if the marker is present, so explicit None checks are required - allow_all_subp = _closest_marker_args_or(request, "allow_all_subp", None) + allow_all_subp = fixture_utils.closest_marker_args_or( + request, "allow_all_subp", None + ) if allow_all_subp is not None and allow_subp_for is None: # Only allow_all_subp specified, don't mock subp.subp @@ -93,3 +137,47 @@ def disable_subp_usage(request): with mock.patch("cloudinit.subp.subp", autospec=True) as m_subp: m_subp.side_effect = side_effect yield + + +@pytest.fixture(scope="session") +def fixture_utils(): + """Return a namespace containing fixture utility functions. + + See :py:class:`_FixtureUtils` for further details.""" + return _FixtureUtils + + +@pytest.yield_fixture +def httpretty(): + """ + Enable HTTPretty for duration of the testcase, resetting before and after. + + This will also ensure allow_net_connect is set to False, and temporarily + unset http_proxy in os.environ if present (to work around + https://github.com/gabrielfalcao/HTTPretty/issues/122). + """ + restore_proxy = os.environ.pop("http_proxy", None) + _httpretty.HTTPretty.allow_net_connect = False + _httpretty.reset() + _httpretty.enable() + + yield _httpretty + + _httpretty.disable() + _httpretty.reset() + if restore_proxy is not None: + os.environ["http_proxy"] = restore_proxy + + +@pytest.fixture +def paths(tmpdir): + """ + Return a helpers.Paths object configured to use a tmpdir. + + (This uses the builtin tmpdir fixture.) + """ + dirs = { + "cloud_dir": tmpdir.mkdir("cloud_dir").strpath, + "run_dir": tmpdir.mkdir("run_dir").strpath, + } + return helpers.Paths(dirs) |