1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import locale
import logging
import os
import re
import pytest
import responses
import tests
import tests.utils
import bugzilla
# pytest plugin adding custom options. Hooks are documented here:
# https://docs.pytest.org/en/latest/writing_plugins.html
def pytest_addoption(parser):
parser.addoption("--ro-integration", action="store_true", default=False,
help="Run readonly tests against local Bugzilla instance.")
parser.addoption("--ro-functional", action="store_true", default=False,
help=("Run readonly functional tests against actual "
"bugzilla instances. This will be very slow."))
parser.addoption("--rw-functional", action="store_true", default=False,
help=("Run read/write functional tests against actual bugzilla "
"instances. As of now this only runs against "
"bugzilla.stage.redhat.com, which requires an RH "
"bugzilla account with cached login creds. This will "
"also be very slow."))
parser.addoption("--redhat-url",
help="Redhat bugzilla URL to use for ro/rw_functional tests")
parser.addoption("--pybz-debug", action="store_true", default=False,
help=("Enable python-bugzilla debug output. This may break "
"output comparison tests."))
parser.addoption("--regenerate-output",
action="store_true", default=False,
help=("Force regeneration of generated test output"))
parser.addoption("--only-rest", action="store_true", default=False)
parser.addoption("--only-xmlrpc", action="store_true", default=False)
def pytest_ignore_collect(collection_path, config):
has_ro = config.getoption("--ro-functional")
has_ro_i = config.getoption("--ro-integration")
has_rw = config.getoption("--rw-functional")
base = os.path.basename(str(collection_path))
is_ro = base == "test_ro_functional.py"
is_ro_i = "tests/integration/ro" in str(collection_path)
is_rw = base == "test_rw_functional.py"
if is_ro_i and not has_ro_i:
return True
if is_ro and not has_ro:
return True
if is_rw and not has_rw:
return True
def pytest_configure(config):
# Needed for test reproducibility on any system not using a UTF-8 locale
locale.setlocale(locale.LC_ALL, "C")
for loc in ["C.UTF-8", "C.utf8", "UTF-8", "en_US.UTF-8"]:
try:
locale.setlocale(locale.LC_CTYPE, loc)
break
except locale.Error:
pass
else:
raise locale.Error("No UTF-8 locale found")
if config.getoption("--redhat-url"):
tests.CLICONFIG.REDHAT_URL = config.getoption("--redhat-url")
if config.getoption("--pybz-debug"):
logging.getLogger(bugzilla.__name__).setLevel(logging.DEBUG)
os.environ["__BUGZILLA_UNITTEST_DEBUG"] = "1"
if config.getoption("--regenerate-output"):
tests.CLICONFIG.REGENERATE_OUTPUT = config.getoption(
"--regenerate-output")
if config.getoption("--only-rest"):
tests.CLICONFIG.ONLY_REST = True
if config.getoption("--only-xmlrpc"):
tests.CLICONFIG.ONLY_XMLRPC = True
if (config.getoption("--ro-functional") or
config.getoption("--rw-functional")):
config.option.verbose = 2
def pytest_generate_tests(metafunc):
"""
If a test requests the 'backends' fixture, run that test with both
force_rest=True and force_xmlrpc=True Bugzilla options
"""
if 'backends' in metafunc.fixturenames:
values = []
ids = []
if not tests.CLICONFIG.ONLY_REST:
values.append({"force_xmlrpc": True})
ids.append("XMLRPC")
if not tests.CLICONFIG.ONLY_XMLRPC:
values.append({"force_rest": True})
ids.append("REST")
metafunc.parametrize("backends", values, ids=ids, scope="session")
@pytest.fixture
def run_cli(capsys, monkeypatch):
"""
Custom pytest fixture to pass a function for testing
a bugzilla cli command.
"""
def _do_run(*args, **kwargs):
return tests.utils.do_run_cli(capsys, monkeypatch, *args, **kwargs)
return _do_run
@pytest.fixture
def mocked_responses():
"""
Mock responses
* Quickly return error responses
* Pass through requests to live instances
* Provide an incorrect XMLRPC response
"""
passthrough = ()
status_pattern = re.compile(r"https://httpstat.us/(?P<status>\d+).*")
def status_callback(request):
match = status_pattern.match(request.url)
status_code = 400
if match:
status_code = int(match.group("status"))
return status_code, {}, "<html><body><h1>Lorem ipsum</h1></body></html>"
test_url = os.getenv("BUGZILLA_URL")
if test_url:
passthrough += (test_url, )
with responses.RequestsMock(passthru_prefixes=passthrough,
assert_all_requests_are_fired=False) as mock:
mock.add_callback(
method=responses.GET,
url=status_pattern,
callback=status_callback
)
mock.add_callback(
method=responses.POST,
url=status_pattern,
callback=status_callback
)
mock.add(
method=responses.POST,
url="https://example.com/#xmlrpc",
status=200,
body="This is no XML"
)
yield mock
|