tests: move reusable test-related modules into the beets package

External Python packages interfacing beets may want to use an in-memory
beets library instance for testing beets-related code.
The `TestHelper` class is very helpful for this purpose.
Previously `TestHelper` was located in the `test/` directory.
Now it is part of `beets` itself (`beets.test.helper.TestHelper`) and
can be easily imported.
This commit is contained in:
Lars Kruse 2024-01-05 02:58:55 +01:00
parent 2b99c12430
commit 508d28f66b
70 changed files with 164 additions and 111 deletions

19
beets/test/__init__.py Normal file
View file

@ -0,0 +1,19 @@
# This file is part of beets.
# Copyright 2024, Lars Kruse
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
"""This module contains components of beets' test environment, which
may be of use for testing procedures of external libraries or programs.
For example the 'TestHelper' class may be useful for creating an
in-memory beets library filled with a few example items.
"""

View file

@ -33,12 +33,29 @@ from beets.ui import commands # noqa: E402
from beets.util import bytestring_path, syspath # noqa: E402
beetsplug.__path__ = [
os.path.abspath(os.path.join(__file__, "..", "..", "beetsplug"))
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
os.path.pardir,
os.path.pardir,
"beetsplug",
)
)
]
# Test resources path.
RSRC = util.bytestring_path(os.path.join(os.path.dirname(__file__), "rsrc"))
PLUGINPATH = os.path.join(os.path.dirname(__file__), "rsrc", "beetsplug")
RSRC = util.bytestring_path(
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
os.path.pardir,
os.path.pardir,
"test",
"rsrc",
)
)
)
PLUGINPATH = os.path.join(RSRC.decode(), "beetsplug")
# Propagate to root logger so the test runner can capture it
log = logging.getLogger("beets")

View file

@ -40,9 +40,6 @@ from enum import Enum
from io import StringIO
from tempfile import mkdtemp, mkstemp
# TODO Move AutotagMock here
from test import _common
from mediafile import Image, MediaFile
import beets
@ -50,6 +47,7 @@ import beets.plugins
from beets import autotag, config, importer, logging, util
from beets.autotag.hooks import AlbumInfo, TrackInfo
from beets.library import Album, Item, Library
from beets.test import _common
from beets.ui.commands import TerminalImportSession
from beets.util import MoveOperation, bytestring_path, syspath

View file

@ -290,6 +290,10 @@ For plugin developers:
overwrite the function defined by the other plugin.
Now, beets will raise an exception when this happens.
:bug:`5002`
* Allow reuse of some parts of beets' testing components. This may ease the
work for externally developed plugins or related software (e.g. the beets
plugin for Mopidy), if they need to create an in-memory instance of a beets
music library for their tests.
For packagers:

View file

@ -117,6 +117,7 @@ per-file-ignores =
./beets/__main__.py:D
./beets/importer.py:D
./beets/plugins.py:D
./beets/test/*:D
./beets/util/bluelet.py:D
./beets/util/enumeration.py:D
./beets/util/artresizer.py:D

View file

@ -19,8 +19,8 @@
import json
import os.path
import unittest
from test._common import RSRC
from beets.test._common import RSRC
from beetsplug.acousticbrainz import ABSCHEME, AcousticPlugin

View file

@ -16,8 +16,8 @@
"""
import unittest
from test.helper import TestHelper
from beets.test.helper import TestHelper
from beets.ui import UserError
PLUGIN_NAME = "advancedrewrite"

View file

@ -16,9 +16,9 @@
import unittest
from test.helper import TestHelper
from beets.autotag.mb import VARIOUS_ARTISTS_ID
from beets.test.helper import TestHelper
from beetsplug.albumtypes import AlbumTypesPlugin

View file

@ -18,8 +18,6 @@
import os
import shutil
import unittest
from test import _common
from test.helper import capture_log
from unittest.mock import patch
import confuse
@ -27,6 +25,8 @@ import responses
from beets import config, importer, library, logging, util
from beets.autotag import AlbumInfo, AlbumMatch
from beets.test import _common
from beets.test.helper import capture_log
from beets.util import syspath
from beets.util.artresizer import ArtResizer
from beetsplug import fetchart

View file

@ -5,9 +5,9 @@
import unittest
from test.helper import TestHelper, capture_stdout
from beets import logging
from beets.test.helper import TestHelper, capture_stdout
class BareascPluginTest(unittest.TestCase, TestHelper):

View file

@ -17,10 +17,10 @@
import unittest
from datetime import timedelta
from test import _common
from test.helper import TestHelper
from beets import library
from beets.test import _common
from beets.test.helper import TestHelper
from beetsplug import beatport

View file

@ -16,9 +16,9 @@
import unittest
from test.helper import TestHelper
from beets import config, ui
from beets.test.helper import TestHelper
from beetsplug import bucket

View file

@ -18,12 +18,12 @@ import os.path
import re
import sys
import unittest
from test import _common, helper
from test.helper import capture_log, control_stdin
from mediafile import MediaFile
from beets import util
from beets.test import _common, helper
from beets.test.helper import capture_log, control_stdin
from beets.util import bytestring_path, displayable_path

View file

@ -16,11 +16,11 @@
"""
import unittest
from test import _common
from test._common import Bag
from test.helper import capture_log
from beets import config
from beets.test import _common
from beets.test._common import Bag
from beets.test.helper import capture_log
from beets.util.id_extractors import extract_discogs_id_regex
from beetsplug.discogs import DiscogsPlugin

View file

@ -14,18 +14,18 @@
import codecs
import unittest
from test import _common
from test.helper import (
from unittest.mock import patch
from beets.dbcore.query import TrueQuery
from beets.library import Item
from beets.test import _common
from beets.test.helper import (
AutotagStub,
ImportHelper,
TerminalImportSessionSetup,
TestHelper,
control_stdin,
)
from unittest.mock import patch
from beets.dbcore.query import TrueQuery
from beets.library import Item
from beetsplug.edit import EditPlugin

View file

@ -17,8 +17,6 @@ import os.path
import shutil
import tempfile
import unittest
from test import _common
from test.helper import TestHelper
from test.plugins.test_art import FetchImageHelper
from test.test_art_resize import DummyIMBackend
from unittest.mock import MagicMock, patch
@ -26,6 +24,8 @@ from unittest.mock import MagicMock, patch
from mediafile import MediaFile
from beets import art, config, logging, ui
from beets.test import _common
from beets.test.helper import TestHelper
from beets.util import bytestring_path, displayable_path, syspath
from beets.util.artresizer import ArtResizer

View file

@ -1,8 +1,8 @@
import unittest
from test.helper import TestHelper
import responses
from beets.test.helper import TestHelper
from beetsplug import embyupdate

View file

@ -19,10 +19,11 @@
import json
import re # used to test csv format
import unittest
from test.helper import TestHelper
from xml.etree import ElementTree
from xml.etree.ElementTree import Element
from beets.test.helper import TestHelper
class ExportPluginTest(unittest.TestCase, TestHelper):
def setUp(self):

View file

@ -17,9 +17,9 @@ import ctypes
import os
import sys
import unittest
from test.helper import TestHelper
from beets import util
from beets.test.helper import TestHelper
class FetchartCliTest(unittest.TestCase, TestHelper):

View file

@ -19,12 +19,12 @@
import os
import shutil
import unittest
from test import _common
from test.helper import ImportHelper, capture_log
from mediafile import MediaFile
from beets import config
from beets.test import _common
from beets.test.helper import ImportHelper, capture_log
from beets.util import bytestring_path, displayable_path, syspath
from beetsplug.filefilter import FileFilterPlugin

View file

@ -16,8 +16,8 @@
import unittest
from test.helper import TestHelper
from beets.test.helper import TestHelper
from beetsplug import ftintitle

View file

@ -17,10 +17,10 @@ import os.path
import sys
import tempfile
import unittest
from test import _common
from test.helper import TestHelper, capture_log
from beets import config, plugins
from beets.test import _common
from beets.test.helper import TestHelper, capture_log
def get_temporary_path():

View file

@ -17,9 +17,9 @@
import os
import unittest
from test.helper import AutotagStub, ImportHelper
from beets import importer
from beets.test.helper import AutotagStub, ImportHelper
from beets.util import displayable_path, syspath
from beetsplug.importadded import ImportAddedPlugin

View file

@ -14,10 +14,10 @@
import unittest
from test.helper import TestHelper
from mediafile import MediaFile
from beets.test.helper import TestHelper
from beets.util import displayable_path

View file

@ -14,11 +14,11 @@
import os
import unittest
from test import _common
from test.helper import TestHelper
from unittest.mock import Mock, patch
from beets import library
from beets.test import _common
from beets.test.helper import TestHelper
from beets.util import _fsencoding, bytestring_path
from beetsplug.ipfs import IPFSPlugin

View file

@ -14,11 +14,11 @@
import unittest
from test.helper import TestHelper
from unittest.mock import patch
from beets import util
from beets.library import Item
from beets.test.helper import TestHelper
@patch("beets.util.command_output")

View file

@ -16,11 +16,11 @@
import unittest
from test import _common
from test.helper import TestHelper
from unittest.mock import Mock
from beets import config
from beets.test import _common
from beets.test.helper import TestHelper
from beetsplug import lastgenre

View file

@ -14,7 +14,8 @@
"""Tests for the 'limit' plugin."""
import unittest
from test.helper import TestHelper
from beets.test.helper import TestHelper
class LimitPluginTest(unittest.TestCase, TestHelper):

View file

@ -19,7 +19,6 @@ import itertools
import os
import re
import unittest
from test import _common
from unittest.mock import MagicMock, patch
import confuse
@ -27,6 +26,7 @@ import requests
from beets import logging
from beets.library import Item
from beets.test import _common
from beets.util import bytestring_path
from beetsplug import lyrics

View file

@ -14,7 +14,8 @@
import unittest
from test.helper import (
from beets.test.helper import (
AutotagStub,
ImportHelper,
TerminalImportSessionSetup,

View file

@ -14,16 +14,16 @@
import unittest
from test.helper import (
from unittest.mock import patch
from beets import config
from beets.library import Item
from beets.test.helper import (
TestHelper,
capture_log,
generate_album_info,
generate_track_info,
)
from unittest.mock import patch
from beets import config
from beets.library import Item
class MbsyncCliTest(unittest.TestCase, TestHelper):

View file

@ -14,11 +14,11 @@
import unittest
from test.helper import TestHelper
from unittest.mock import ANY, Mock, call, patch
from beets import util
from beets.library import Item
from beets.test.helper import TestHelper
from beetsplug.mpdstats import MPDStats

View file

@ -17,10 +17,10 @@
import os
import unittest
from test.helper import TestHelper
from unittest.mock import patch
from beets.library import Item
from beets.test.helper import TestHelper
from beetsplug import parentwork
work = {

View file

@ -4,10 +4,10 @@
import os
import platform
import unittest
from test._common import touch
from test.helper import TestHelper
from unittest.mock import Mock, patch
from beets.test._common import touch
from beets.test.helper import TestHelper
from beets.util import displayable_path
from beetsplug.permissions import (
check_permissions,

View file

@ -18,9 +18,9 @@
import os
import sys
import unittest
from test.helper import TestHelper, control_stdin
from unittest.mock import ANY, patch
from beets.test.helper import TestHelper, control_stdin
from beets.ui import UserError
from beets.util import open_anything

View file

@ -25,7 +25,6 @@ import threading
import time
import unittest
from contextlib import contextmanager
from test.helper import TestHelper
# Mock GstPlayer so that the forked process doesn't attempt to import gi:
from unittest import mock
@ -33,6 +32,7 @@ from unittest import mock
import confuse
import yaml
from beets.test.helper import TestHelper
from beets.util import bluelet, py3_path
from beetsplug import bpd

View file

@ -18,9 +18,9 @@ import shutil
import tempfile
import unittest
from shlex import quote
from test import _common, helper
import beets
from beets.test import _common, helper
class PlaylistTestHelper(helper.TestHelper):

View file

@ -1,8 +1,8 @@
import unittest
from test.helper import TestHelper
import responses
from beets.test.helper import TestHelper
from beetsplug.plexupdate import get_music_section, update_plex

View file

@ -18,12 +18,12 @@
import os
import shutil
import unittest
from test import _common
import mediafile
from beets.library import Item
from beets.plugins import BeetsPlugin
from beets.test import _common
from beets.util import bytestring_path, syspath
field_extension = mediafile.MediaField(

View file

@ -19,9 +19,9 @@
import math
import unittest
from random import Random
from test.helper import TestHelper
from beets import random
from beets.test.helper import TestHelper
class RandomTest(unittest.TestCase, TestHelper):

View file

@ -14,11 +14,11 @@
import unittest
from test.helper import TestHelper, has_program
from mediafile import MediaFile
from beets import config
from beets.test.helper import TestHelper, has_program
from beetsplug.replaygain import (
FatalGstreamerPluginReplayGainError,
GStreamerBackend,

View file

@ -17,14 +17,14 @@ import unittest
from os import path, remove
from shutil import rmtree
from tempfile import mkdtemp
from test import _common
from test.helper import TestHelper
from unittest.mock import MagicMock, Mock, PropertyMock
from beets import config
from beets.dbcore import OrQuery
from beets.dbcore.query import FixedFieldSort, MultipleSort, NullSort
from beets.library import Album, Item, parse_query_string
from beets.test import _common
from beets.test.helper import TestHelper
from beets.ui import UserError
from beets.util import CHAR_REPLACE, bytestring_path, py3_path, syspath
from beetsplug.smartplaylist import SmartPlaylistPlugin

View file

@ -3,14 +3,14 @@
import os
import unittest
from test import _common
from test.helper import TestHelper
from urllib.parse import parse_qs, urlparse
import responses
from beets import config
from beets.library import Item
from beets.test import _common
from beets.test.helper import TestHelper
from beetsplug import spotify

View file

@ -2,13 +2,13 @@
import unittest
from test import _common
from test.helper import TestHelper
from urllib.parse import parse_qs, urlparse
import responses
from beets import config
from beets.test import _common
from beets.test.helper import TestHelper
from beetsplug import subsonicupdate

View file

@ -2,9 +2,9 @@
import unittest
from test import _common
from beets import config
from beets.test import _common
from beetsplug.the import FORMAT, PATTERN_A, PATTERN_THE, ThePlugin

View file

@ -17,9 +17,9 @@ import os.path
import unittest
from shutil import rmtree
from tempfile import mkdtemp
from test.helper import TestHelper
from unittest.mock import Mock, call, patch
from beets.test.helper import TestHelper
from beets.util import bytestring_path, syspath
from beetsplug.thumbnails import (
LARGE_DIR,

View file

@ -16,10 +16,11 @@
import time
import unittest
from datetime import datetime
from test.helper import TestHelper
from confuse import ConfigValueError
from beets.test.helper import TestHelper
class TypesPluginTest(unittest.TestCase, TestHelper):
def setUp(self):

View file

@ -6,10 +6,10 @@ import os.path
import platform
import shutil
import unittest
from test import _common
from beets import logging
from beets.library import Album, Item
from beets.test import _common
from beetsplug import web

View file

@ -2,11 +2,11 @@
import unittest
from test.helper import TestHelper, control_stdin
from mediafile import MediaFile
from beets.library import Item
from beets.test.helper import TestHelper, control_stdin
from beets.util import syspath
from beetsplug.zero import ZeroPlugin

View file

@ -17,10 +17,10 @@
import os
import unittest
from test import _common
from test.helper import TestHelper
from unittest.mock import patch
from beets.test import _common
from beets.test.helper import TestHelper
from beets.util import command_output, syspath
from beets.util.artresizer import IMBackend, PILBackend

View file

@ -17,12 +17,12 @@
import re
import unittest
from test import _common
from beets import autotag, config
from beets.autotag import AlbumInfo, TrackInfo, match
from beets.autotag.hooks import Distance, string_dist
from beets.library import Item
from beets.test import _common
from beets.util import plurality

View file

@ -2,13 +2,13 @@ import os
import unittest
from shutil import rmtree
from tempfile import mkdtemp
from test.helper import TestHelper
from unittest.mock import patch
import yaml
from beets import config, ui
from beets.library import Library
from beets.test.helper import TestHelper
class ConfigCommandTest(unittest.TestCase, TestHelper):

View file

@ -18,7 +18,6 @@
import time
import unittest
from datetime import datetime, timedelta
from test import _common
from beets.dbcore.query import (
DateInterval,
@ -26,6 +25,7 @@ from beets.dbcore.query import (
InvalidQueryArgumentValueError,
_parse_periods,
)
from beets.test import _common
def _date(string):

View file

@ -20,9 +20,9 @@ import shutil
import sqlite3
import unittest
from tempfile import mkstemp
from test import _common
from beets import dbcore
from beets.test import _common
# Fixture: concrete database and model classes. For migration tests, we
# have multiple models with different numbers of fields.

View file

@ -20,11 +20,11 @@ import shutil
import stat
import unittest
from os.path import join
from test import _common
from test._common import item, touch
import beets.library
from beets import util
from beets.test import _common
from beets.test._common import item, touch
from beets.util import MoveOperation, bytestring_path, syspath

View file

@ -25,14 +25,6 @@ import unittest
from io import StringIO
from tarfile import TarFile
from tempfile import mkstemp
from test import _common
from test.helper import (
AutotagStub,
ImportHelper,
TestHelper,
capture_log,
has_program,
)
from unittest.mock import Mock, patch
from zipfile import ZipFile
@ -41,6 +33,14 @@ from mediafile import MediaFile
from beets import config, importer, logging, util
from beets.autotag import AlbumInfo, AlbumMatch, TrackInfo
from beets.importer import albums_in_dir
from beets.test import _common
from beets.test.helper import (
AutotagStub,
ImportHelper,
TestHelper,
capture_log,
has_program,
)
from beets.util import bytestring_path, displayable_path, py3_path, syspath

View file

@ -24,15 +24,15 @@ import sys
import time
import unicodedata
import unittest
from test import _common
from test._common import item
from test.helper import TestHelper
from mediafile import MediaFile, UnreadableFileError
import beets.dbcore.query
import beets.library
from beets import config, plugins, util
from beets.test import _common
from beets.test._common import item
from beets.test.helper import TestHelper
from beets.util import bytestring_path, syspath
# Shortcut to path normalization.

View file

@ -5,12 +5,12 @@ import sys
import threading
import unittest
from io import StringIO
from test import _common, helper
from test._common import TestCase
import beets.logging as blog
import beetsplug
from beets import plugins, ui
from beets.test import _common, helper
from beets.test._common import TestCase
class LoggingTest(TestCase):

View file

@ -19,8 +19,8 @@ import unittest
from os import path
from shutil import rmtree
from tempfile import mkdtemp
from test._common import RSRC
from beets.test._common import RSRC
from beets.util import bytestring_path
from beets.util.m3u import EmptyPlaylistError, M3UFile

View file

@ -16,11 +16,11 @@
"""
import unittest
from test import _common
from unittest import mock
from beets import config
from beets.autotag import mb
from beets.test import _common
class MBAlbumInfoTest(_common.TestCase):

View file

@ -18,10 +18,10 @@ import platform
import time
import unittest
from datetime import datetime
from test import _common
from test.helper import TestHelper
from beets.library import Item
from beets.test import _common
from beets.test.helper import TestHelper
from beets.util import py3_path

View file

@ -17,9 +17,6 @@ import itertools
import os
import shutil
import unittest
from test import helper
from test._common import RSRC
from test.helper import AutotagStub, ImportHelper, TerminalImportSessionSetup
from unittest.mock import ANY, Mock, patch
from mediafile import MediaFile
@ -34,6 +31,13 @@ from beets.importer import (
)
from beets.library import Item
from beets.plugins import MetadataSourcePlugin
from beets.test import helper
from beets.test._common import RSRC
from beets.test.helper import (
AutotagStub,
ImportHelper,
TerminalImportSessionSetup,
)
from beets.util import bytestring_path, displayable_path, syspath
from beets.util.id_extractors import (
beatport_id_regex,

View file

@ -20,7 +20,6 @@ import sys
import unittest
from contextlib import contextmanager
from functools import partial
from test import _common, helper
import beets.library
from beets import dbcore, util
@ -31,6 +30,7 @@ from beets.dbcore.query import (
ParsingError,
)
from beets.library import Item, Library
from beets.test import _common, helper
from beets.util import syspath
# Because the absolute path begins with something like C:, we

View file

@ -16,10 +16,10 @@
"""
import unittest
from test import _common
import beets.library
from beets import config, dbcore
from beets.test import _common
# A test case class providing a library with some dummy data and some

View file

@ -22,8 +22,6 @@ import shutil
import subprocess
import sys
import unittest
from test import _common
from test.helper import TestHelper, capture_stdout, control_stdin, has_program
from unittest.mock import Mock, patch
from confuse import ConfigError
@ -31,6 +29,13 @@ from mediafile import MediaFile
from beets import autotag, config, library, plugins, ui, util
from beets.autotag.match import distance
from beets.test import _common
from beets.test.helper import (
TestHelper,
capture_stdout,
control_stdin,
has_program,
)
from beets.ui import commands
from beets.util import MoveOperation, syspath

View file

@ -19,9 +19,9 @@
import os
import shutil
import unittest
from test import _common
from beets import library, ui
from beets.test import _common
from beets.ui import commands
from beets.util import syspath

View file

@ -20,7 +20,8 @@ test_importer module. But here the test importer inherits from
import unittest
from test import test_importer
from test.helper import TerminalImportSessionSetup
from beets.test.helper import TerminalImportSessionSetup
class NonAutotaggedImportTest(

View file

@ -20,10 +20,10 @@ import shutil
import unittest
from copy import deepcopy
from random import random
from test import _common
from test.helper import control_stdin
from beets import config, ui
from beets.test import _common
from beets.test.helper import control_stdin
class InputMethodsTest(_common.TestCase):

View file

@ -20,10 +20,10 @@ import re
import subprocess
import sys
import unittest
from test import _common
from unittest.mock import Mock, patch
from beets import util
from beets.test import _common
class UtilTest(unittest.TestCase):

View file

@ -15,9 +15,9 @@
"""Tests for the virtual filesystem builder.."""
import unittest
from test import _common
from beets import library, vfs
from beets.test import _common
class VFSTest(_common.TestCase):