Skip to content

Commit 2a2fab1

Browse files
authored
test: Make import-related tests stable (getsentry#3548)
The integrations not getting enabled when there are missing modules test was relying on certain packages not being installed in the environment and was causing issues when dev requirements was installed. This patch adds a context manager that simulates import errors for certain packages to make the test robust. It also enables the redis-related test by simulating a missing 'redis' package with the same context manager.
1 parent 26b86a5 commit 2a2fab1

File tree

1 file changed

+27
-23
lines changed

1 file changed

+27
-23
lines changed

tests/test_basics.py

+27-23
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from sentry_sdk.integrations import (
3030
_AUTO_ENABLING_INTEGRATIONS,
3131
_DEFAULT_INTEGRATIONS,
32+
DidNotEnable,
3233
Integration,
3334
setup_integrations,
3435
)
@@ -40,18 +41,6 @@
4041
from sentry_sdk.tracing_utils import has_tracing_enabled
4142

4243

43-
def _redis_installed(): # type: () -> bool
44-
"""
45-
Determines whether Redis is installed.
46-
"""
47-
try:
48-
import redis # noqa: F401
49-
except ImportError:
50-
return False
51-
52-
return True
53-
54-
5544
class NoOpIntegration(Integration):
5645
"""
5746
A simple no-op integration for testing purposes.
@@ -90,20 +79,35 @@ def error_processor(event, exc_info):
9079
assert event["exception"]["values"][0]["value"] == "aha! whatever"
9180

9281

82+
class ModuleImportErrorSimulator:
83+
def __init__(self, modules, error_cls=DidNotEnable):
84+
self.modules = modules
85+
self.error_cls = error_cls
86+
for sys_module in list(sys.modules.keys()):
87+
if any(sys_module.startswith(module) for module in modules):
88+
del sys.modules[sys_module]
89+
90+
def find_spec(self, fullname, _path, _target=None):
91+
if fullname in self.modules:
92+
raise self.error_cls("Test import failure for %s" % fullname)
93+
94+
def __enter__(self):
95+
# WARNING: We need to be first to avoid pytest messing with local imports
96+
sys.meta_path.insert(0, self)
97+
98+
def __exit__(self, *_args):
99+
sys.meta_path.remove(self)
100+
101+
93102
def test_auto_enabling_integrations_catches_import_error(sentry_init, caplog):
94103
caplog.set_level(logging.DEBUG)
95-
redis_index = _AUTO_ENABLING_INTEGRATIONS.index(
96-
"sentry_sdk.integrations.redis.RedisIntegration"
97-
) # noqa: N806
98104

99-
sentry_init(auto_enabling_integrations=True, debug=True)
105+
with ModuleImportErrorSimulator(
106+
[i.rsplit(".", 1)[0] for i in _AUTO_ENABLING_INTEGRATIONS]
107+
):
108+
sentry_init(auto_enabling_integrations=True, debug=True)
100109

101110
for import_string in _AUTO_ENABLING_INTEGRATIONS:
102-
# Ignore redis in the test case, because it does not raise a DidNotEnable
103-
# exception on import; rather, it raises the exception upon enabling.
104-
if _AUTO_ENABLING_INTEGRATIONS[redis_index] == import_string:
105-
continue
106-
107111
assert any(
108112
record.message.startswith(
109113
"Did not import default integration {}:".format(import_string)
@@ -883,9 +887,9 @@ def test_functions_to_trace_with_class(sentry_init, capture_events):
883887
assert event["spans"][1]["description"] == "tests.test_basics.WorldGreeter.greet"
884888

885889

886-
@pytest.mark.skipif(_redis_installed(), reason="skipping because redis is installed")
887890
def test_redis_disabled_when_not_installed(sentry_init):
888-
sentry_init()
891+
with ModuleImportErrorSimulator(["redis"], ImportError):
892+
sentry_init()
889893

890894
assert sentry_sdk.get_client().get_integration(RedisIntegration) is None
891895

0 commit comments

Comments
 (0)