Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e032332
chore: set up autoresearch session (less tests, same coverage)
ericapisani Jul 30, 2026
f3df3b1
fix: count junit testcases by occurrences, not lines
ericapisani Jul 30, 2026
5a1c757
test: remove 6 permanently-skipped dead tests (Hub deprecation leftov…
ericapisani Jul 30, 2026
ab3919f
test(transport): replace 192-case cross-product with 24 curated cases
ericapisani Jul 30, 2026
1db1f0a
test(transport): reduce async transport matrix from 96 to 12 cases
ericapisani Jul 30, 2026
133a301
test(utils): prune redundant case permutations in test_env_to_bool (6…
ericapisani Jul 30, 2026
248fcc1
test(client): run proxy matrices over HTTP/2 for representative cases…
ericapisani Jul 30, 2026
4f35d2c
test(client): slim debug/spotlight option precedence tables (42 -> 17)
ericapisani Jul 30, 2026
83e5df8
test(tracing): reduce sample_rand x sample_rate grids to boundary cas…
ericapisani Jul 30, 2026
e7ca457
test(tracing): dedupe wrong-type equivalence class in invalid sampler…
ericapisani Jul 30, 2026
bb324d7
test(utils): corner-set for safe_repr prefix x control-char grid (12 …
ericapisani Jul 30, 2026
208137e
test: prune wrong-type dupes in sample-rate table and attr-irrelevant…
ericapisani Jul 30, 2026
d316e23
chore: update autoresearch playbook and ideas backlog
ericapisani Jul 30, 2026
f2ad95c
docs: autoresearch final summary (2720 -> 2289 tests, coverage flat)
ericapisani Jul 30, 2026
10e8d7d
chore: gitignore regenerable autoresearch analysis artifacts
ericapisani Jul 30, 2026
8c05a0e
Restored the full HTTP/2 proxy matrices requested after review and re…
ericapisani Jul 30, 2026
0a8678f
Removed the test_transport_num_pools row that explicitly sets the def…
ericapisani Jul 30, 2026
89b185f
Removed the redundant bare localhost trace-propagation URL case; rege…
ericapisani Jul 30, 2026
07b1996
Removed the redundant -10 invalid LRU cache size case; -1 and zero re…
ericapisani Jul 30, 2026
0e82f36
Removed the redundant float non-string/non-list message-content case;…
ericapisani Jul 30, 2026
91f7cd8
Removed the redundant anchored non-match regex row: both 'some' and '…
ericapisani Jul 30, 2026
ed53b2c
Removed the redundant None item with an empty regex list; empty lists…
ericapisani Jul 30, 2026
419d52a
Removed the redundant None item with regex_list=None; the early None-…
ericapisani Jul 30, 2026
88ec1f7
Removed the redundant ordinary-string item with an empty regex list; …
ericapisani Jul 30, 2026
5366d2b
Removed the redundant interior valid sample-rate value; zero and one …
ericapisani Jul 30, 2026
06c2173
Removed the redundant ordinary-string item with regex_list=None; the …
ericapisani Jul 30, 2026
f31311d
Removed the redundant False sample-rate case; True preserves explicit…
ericapisani Jul 30, 2026
b5f1c4e
Removed the standalone LRU cache-miss test because test_simple_set_ge…
ericapisani Jul 30, 2026
bf7427c
Removed test_simple_set_get because test_overwrite is a behavioral su…
ericapisani Jul 30, 2026
64bfdce
Removed the larger-capacity LRU overwrite test because test_overwrite…
ericapisani Jul 30, 2026
f414446
Removed the direct-scope streamed-span getter test because the retain…
ericapisani Jul 31, 2026
6409f45
remove .auto subdirectory from source control
ericapisani Jul 31, 2026
2ee729e
.
ericapisani Jul 31, 2026
87bead7
list cases
ericapisani Jul 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pip-wheel-metadata
.serena
.tool-versions
.warden
.auto/

# for running AWS Lambda tests using AWS SAM
sam.template.yaml
2 changes: 1 addition & 1 deletion tests/test_ai_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ def test_single_message_truncation_list_content_multiple_text_parts(self):
# Second part gets truncated to 0 chars + ellipsis
assert parts[1]["text"] == "..."

@pytest.mark.parametrize("content", [None, 42, 3.14, True])
@pytest.mark.parametrize("content", [None, 42, True])
def test_single_message_truncation_non_str_non_list_content(self, content):
messages = [{"role": "user", "content": content}]

Expand Down
98 changes: 0 additions & 98 deletions tests/test_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
push_scope,
start_transaction,
)
from sentry_sdk.client import Client
from sentry_sdk.integrations import (
_AUTO_ENABLING_INTEGRATIONS,
_DEFAULT_INTEGRATIONS,
Expand Down Expand Up @@ -334,38 +333,6 @@ def test_push_scope_null_client(
assert len(events) == 0


@pytest.mark.skip(
reason="This test is not valid anymore, because push_scope just returns the isolation scope. This test should be removed once the Hub is removed"
)
@pytest.mark.parametrize("null_client", (True, False))
def test_push_scope_callback(sentry_init, null_client, capture_events):
"""
This test can be removed when we remove push_scope and the Hub from the SDK.
"""
sentry_init()

if null_client:
Hub.current.bind_client(None)

outer_scope = Hub.current.scope

calls = []

@push_scope
def _(scope):
assert scope is Hub.current.scope
assert scope is not outer_scope
calls.append(1)

# push_scope always needs to execute the callback regardless of
# client state, because that actually runs usercode in it, not
# just scope config code
assert calls == [1]

# Assert scope gets popped correctly
assert Hub.current.scope is outer_scope


def test_breadcrumbs(sentry_init, capture_events):
sentry_init(max_breadcrumbs=10)
events = capture_events()
Expand Down Expand Up @@ -636,71 +603,6 @@ def test_integrations(
} == expected_integrations


@pytest.mark.skip(
reason="This test is not valid anymore, because with the new Scopes calling bind_client on the Hub sets the client on the global scope. This test should be removed once the Hub is removed"
)
def test_client_initialized_within_scope(sentry_init, caplog):
"""
This test can be removed when we remove push_scope and the Hub from the SDK.
"""
caplog.set_level(logging.WARNING)

sentry_init()

with push_scope():
Hub.current.bind_client(Client())

(record,) = (x for x in caplog.records if x.levelname == "WARNING")

assert record.msg.startswith("init() called inside of pushed scope.")


@pytest.mark.skip(
reason="This test is not valid anymore, because with the new Scopes the push_scope just returns the isolation scope. This test should be removed once the Hub is removed"
)
def test_scope_leaks_cleaned_up(sentry_init, caplog):
"""
This test can be removed when we remove push_scope and the Hub from the SDK.
"""
caplog.set_level(logging.WARNING)

sentry_init()

old_stack = list(Hub.current._stack)

with push_scope():
push_scope()

assert Hub.current._stack == old_stack

(record,) = (x for x in caplog.records if x.levelname == "WARNING")

assert record.message.startswith("Leaked 1 scopes:")


@pytest.mark.skip(
reason="This test is not valid anymore, because with the new Scopes there is not pushing and popping of scopes. This test should be removed once the Hub is removed"
)
def test_scope_popped_too_soon(sentry_init, caplog):
"""
This test can be removed when we remove push_scope and the Hub from the SDK.
"""
caplog.set_level(logging.ERROR)

sentry_init()

old_stack = list(Hub.current._stack)

with push_scope():
Hub.current.pop_scope_unsafe()

assert Hub.current._stack == old_stack

(record,) = (x for x in caplog.records if x.levelname == "ERROR")

assert record.message == ("Scope popped too soon. Popped 1 scopes too many.")


def test_scope_event_processor_order(sentry_init, capture_events):
def before_send(event, hint):
event["message"] += "baz"
Expand Down
52 changes: 6 additions & 46 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,27 +678,6 @@ def test_client_debug_option_disabled(with_client, sentry_init, caplog):
assert "OK" not in caplog.text


@pytest.mark.skip(
reason="New behavior in SDK 2.0: You have a scope before init and add data to it."
)
def test_scope_initialized_before_client(sentry_init, capture_events):
"""
This is a consequence of how configure_scope() works. We must
make `configure_scope()` a noop if no client is configured. Even
if the user later configures a client: We don't know that.
"""
with configure_scope() as scope:
scope.set_tag("foo", 42)

sentry_init()

events = capture_events()
capture_message("hi")
(event,) = events

assert "tags" not in event


def test_weird_chars(sentry_init, capture_events):
sentry_init()
events = capture_events()
Expand Down Expand Up @@ -1115,36 +1094,17 @@ def test_max_value_length_option(sentry_init, capture_events):
@pytest.mark.parametrize(
"client_option,env_var_value,debug_output_expected",
[
# env var parsing itself (env_to_bool) is exhaustively tested in
# tests/test_utils.py; what is specified here is the precedence:
# explicit option beats env var, env var only applies otherwise.
(None, "", False),
(None, "t", True),
(None, "1", True),
(None, "True", True),
(None, "true", True),
(None, "f", False),
(None, "0", False),
(None, "False", False),
(None, "false", False),
(None, "xxx", False),
(True, "", True),
(True, "t", True),
(True, "1", True),
(True, "True", True),
(True, "true", True),
(True, "f", True),
(True, "0", True),
(True, "False", True),
(True, "false", True),
(True, "xxx", True),
(False, "", False),
(False, "t", False),
(False, "1", False),
(False, "True", False),
(False, "true", False),
(False, "f", False),
(False, "0", False),
(False, "False", False),
(False, "false", False),
(False, "xxx", False),
],
)
@pytest.mark.tests_internal_exceptions
Expand Down Expand Up @@ -1173,14 +1133,14 @@ def test_debug_option(
@pytest.mark.parametrize(
"client_option,env_var_value,spotlight_url_expected",
[
# option x env precedence: option in {None, False, True, URL} crossed
# with env in {unset, falsy, truthy, URL}; env bool parsing itself is
# covered in tests/test_utils.py::test_env_to_bool.
(None, None, None),
(None, "", None),
(None, "F", None),
(False, None, None),
(False, "", None),
(False, "t", None),
(None, "t", DEFAULT_SPOTLIGHT_URL),
(None, "1", DEFAULT_SPOTLIGHT_URL),
(True, None, DEFAULT_SPOTLIGHT_URL),
# Per spec: spotlight=True + env URL -> use env URL
(True, "http://localhost:8080/slurp", "http://localhost:8080/slurp"),
Expand Down
21 changes: 1 addition & 20 deletions tests/test_lru_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,12 @@
from sentry_sdk._lru_cache import LRUCache


@pytest.mark.parametrize("max_size", [-10, -1, 0])
@pytest.mark.parametrize("max_size", [-1, 0])
def test_illegal_size(max_size):
with pytest.raises(AssertionError):
LRUCache(max_size=max_size)


def test_simple_set_get():
cache = LRUCache(1)
assert cache.get(1) is None
cache.set(1, 1)
assert cache.get(1) == 1


def test_overwrite():
cache = LRUCache(1)
assert cache.get(1) is None
Expand All @@ -37,18 +30,6 @@ def test_cache_eviction():
assert cache.get(4) == 4


def test_cache_miss():
cache = LRUCache(1)
assert cache.get(0) is None


def test_cache_set_overwrite():
cache = LRUCache(3)
cache.set(0, 0)
cache.set(0, 1)
assert cache.get(0) == 1


def test_cache_get_all():
cache = LRUCache(3)
cache.set(0, 0)
Expand Down
63 changes: 50 additions & 13 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,37 @@ def mock_transaction_envelope(span_count: int) -> "Envelope":
return envelope


@pytest.mark.parametrize("debug", (True, False))
@pytest.mark.parametrize("client_flush_method", ["close", "flush"])
@pytest.mark.parametrize("use_pickle", (True, False))
@pytest.mark.parametrize("compression_level", (0, 9, None))
def _transport_works_cases():
"""
The compression-relevant dimensions (level x algo x http2) are fully
crossed; debug, flush method and pickling are rotated through the cases
so every value of every dimension is still exercised.
"""
algos = ("gzip", "br", "<invalid>", None) if PY37 else ("gzip", "<invalid>", None)
http2_options = (True, False) if PY38 else (False,)
cases = []
i = 0
for compression_level in (None, 0, 9):
for compression_algo in algos:
for http2 in http2_options:
cases.append(
(
i % 2 == 0, # debug
("close", "flush")[i % 2], # client_flush_method
(i // 2) % 2 == 0, # use_pickle
compression_level,
compression_algo,
http2,
)
)
i += 1
return cases


@pytest.mark.parametrize(
"compression_algo",
(("gzip", "br", "<invalid>", None) if PY37 else ("gzip", "<invalid>", None)),
"debug,client_flush_method,use_pickle,compression_level,compression_algo,http2",
_transport_works_cases(),
)
@pytest.mark.parametrize("http2", [True, False] if PY38 else [False])
def test_transport_works(
capturing_server,
request,
Expand Down Expand Up @@ -185,7 +207,6 @@ def test_transport_works(
"num_pools,expected_num_pools",
(
(None, 2),
(2, 2),
(10, 10),
),
)
Expand Down Expand Up @@ -878,11 +899,27 @@ def test_record_lost_event_transaction_item(capturing_server, make_client, span_

@skip_under_gevent
@pytest.mark.asyncio
@pytest.mark.parametrize("debug", (True, False))
@pytest.mark.parametrize("client_flush_method", ["close", "flush"])
@pytest.mark.parametrize("use_pickle", (True, False))
@pytest.mark.parametrize("compression_level", (0, 9, None))
@pytest.mark.parametrize("compression_algo", ("gzip", "br", "<invalid>", None))
@pytest.mark.parametrize(
"debug,client_flush_method,use_pickle,compression_level,compression_algo",
[
# debug and client_flush_method alternate every case; use_pickle
# alternates every two cases. This rotates those dimensions through the
# fully-crossed (compression_level x compression_algo) grid so each
# value is exercised without running the full cross product.
(True, "close", True, None, "gzip"),
(False, "flush", True, None, "br"),
(True, "close", False, None, "<invalid>"),
(False, "flush", False, None, None),
(True, "close", True, 0, "gzip"),
(False, "flush", True, 0, "br"),
(True, "close", False, 0, "<invalid>"),
(False, "flush", False, 0, None),
(True, "close", True, 9, "gzip"),
(False, "flush", True, 9, "br"),
(True, "close", False, 9, "<invalid>"),
(False, "flush", False, 9, None),
],
)
@pytest.mark.skipif(not PY38, reason="Async transport only supported in Python 3.8+")
async def test_transport_works_async(
capturing_server,
Expand Down
Loading
Loading