mirror of
https://github.com/beetbox/beets.git
synced 2025-12-31 04:52:49 +01:00
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 ================================================================================
```
This commit is contained in:
commit
d5f87264e9
4 changed files with 417 additions and 840 deletions
|
|
@ -85,6 +85,7 @@ class Query(ABC):
|
|||
"""Return a set with field names that this query operates on."""
|
||||
return set()
|
||||
|
||||
@abstractmethod
|
||||
def clause(self) -> tuple[str | None, Sequence[Any]]:
|
||||
"""Generate an SQLite expression implementing the query.
|
||||
|
||||
|
|
@ -95,14 +96,12 @@ class Query(ABC):
|
|||
The default implementation returns None, falling back to a slow query
|
||||
using `match()`.
|
||||
"""
|
||||
return None, ()
|
||||
|
||||
@abstractmethod
|
||||
def match(self, obj: Model):
|
||||
"""Check whether this query matches a given Model. Can be used to
|
||||
perform queries on arbitrary sets of Model.
|
||||
"""
|
||||
...
|
||||
|
||||
def __and__(self, other: Query) -> AndQuery:
|
||||
return AndQuery([self, other])
|
||||
|
|
@ -152,7 +151,7 @@ class FieldQuery(Query, Generic[P]):
|
|||
self.fast = fast
|
||||
|
||||
def col_clause(self) -> tuple[str, Sequence[SQLiteType]]:
|
||||
return self.field, ()
|
||||
raise NotImplementedError
|
||||
|
||||
def clause(self) -> tuple[str | None, Sequence[SQLiteType]]:
|
||||
if self.fast:
|
||||
|
|
@ -164,7 +163,7 @@ class FieldQuery(Query, Generic[P]):
|
|||
@classmethod
|
||||
def value_match(cls, pattern: P, value: Any):
|
||||
"""Determine whether the value matches the pattern."""
|
||||
raise NotImplementedError()
|
||||
raise NotImplementedError
|
||||
|
||||
def match(self, obj: Model) -> bool:
|
||||
return self.value_match(self.pattern, obj.get(self.field_name))
|
||||
|
|
@ -234,7 +233,7 @@ class StringFieldQuery(FieldQuery[P]):
|
|||
"""Determine whether the value matches the pattern. Both
|
||||
arguments are strings. Subclasses implement this method.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class StringQuery(StringFieldQuery[str]):
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ HAVE_SYMLINK = sys.platform != "win32"
|
|||
HAVE_HARDLINK = sys.platform != "win32"
|
||||
|
||||
|
||||
def item(lib=None):
|
||||
i = beets.library.Item(
|
||||
def item(lib=None, **kwargs):
|
||||
defaults = dict(
|
||||
title="the title",
|
||||
artist="the artist",
|
||||
albumartist="the album artist",
|
||||
|
|
@ -99,6 +99,7 @@ def item(lib=None):
|
|||
album_id=None,
|
||||
mtime=12345,
|
||||
)
|
||||
i = beets.library.Item(**{**defaults, **kwargs})
|
||||
if lib:
|
||||
lib.add(i)
|
||||
return i
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import inspect
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from beets.dbcore.query import Query
|
||||
|
||||
|
||||
def skip_marked_items(items: list[pytest.Item], marker_name: str, reason: str):
|
||||
for item in (i for i in items if i.get_closest_marker(marker_name)):
|
||||
|
|
@ -21,3 +24,20 @@ def pytest_collection_modifyitems(
|
|||
skip_marked_items(
|
||||
items, "on_lyrics_update", "No change in lyrics source code"
|
||||
)
|
||||
|
||||
|
||||
def pytest_make_parametrize_id(config, val, argname):
|
||||
"""Generate readable test identifiers for pytest parametrized tests.
|
||||
|
||||
Provides custom string representations for:
|
||||
- Query classes/instances: use class name
|
||||
- Lambda functions: show abbreviated source
|
||||
- Other values: use standard repr()
|
||||
"""
|
||||
if inspect.isclass(val) and issubclass(val, Query):
|
||||
return val.__name__
|
||||
|
||||
if inspect.isfunction(val) and val.__name__ == "<lambda>":
|
||||
return inspect.getsource(val).split("lambda")[-1][:30]
|
||||
|
||||
return repr(val)
|
||||
|
|
|
|||
1223
test/test_query.py
1223
test/test_query.py
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue