Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve test coverage #32

Merged
merged 5 commits into from Jul 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
87 changes: 81 additions & 6 deletions test/cli_test.py
Expand Up @@ -10,6 +10,9 @@


class DocTest(TestHelper):
"""Test alternatives in a larger-scale scenario with transcoding and
multiple changes to the library.
"""

def test_external(self):
external_dir = os.path.join(self.mkdtemp(), 'myplayer')
Expand Down Expand Up @@ -69,7 +72,13 @@ def test_external(self):
self.assertFalse(os.path.isfile(external_from_ogg))
self.assertFileTag(external_beet, b'ISAAC')

def test_symlink_view(self):

class SymlinkViewTest(TestHelper):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs:

"""Test alternatives with the ``link`` format producing symbolic links.
"""

"""Test alternatives with the ``link`` format producing symbolic links.
"""

def setUp(self):
super(SymlinkViewTest, self).setUp()
self.set_paths_config({
'default': '$artist/$album/$title'
})
Expand All @@ -79,18 +88,41 @@ def test_symlink_view(self):
'formats': 'link',
}
}
self.alt_config = self.config['alternatives']['by-year']

def test_add_move_remove_album(self):
geigerzaehler marked this conversation as resolved.
Show resolved Hide resolved
"""Test the symlinks are created and deleted
* An album is added
* The path of the alternative collection is changed
* The query of the alternative collection is changed such that the
album does not match it anymore.
"""
self.add_album(artist='Michael Jackson', album='Thriller',
year='1990', original_year='1982')

self.runcli('alt', 'update', 'by-year')

self.add_album(artist='Michael Jackson', album='Thriller', year='1982')
by_year_path = self.lib_path(b'by-year/1990/Thriller/track 1.mp3')
target_path = self.lib_path(b'Michael Jackson/Thriller/track 1.mp3')
self.assertSymlink(by_year_path, target_path)

self.alt_config['paths']['default'] = '$original_year/$album/$title'
self.runcli('alt', 'update', 'by-year')

self.assertSymlink(
self.lib_path(b'by-year/1982/Thriller/track 1.mp3'),
self.lib_path(b'Michael Jackson/Thriller/track 1.mp3'),
)
by_orig_year_path = self.lib_path(b'by-year/1982/Thriller/track 1.mp3')
self.assertIsNotFile(by_year_path)
self.assertSymlink(by_orig_year_path, target_path)

self.alt_config['query'] = u'some_field::foobar'
self.runcli('alt', 'update', 'by-year')

self.assertIsNotFile(by_orig_year_path)


class ExternalCopyTest(TestHelper):
"""Test alternatives with empty ``format `` option, i.e. only copying
without transcoding.
"""

def setUp(self):
super(ExternalCopyTest, self).setUp()
Expand Down Expand Up @@ -288,6 +320,9 @@ def touch_art(item, image_path):


class ExternalConvertTest(TestHelper):
"""Test alternatives with non-empty ``format`` option, i.e. transcoding
some of the files.
"""

def setUp(self):
super(ExternalConvertTest, self).setUp()
Expand Down Expand Up @@ -373,7 +408,47 @@ def test_no_move_on_extension_change(self):
self.assertFileTag(converted_path, b'ISMP3')


class ExternalConvertWorkerTest(TestHelper):
"""Test alternatives with non-empty ``format`` option, i.e. transcoding
some of the files. In contrast to the previous test, these test do use
the parallelizing ``beetsplug.alternatives.Worker``.
"""

def setUp(self):
super(ExternalConvertWorkerTest, self).setUp(mock_worker=False)
external_dir = self.mkdtemp()
self.config['convert']['formats'] = {
'ogg': 'bash -c "cp \'{source}\' \'$dest\'"'.format(
# The convert plugin will encode this again using arg_encoding
source=self.item_fixture_path('ogg').decode(
util.arg_encoding()))
}
self.config['alternatives'] = {
'myexternal': {
'directory': external_dir,
'query': u'myexternal:true',
'formats': 'ogg'
}
}

def test_convert_multiple(self):
items = [self.add_track(title="track {}".format(i),
myexternal='true',
format='m4a',
) for i in range(24)
]
self.runcli('alt', 'update', 'myexternal')
for item in items:
item.load()
converted_path = self.get_path(item)
self.assertMediaFileFields(converted_path,
type='ogg', title=item.title)


class ExternalRemovableTest(TestHelper):
"""Test whether alternatives properly detects ``removable`` collections
and performs the expected user queries before doing anything.
"""

def setUp(self):
super(ExternalRemovableTest, self).setUp()
Expand Down
51 changes: 39 additions & 12 deletions test/helper.py
Expand Up @@ -128,10 +128,18 @@ def assertIsFile(self, path):
))

def assertIsNotFile(self, path):
"""Asserts that `path` is neither a regular file (``os.path.isfile``,
follows symlinks and returns False for a broken symlink) nor a symlink
(``os.path.islink``, returns True for both valid and broken symlinks).
"""
self.assertFalse(os.path.isfile(syspath(path)),
msg=u'Path is a file: {0}'.format(
displayable_path(path)
))
self.assertFalse(os.path.islink(syspath(path)),
msg=u'Path is a symlink: {0}'.format(
displayable_path(path)
))

def assertSymlink(self, link, target):
self.assertTrue(os.path.islink(syspath(link)),
Expand Down Expand Up @@ -175,13 +183,33 @@ def assertHasNoEmbeddedArtwork(self, path):
self.assertIsNone(mediafile.art,
msg=u'MediaFile has embedded artwork')

def assertMediaFileFields(self, path, **kwargs):
mediafile = MediaFile(syspath(path))
for k, v in kwargs.items():
actual = getattr(mediafile, k)
self.assertTrue(actual == v,
msg=u"MediaFile has tag {k}='{actual}' "
u"instead of '{expected}'".format(
k=k, actual=actual, expected=v)
)


class TestHelper(TestCase, Assertions, MediaFileAssertions):

def setUp(self):
patcher = patch('beetsplug.alternatives.Worker', new=MockedWorker)
patcher.start()
self.addCleanup(patcher.stop)
def setUp(self, mock_worker=True):
geigerzaehler marked this conversation as resolved.
Show resolved Hide resolved
"""Setup required for running test. Must be called before
running any tests.

If ``mock_worker`` is ``True`` the simple non-threaded
``MockedWorker`` is used to run file conversion commands. In
particular, in contrast to the actual conversion routine from the
``convert`` plugin, it will not attempt to write tags to the output
files. Thus, the 'converted' files need not be valid audio files.
"""
if mock_worker:
patcher = patch('beetsplug.alternatives.Worker', new=MockedWorker)
patcher.start()
self.addCleanup(patcher.stop)

self._tempdirs = []
plugins._classes = set([alternatives.AlternativesPlugin,
Expand Down Expand Up @@ -258,6 +286,11 @@ def lib_path(self, path):
return os.path.join(self.libdir,
path.replace(b'/', bytestring_path(os.sep)))

def item_fixture_path(self, fmt):
assert(fmt in 'mp3 m4a ogg'.split())
return os.path.join(self.fixture_dir,
bytestring_path('min.' + fmt.lower()))

def add_album(self, **kwargs):
values = {
'title': 'track 1',
Expand All @@ -266,9 +299,7 @@ def add_album(self, **kwargs):
'format': 'mp3',
}
values.update(kwargs)
ext = values.pop('format').lower()
item = Item.from_path(os.path.join(self.fixture_dir,
bytestring_path('min.' + ext)))
item = Item.from_path(self.item_fixture_path(values.pop('format')))
item.add(self.lib)
item.update(values)
item.move(MoveOperation.COPY)
Expand All @@ -286,12 +317,8 @@ def add_track(self, **kwargs):
'format': 'mp3',
}
values.update(kwargs)
assert(values['format'] in 'mp3 m4a ogg'.split())

item = Item.from_path(os.path.join(
self.fixture_dir,
bytestring_path('min.' + values['format'])
))
item = Item.from_path(self.item_fixture_path(values.pop('format')))
item.add(self.lib)
item.update(values)
item.move(MoveOperation.COPY)
Expand Down