Skip to content

Commit

Permalink
lyrics: isolate test configuration
Browse files Browse the repository at this point in the history
Create 'helpers.ConfigMixin' which sets up testing configuration.
This is helpful for tests (e.g. test_lyrics.py) that only need the
configuration and do not require temp dir.

(#5102) Refactor lyrics tests to fix the issue global beets config
issue.

Additionally, add 'integration_test' mark that can be used to mark tests
that should only run once a week.
  • Loading branch information
snejus committed Sep 19, 2024
1 parent 5039894 commit 57fed01
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 229 deletions.
44 changes: 23 additions & 21 deletions beets/test/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

import beets
import beets.plugins
from beets import autotag, config, importer, logging, util
from beets import autotag, importer, logging, util
from beets.autotag.hooks import AlbumInfo, TrackInfo
from beets.importer import ImportSession
from beets.library import Album, Item, Library
Expand Down Expand Up @@ -156,12 +156,27 @@ def check_reflink_support(path: str) -> bool:
return reflink.supported_at(path)


class ConfigMixin:
@cached_property
def config(self) -> beets.IncludeLazyConfig:
"""Base beets configuration for tests."""
config = beets.config
config.sources = []
config.read(user=False, defaults=True)

config["plugins"] = []
config["verbose"] = 1
config["ui"]["color"] = False
config["threaded"] = False
return config


NEEDS_REFLINK = unittest.skipUnless(
check_reflink_support(gettempdir()), "no reflink support for libdir"
)


class TestHelper(_common.Assertions):
class TestHelper(_common.Assertions, ConfigMixin):
"""Helper mixin for high-level cli and plugin tests.
This mixin provides methods to isolate beets' global state provide
Expand All @@ -187,8 +202,6 @@ def setup_beets(self):
- ``libdir`` Path to a subfolder of ``temp_dir``, containing the
library's media files. Same as ``config['directory']``.
- ``config`` The global configuration used by beets.
- ``lib`` Library instance created with the settings from
``config``.
Expand All @@ -205,15 +218,6 @@ def setup_beets(self):
)
self.env_patcher.start()

self.config = beets.config
self.config.sources = []
self.config.read(user=False, defaults=True)

self.config["plugins"] = []
self.config["verbose"] = 1
self.config["ui"]["color"] = False
self.config["threaded"] = False

self.libdir = os.path.join(self.temp_dir, b"libdir")
os.mkdir(syspath(self.libdir))
self.config["directory"] = os.fsdecode(self.libdir)
Expand All @@ -232,8 +236,6 @@ def teardown_beets(self):
self.io.restore()
self.lib._close()
self.remove_temp_dir()
beets.config.clear()
beets.config._materialized = False

# Library fixtures methods

Expand Down Expand Up @@ -462,7 +464,7 @@ def setUp(self):
self.i = _common.item(self.lib)


class PluginMixin:
class PluginMixin(ConfigMixin):
plugin: ClassVar[str]
preload_plugin: ClassVar[bool] = True

Expand All @@ -483,7 +485,7 @@ def load_plugins(self, *plugins: str) -> None:
"""
# FIXME this should eventually be handled by a plugin manager
plugins = (self.plugin,) if hasattr(self, "plugin") else plugins
beets.config["plugins"] = plugins
self.config["plugins"] = plugins
beets.plugins.load_plugins(plugins)
beets.plugins.find_plugins()

Expand All @@ -504,7 +506,7 @@ def unload_plugins(self) -> None:
# FIXME this should eventually be handled by a plugin manager
for plugin_class in beets.plugins._instances:
plugin_class.listeners = None
beets.config["plugins"] = []
self.config["plugins"] = []
beets.plugins._classes = set()
beets.plugins._instances = {}
Item._types = getattr(Item, "_original_types", {})
Expand All @@ -515,10 +517,10 @@ def unload_plugins(self) -> None:
@contextmanager
def configure_plugin(self, config: list[Any] | dict[str, Any]):
if isinstance(config, list):
beets.config[self.plugin] = config
self.config[self.plugin] = config
else:
for key, value in config.items():
beets.config[self.plugin][key] = value
self.config[self.plugin][key] = value
self.load_plugins(self.plugin)

yield
Expand Down Expand Up @@ -638,7 +640,7 @@ def _get_import_session(self, import_dir: bytes) -> ImportSession:
def setup_importer(
self, import_dir: bytes | None = None, **kwargs
) -> ImportSession:
config["import"].set_args({**self.default_import_config, **kwargs})
self.config["import"].set_args({**self.default_import_config, **kwargs})
self.importer = self._get_import_session(import_dir or self.import_dir)
return self.importer

Expand Down
3 changes: 3 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ Other changes:
calculate the bpm. Previously this import was being done immediately, so
every ``beet`` invocation was being delayed by a couple of seconds.
:bug:`5185`
* :doc:`plugins/lyrics`: Rewrite lyrics tests using pytest to provide isolated
configuration for each test case.
:bug:`5133`

2.0.0 (May 30, 2024)
--------------------
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ addopts =
# show all skipped/failed/xfailed tests in the summary except passed
-ra
--strict-config
markers =
integration_test: mark a test as an integration test

[coverage:run]
data_file = .reports/coverage/data
Expand Down
12 changes: 12 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import os

import pytest


def pytest_runtest_setup(item: pytest.Item):
"""Skip integration tests if INTEGRATION_TEST environment variable is not set."""
if os.environ.get("INTEGRATION_TEST"):
return

if next(item.iter_markers(name="integration_test"), None):
pytest.skip("Skipping integration tests")
Loading

0 comments on commit 57fed01

Please sign in to comment.