1 # This file initializes the py.test environment
4 # TODO: Can we somehow push some of the registrations below to the subdirectories?
5 pytest
.register_assert_rewrite(
7 "unit.checks.checktestlib", #
8 "unit.checks.generictests.run", #
9 "unit.cmk.gui.old.html_tests", #
12 import _pytest
.monkeypatch
24 # Each test is of one of the following types.
26 # The tests are marked using the marker pytest.marker.type("TYPE")
27 # which is added to the test automatically according to their location.
29 # With each call to py.test one type of tests needs to be selected using
30 # the "-T TYPE" option. Only these tests will then be executed. Tests of
31 # the other type will be skipped.
34 EXECUTE_IN_SITE
, EXECUTE_IN_VENV
= True, False
36 test_types
= collections
.OrderedDict([
37 ("unit", EXECUTE_IN_VENV
),
38 ("pylint", EXECUTE_IN_VENV
),
39 ("docker", EXECUTE_IN_VENV
),
40 ("integration", EXECUTE_IN_SITE
),
41 ("gui_crawl", EXECUTE_IN_SITE
),
42 ("packaging", EXECUTE_IN_VENV
),
46 def pytest_addoption(parser
):
47 """Register the -T option to pytest"""
48 options
= [name
for opt
in parser
._anonymous
.options
for name
in opt
.names()]
49 # conftest.py is symlinked from enterprise/tests/conftest.py which makes it being executed
50 # twice. Only register this option once.
59 help="Run tests of the given TYPE. Available types are: %s" % ", ".join(test_types
.keys()))
62 def pytest_configure(config
):
63 """Register the type marker to pytest"""
64 config
.addinivalue_line(
65 "markers", "type(TYPE): Mark TYPE of test. Available: %s" % ", ".join(test_types
.keys()))
68 def pytest_collection_modifyitems(items
):
69 """Mark collected test types based on their location"""
71 type_marker
= item
.get_closest_marker("type")
72 if type_marker
and type_marker
.args
:
73 continue # Do not modify manually set marks
75 file_path
= "%s" % item
.reportinfo()[0]
76 if "tests/unit" in file_path
:
78 elif "tests/git" in file_path
:
80 elif "tests/packaging" in file_path
:
82 elif "tests/pylint" in file_path
:
84 elif "tests/docker" in file_path
:
86 elif "tests/integration" in file_path
:
89 raise Exception("Test not TYPE marked: %r" % item
)
91 item
.add_marker(pytest
.mark
.type.with_args(ty
))
94 def pytest_runtest_setup(item
):
95 """Skip tests of unwanted types"""
96 testlib
.skip_unwanted_test_types(item
)
99 # Some cmk.* code is calling things like cmk. is_raw_edition() at import time
100 # (e.g. cmk_base/default_config/notify.py) for edition specific variable
101 # defaults. In integration tests we want to use the exact version of the
102 # site. For unit tests we assume we are in Enterprise Edition context.
103 def fake_version_and_paths():
104 if is_running_as_site_user():
107 monkeypatch
= _pytest
.monkeypatch
.MonkeyPatch()
108 tmp_dir
= tempfile
.mkdtemp(prefix
="pytest_cmk_")
111 monkeypatch
.setattr(cmk
, "omd_version", lambda: "%s.cee" % cmk
.__version
__)
113 monkeypatch
.setattr("cmk.utils.paths.checks_dir", "%s/checks" % cmk_path())
114 monkeypatch
.setattr("cmk.utils.paths.notifications_dir", "%s/notifications" % cmk_path())
115 monkeypatch
.setattr("cmk.utils.paths.inventory_dir", "%s/inventory" % cmk_path())
116 monkeypatch
.setattr("cmk.utils.paths.check_manpages_dir", "%s/checkman" % cmk_path())
117 monkeypatch
.setattr("cmk.utils.paths.tmp_dir", tmp_dir
)
118 monkeypatch
.setattr("cmk.utils.paths.precompiled_checks_dir",
119 os
.path
.join(tmp_dir
, "var/check_mk/precompiled_checks"))
120 monkeypatch
.setattr("cmk.utils.paths.include_cache_dir",
121 os
.path
.join(tmp_dir
, "check_mk/check_includes"))
124 # Cleanup temporary directory created above
125 @pytest.fixture(scope
="session", autouse
=True)
129 if is_running_as_site_user():
132 import cmk
.utils
.paths
134 if "pytest_cmk_" not in cmk
.utils
.paths
.tmp_dir
:
138 shutil
.rmtree(cmk
.utils
.paths
.tmp_dir
)
139 except OSError as exc
:
140 if exc
.errno
!= errno
.ENOENT
:
141 raise # re-raise exception
145 return os
.path
.dirname(os
.path
.dirname(__file__
))
149 return os
.path
.realpath(cmk_path() + "/enterprise")
153 return os
.path
.realpath(cmk_path() + "/managed")
156 def add_python_paths():
157 # make the testlib available to the test modules
158 sys
.path
.insert(0, os
.path
.dirname(__file__
))
159 # make the repo directory available (cmk lib)
160 sys
.path
.insert(0, cmk_path())
162 # if not running as site user, make the livestatus module available
163 if not is_running_as_site_user():
164 sys
.path
.insert(0, os
.path
.join(cmk_path(), "livestatus/api/python"))
165 sys
.path
.insert(0, os
.path
.join(cmk_path(), "omd/packages/omd"))
168 def pytest_cmdline_main(config
):
169 """There are 2 environments for testing:
171 * A real Check_MK site environment (e.g. integration tests)
172 * Python virtual environment (e.g. for unit tests)
174 Depending on the selected "type" marker the environment is ensured
176 if not config
.getoption("-T"):
177 return # missing option is handled later
179 context
= test_types
[config
.getoption("-T")]
180 if context
== EXECUTE_IN_SITE
:
181 setup_site_and_switch_user()
186 def verify_virtualenv():
187 if not testlib
.virtualenv_path():
188 raise SystemExit("ERROR: Please load virtual environment first "
189 "(Use \"pipenv shell\" or configure direnv)")
192 def is_running_as_site_user():
193 return pwd
.getpwuid(os
.getuid()).pw_name
== _site_id()
196 def setup_site_and_switch_user():
197 if is_running_as_site_user():
198 return # This is executed as site user. Nothing to be done.
200 sys
.stdout
.write("===============================================\n")
201 sys
.stdout
.write("Setting up site '%s'\n" % _site_id())
202 sys
.stdout
.write("===============================================\n")
204 site
= _get_site_object()
206 cleanup_pattern
= os
.environ
.get("CLEANUP_OLD")
208 site
.cleanup_old_sites(cleanup_pattern
)
210 site
.cleanup_if_wrong_version()
212 #site.open_livestatus_tcp()
214 site
.prepare_for_tests()
216 sys
.stdout
.write("===============================================\n")
217 sys
.stdout
.write("Switching to site context\n")
218 sys
.stdout
.write("===============================================\n")
221 exit_code
= site
.switch_to_site_user()
223 sys
.stdout
.write("===============================================\n")
224 sys
.stdout
.write("Cleaning up after testing\n")
225 sys
.stdout
.write("===============================================\n")
227 #site.rm_if_not_reusing()
231 def _get_site_object():
233 return os
.environ
.get("VERSION", testlib
.CMKVersion
.DAILY
)
236 return os
.environ
.get("EDITION", testlib
.CMKVersion
.CEE
)
239 return os
.environ
.get("BRANCH", testlib
.current_branch_name())
242 return os
.environ
.get("REUSE", "1") == "1"
246 version
=site_version(),
247 edition
=site_edition(),
249 branch
=site_branch())
253 site_id
= os
.environ
.get("OMD_SITE")
254 if site_id
is not None:
257 branch_name
= os
.environ
.get("BRANCH", testlib
.current_branch_name())
258 # Split by / and get last element, remove unwanted chars
259 branch_part
= re
.sub("[^a-zA-Z0-9_]", "", branch_name
.split("/")[-1])
260 site_id
= "int_%s" % branch_part
262 os
.putenv("OMD_SITE", site_id
)
271 fake_version_and_paths()
274 # Session fixtures must be in conftest.py to work properly
275 @pytest.fixture(scope
="session", autouse
=True)
277 return _get_site_object()