Skip to content

Commit d5f8726

Browse files
authored
Rewrite and speed up query tests (#5813)
Previously: ```sh Poe => pytest -p no:cov test/test_query.py --durations=10 =============================================================================== test session starts =============================================================================== platform linux -- Python 3.9.20, pytest-8.3.5, pluggy-1.5.0 cachedir: /tmp/pytest_cache rootdir: /home/sarunas/repo/beets configfile: setup.cfg plugins: anyio-4.9.0, xdist-3.6.1, requests-mock-1.12.1, flask-1.3.0 collected 133 items test/test_query.py ..................................................................................................................................... [133/133] ============================================================================== slowest 10 durations =============================================================================== 0.13s call test/test_query.py::NotQueryTest::test_type_none 0.12s call test/test_query.py::NotQueryTest::test_fast_vs_slow 0.11s call test/test_query.py::GetTest::test_singleton_0 0.11s call test/test_query.py::NotQueryTest::test_type_substring 0.11s call test/test_query.py::RelatedQueriesTest::test_filter_items_by_common_field 0.11s call test/test_query.py::RelatedQueriesTest::test_get_items_filter_by_album_field 0.11s call test/test_query.py::NotQueryTest::test_type_boolean 0.11s call test/test_query.py::NotQueryTest::test_type_or 0.11s call test/test_query.py::NotQueryTest::test_type_numeric 0.11s call test/test_query.py::NotQueryTest::test_type_true =============================================================================== 133 passed in 9.94s =============================================================================== ``` Now: ```sh Poe => pytest -p no:cov test/test_query.py --durations=10 =============================================================================== test session starts ================================================================================ platform linux -- Python 3.9.20, pytest-8.3.5, pluggy-1.5.0 cachedir: /tmp/pytest_cache rootdir: /home/sarunas/repo/beets configfile: setup.cfg plugins: anyio-4.9.0, xdist-3.6.1, requests-mock-1.12.1, flask-1.3.0 collected 129 items test/test_query.py ................................................................................................................................. [129/129] =============================================================================== slowest 10 durations =============================================================================== 0.10s setup test/test_query.py::TestRelatedQueries::test_related_query[match-album-with-item-field-query] 0.09s setup test/test_query.py::TestGet::test_get_query[''-['first', 'second', 'third']] 0.09s setup test/test_query.py::TestPathQuery::test_explicit[exact-match] 0.09s setup test/test_query.py::TestQuery::test_value_type[parse-true] 0.08s setup test/test_query.py::TestDefaultSearchFields::test_search[album-match-album] 0.02s call test/test_query.py::TestGet::test_query_logic[SubstringQuery('album', 'ba', fast=True)-{'third'}] 0.02s call test/test_query.py::TestGet::test_query_logic[NoneQuery('rg_track_gain', True)-set()] 0.02s call test/test_query.py::TestGet::test_query_logic[NumericQuery('year', '2001..2002', fast=True)-{'third'}] 0.02s call test/test_query.py::TestGet::test_query_logic[RegexpQuery('artist', re.compile('^t'), fast=True)-{'first'}] 0.02s call test/test_query.py::TestGet::test_query_logic[OrQuery([BooleanQuery('comp', 1, fast=True), NumericQuery('year', '2002', fast=True)])-{'third'}] =============================================================================== 129 passed in 2.53s ================================================================================ ```
2 parents 7165b04 + 443ed57 commit d5f8726

File tree

4 files changed

+400
-823
lines changed

4 files changed

+400
-823
lines changed

beets/dbcore/query.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def field_names(self) -> set[str]:
8585
"""Return a set with field names that this query operates on."""
8686
return set()
8787

88+
@abstractmethod
8889
def clause(self) -> tuple[str | None, Sequence[Any]]:
8990
"""Generate an SQLite expression implementing the query.
9091
@@ -95,14 +96,12 @@ def clause(self) -> tuple[str | None, Sequence[Any]]:
9596
The default implementation returns None, falling back to a slow query
9697
using `match()`.
9798
"""
98-
return None, ()
9999

100100
@abstractmethod
101101
def match(self, obj: Model):
102102
"""Check whether this query matches a given Model. Can be used to
103103
perform queries on arbitrary sets of Model.
104104
"""
105-
...
106105

107106
def __and__(self, other: Query) -> AndQuery:
108107
return AndQuery([self, other])
@@ -152,7 +151,7 @@ def __init__(self, field_name: str, pattern: P, fast: bool = True):
152151
self.fast = fast
153152

154153
def col_clause(self) -> tuple[str, Sequence[SQLiteType]]:
155-
return self.field, ()
154+
raise NotImplementedError
156155

157156
def clause(self) -> tuple[str | None, Sequence[SQLiteType]]:
158157
if self.fast:
@@ -164,7 +163,7 @@ def clause(self) -> tuple[str | None, Sequence[SQLiteType]]:
164163
@classmethod
165164
def value_match(cls, pattern: P, value: Any):
166165
"""Determine whether the value matches the pattern."""
167-
raise NotImplementedError()
166+
raise NotImplementedError
168167

169168
def match(self, obj: Model) -> bool:
170169
return self.value_match(self.pattern, obj.get(self.field_name))
@@ -234,7 +233,7 @@ def string_match(
234233
"""Determine whether the value matches the pattern. Both
235234
arguments are strings. Subclasses implement this method.
236235
"""
237-
raise NotImplementedError()
236+
raise NotImplementedError
238237

239238

240239
class StringQuery(StringFieldQuery[str]):

beets/test/_common.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@
6363
HAVE_HARDLINK = sys.platform != "win32"
6464

6565

66-
def item(lib=None):
67-
i = beets.library.Item(
66+
def item(lib=None, **kwargs):
67+
defaults = dict(
6868
title="the title",
6969
artist="the artist",
7070
albumartist="the album artist",
@@ -99,6 +99,7 @@ def item(lib=None):
9999
album_id=None,
100100
mtime=12345,
101101
)
102+
i = beets.library.Item(**{**defaults, **kwargs})
102103
if lib:
103104
lib.add(i)
104105
return i

test/conftest.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import inspect
12
import os
23

34
import pytest
45

6+
from beets.dbcore.query import Query
7+
58

69
def skip_marked_items(items: list[pytest.Item], marker_name: str, reason: str):
710
for item in (i for i in items if i.get_closest_marker(marker_name)):
@@ -21,3 +24,20 @@ def pytest_collection_modifyitems(
2124
skip_marked_items(
2225
items, "on_lyrics_update", "No change in lyrics source code"
2326
)
27+
28+
29+
def pytest_make_parametrize_id(config, val, argname):
30+
"""Generate readable test identifiers for pytest parametrized tests.
31+
32+
Provides custom string representations for:
33+
- Query classes/instances: use class name
34+
- Lambda functions: show abbreviated source
35+
- Other values: use standard repr()
36+
"""
37+
if inspect.isclass(val) and issubclass(val, Query):
38+
return val.__name__
39+
40+
if inspect.isfunction(val) and val.__name__ == "<lambda>":
41+
return inspect.getsource(val).split("lambda")[-1][:30]
42+
43+
return repr(val)

0 commit comments

Comments
 (0)