tests: obviate on-disk test library

This commit is contained in:
Adrian Sampson 2013-09-23 10:57:17 -07:00
parent 9993993cab
commit 4d0db3fcb4
4 changed files with 116 additions and 131 deletions

View file

@ -126,6 +126,16 @@ class TestCase(unittest.TestCase):
self.assertFalse(os.path.exists(path),
'file exists: %s' % path)
class LibTestCase(TestCase):
"""A test case that includes an in-memory library object (`lib`) and
an item added to the library (`i`).
"""
def setUp(self):
super(LibTestCase, self).setUp()
self.lib = beets.library.Library(':memory:')
self.i = item(self.lib)
# Mock timing.

Binary file not shown.

View file

@ -33,28 +33,11 @@ from beets import config
TEMP_LIB = os.path.join(_common.RSRC, 'test_copy.blb')
def lib():
shutil.copy(os.path.join(_common.RSRC, 'test.blb'), TEMP_LIB)
return beets.library.Library(TEMP_LIB)
def remove_lib():
if os.path.exists(TEMP_LIB):
os.unlink(TEMP_LIB)
def boracay(l):
return beets.library.Item(l,
**l._connection().execute('select * from items where id=3').fetchone()
)
# Shortcut to path normalization.
np = util.normpath
class LoadTest(_common.TestCase):
def setUp(self):
super(LoadTest, self).setUp()
self.lib = lib()
self.i = boracay(self.lib)
def tearDown(self):
super(LoadTest, self).tearDown()
self.lib._connection().close()
remove_lib()
class LoadTest(_common.LibTestCase):
def test_load_restores_data_from_db(self):
original_title = self.i.title
self.i.title = 'something'
@ -63,25 +46,18 @@ class LoadTest(_common.TestCase):
def test_load_clears_dirty_flags(self):
self.i.artist = 'something'
self.assertTrue('artist' in self.i._dirty)
self.i.load()
self.assertTrue('artist' not in self.i._dirty)
class StoreTest(_common.TestCase):
def setUp(self):
super(StoreTest, self).setUp()
self.lib = lib()
self.i = boracay(self.lib)
def tearDown(self):
super(StoreTest, self).tearDown()
self.lib._connection().close()
remove_lib()
class StoreTest(_common.LibTestCase):
def test_store_changes_database_value(self):
self.i.year = 1987
self.i.store()
new_year = self.lib._connection().execute(
'select year from items where '
'title="Boracay"').fetchone()['year']
'title="the title"').fetchone()['year']
self.assertEqual(new_year, 1987)
def test_store_only_writes_dirty_fields(self):
@ -90,7 +66,7 @@ class StoreTest(_common.TestCase):
self.i.store()
new_genre = self.lib._connection().execute(
'select genre from items where '
'title="Boracay"').fetchone()['genre']
'title="the title"').fetchone()['genre']
self.assertEqual(new_genre, original_genre)
def test_store_clears_dirty_flags(self):
@ -98,14 +74,12 @@ class StoreTest(_common.TestCase):
self.i.store()
self.assertTrue('composer' not in self.i._dirty)
class AddTest(_common.TestCase):
def setUp(self):
super(AddTest, self).setUp()
self.lib = beets.library.Library(':memory:')
self.i = item()
def tearDown(self):
super(AddTest, self).tearDown()
self.lib._connection().close()
def test_item_add_inserts_row(self):
self.lib.add(self.i)
@ -122,21 +96,14 @@ class AddTest(_common.TestCase):
'where composer="the composer"').fetchone()['grouping']
self.assertEqual(new_grouping, self.i.grouping)
class RemoveTest(_common.TestCase):
def setUp(self):
super(RemoveTest, self).setUp()
self.lib = lib()
self.i = boracay(self.lib)
def tearDown(self):
super(RemoveTest, self).tearDown()
self.lib._connection().close()
remove_lib()
class RemoveTest(_common.LibTestCase):
def test_remove_deletes_from_db(self):
self.i.remove()
c = self.lib._connection().execute('select * from items where id=3')
c = self.lib._connection().execute('select * from items')
self.assertEqual(c.fetchone(), None)
class GetSetTest(_common.TestCase):
def setUp(self):
super(GetSetTest, self).setUp()
@ -157,6 +124,7 @@ class GetSetTest(_common.TestCase):
def test_invalid_field_raises_attributeerror(self):
self.assertRaises(AttributeError, getattr, self.i, 'xyzzy')
class DestinationTest(_common.TestCase):
def setUp(self):
super(DestinationTest, self).setUp()
@ -458,6 +426,7 @@ class DestinationTest(_common.TestCase):
dest = self.i.destination(platform='linux2', fragment=True)
self.assertEqual(dest, u'foo.caf\xe9')
class PathFormattingMixin(object):
"""Utilities for testing path formatting."""
def _setf(self, fmt):
@ -467,6 +436,7 @@ class PathFormattingMixin(object):
i = self.i
self.assertEqual(i.destination(pathmod=posixpath), dest)
class DestinationFunctionTest(_common.TestCase, PathFormattingMixin):
def setUp(self):
super(DestinationFunctionTest, self).setUp()
@ -518,6 +488,7 @@ class DestinationFunctionTest(_common.TestCase, PathFormattingMixin):
self._setf(u'%foo{bar}')
self._assert_dest('/base/%foo{bar}')
class DisambiguationTest(_common.TestCase, PathFormattingMixin):
def setUp(self):
super(DisambiguationTest, self).setUp()
@ -578,6 +549,7 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin):
self._setf(u'foo%aunique{albumartist album,albumtype}/$title')
self._assert_dest('/base/foo [foo_bar]/the title', self.i1)
class PathConversionTest(_common.TestCase):
def test_syspath_windows_format(self):
path = ntpath.join('a', 'b', 'c')
@ -608,6 +580,7 @@ class PathConversionTest(_common.TestCase):
outpath = self._windows_bytestring_path(path)
self.assertEqual(outpath, u'C:\\caf\xe9'.encode('utf8'))
class PluginDestinationTest(_common.TestCase):
# Mock the plugins.template_values(item) function.
def _template_values(self, item):
@ -651,6 +624,7 @@ class PluginDestinationTest(_common.TestCase):
}
self._assert_dest('the artist bar_baz')
class MigrationTest(_common.TestCase):
"""Tests the ability to change the database schema between
versions.
@ -758,6 +732,7 @@ class MigrationTest(_common.TestCase):
album = c.fetchone()
self.assertEqual(album['albumartist'], 'theartist')
class AlbumInfoTest(_common.TestCase):
def setUp(self):
super(AlbumInfoTest, self).setUp()
@ -845,6 +820,7 @@ class AlbumInfoTest(_common.TestCase):
self.i.remove()
self.assertEqual(len(self.lib.albums()), 0)
class ArtDestinationTest(_common.TestCase):
def setUp(self):
super(ArtDestinationTest, self).setUp()
@ -871,6 +847,7 @@ class ArtDestinationTest(_common.TestCase):
art = self.ai.art_destination('something.jpg')
self.assert_('artYimage' in art)
class PathStringTest(_common.TestCase):
def setUp(self):
super(PathStringTest, self).setUp()
@ -954,6 +931,7 @@ class PathStringTest(_common.TestCase):
alb = self.lib.get_album(alb.id)
self.assert_(isinstance(alb.artpath, str))
class PathTruncationTest(_common.TestCase):
def test_truncate_bytestring(self):
p = util.truncate_path('abcde/fgh', posixpath, 4)
@ -967,6 +945,7 @@ class PathTruncationTest(_common.TestCase):
p = util.truncate_path(u'abcde/fgh.ext', posixpath, 5)
self.assertEqual(p, u'abcde/f.ext')
class MtimeTest(_common.TestCase):
def setUp(self):
super(MtimeTest, self).setUp()
@ -1001,6 +980,7 @@ class MtimeTest(_common.TestCase):
self.i.read()
self.assertGreaterEqual(self.i.mtime, self._mtime())
class ImportTimeTest(_common.TestCase):
def setUp(self):
super(ImportTimeTest, self).setUp()
@ -1016,8 +996,10 @@ class ImportTimeTest(_common.TestCase):
self.singleton = item(self.lib)
self.assertGreater(self.singleton.added, 0)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
if __name__ == '__main__':
unittest.main(defaultTest='suite')

View file

@ -22,7 +22,6 @@ import beets.library
pqp = beets.library.parse_query_part
some_item = _common.item()
class QueryParseTest(unittest.TestCase):
def test_one_basic_term(self):
@ -70,10 +69,11 @@ class QueryParseTest(unittest.TestCase):
r = ('year', '1999..2010', beets.library.NumericQuery)
self.assertEqual(pqp(q), r)
class AnyFieldQueryTest(unittest.TestCase):
def setUp(self):
self.lib = beets.library.Library(':memory:')
self.lib.add(some_item)
_common.item(self.lib)
def test_no_restriction(self):
q = beets.library.AnyFieldQuery('title', beets.library.ITEM_KEYS,
@ -90,25 +90,44 @@ class AnyFieldQueryTest(unittest.TestCase):
beets.library.SubstringQuery)
self.assertEqual(self.lib.items(q).get(), None)
# Convenient asserts for matching items.
class AssertsMixin(object):
def assert_matched(self, results, titles):
self.assertEqual([i.title for i in results], titles)
# A test case class providing a library with some dummy data and some
# assertions involving that data.
class DummyDataTestCase(_common.TestCase, AssertsMixin):
def setUp(self):
super(DummyDataTestCase, self).setUp()
self.lib = beets.library.Library(':memory:')
items = [_common.item() for _ in range(3)]
items[0].title = 'foo bar'
items[0].artist = 'one'
items[0].album = 'baz'
items[0].year = 2001
items[1].title = 'baz qux'
items[1].artist = 'two'
items[1].album = 'baz'
items[1].year = 2002
items[2].title = 'beets 4 eva'
items[2].artist = 'three'
items[2].album = 'foo'
items[2].year = 2003
for item in items:
self.lib.add(item)
self.lib.add_album(items[:2])
def assert_matched_all(self, results):
self.assert_matched(results, [
'Littlest Things',
'Take Pills',
'Lovers Who Uncover',
'Boracay',
'foo bar',
'baz qux',
'beets 4 eva',
])
class GetTest(unittest.TestCase, AssertsMixin):
def setUp(self):
self.lib = beets.library.Library(
os.path.join(_common.RSRC, 'test.blb')
)
class GetTest(DummyDataTestCase):
def test_get_empty(self):
q = ''
results = self.lib.items(q)
@ -120,24 +139,24 @@ class GetTest(unittest.TestCase, AssertsMixin):
self.assert_matched_all(results)
def test_get_one_keyed_term(self):
q = 'artist:Lil'
q = 'title:qux'
results = self.lib.items(q)
self.assert_matched(results, ['Littlest Things'])
self.assert_matched(results, ['baz qux'])
def test_get_one_keyed_regexp(self):
q = r'artist::L.+y'
q = r'artist::t.+r'
results = self.lib.items(q)
self.assert_matched(results, ['Littlest Things'])
self.assert_matched(results, ['beets 4 eva'])
def test_get_one_unkeyed_term(self):
q = 'Terry'
q = 'three'
results = self.lib.items(q)
self.assert_matched(results, ['Boracay'])
self.assert_matched(results, ['beets 4 eva'])
def test_get_one_unkeyed_regexp(self):
q = r':y$'
q = r':x$'
results = self.lib.items(q)
self.assert_matched(results, ['Boracay'])
self.assert_matched(results, ['baz qux'])
def test_get_no_matches(self):
q = 'popebear'
@ -152,101 +171,91 @@ class GetTest(unittest.TestCase, AssertsMixin):
self.assert_matched(results, [])
def test_term_case_insensitive(self):
q = 'UNCoVER'
q = 'oNE'
results = self.lib.items(q)
self.assert_matched(results, ['Lovers Who Uncover'])
self.assert_matched(results, ['foo bar'])
def test_regexp_case_sensitive(self):
q = r':UNCoVER'
q = r':oNE'
results = self.lib.items(q)
self.assert_matched(results, [])
q = r':Uncover'
q = r':one'
results = self.lib.items(q)
self.assert_matched(results, ['Lovers Who Uncover'])
self.assert_matched(results, ['foo bar'])
def test_term_case_insensitive_with_key(self):
q = 'album:stiLL'
q = 'artist:thrEE'
results = self.lib.items(q)
self.assert_matched(results, ['Littlest Things'])
self.assert_matched(results, ['beets 4 eva'])
def test_key_case_insensitive(self):
q = 'ArTiST:Allen'
q = 'ArTiST:three'
results = self.lib.items(q)
self.assert_matched(results, ['Littlest Things'])
self.assert_matched(results, ['beets 4 eva'])
def test_unkeyed_term_matches_multiple_columns(self):
q = 'little'
q = 'baz'
results = self.lib.items(q)
self.assert_matched(results, [
'Littlest Things',
'Lovers Who Uncover',
'Boracay',
'foo bar',
'baz qux',
])
def test_unkeyed_regexp_matches_multiple_columns(self):
q = r':^T'
q = r':z$'
results = self.lib.items(q)
self.assert_matched(results, [
'Take Pills',
'Lovers Who Uncover',
'Boracay',
'foo bar',
'baz qux',
])
def test_keyed_term_matches_only_one_column(self):
q = 'artist:little'
q = 'title:baz'
results = self.lib.items(q)
self.assert_matched(results, [
'Lovers Who Uncover',
'Boracay',
])
self.assert_matched(results, ['baz qux'])
def test_keyed_regexp_matches_only_one_column(self):
q = r'album::\sS'
q = r'title::baz'
results = self.lib.items(q)
self.assert_matched(results, [
'Littlest Things',
'Lovers Who Uncover',
'baz qux',
])
def test_multiple_terms_narrow_search(self):
q = 'little ones'
q = 'qux baz'
results = self.lib.items(q)
self.assert_matched(results, [
'Lovers Who Uncover',
'Boracay',
'baz qux',
])
def test_multiple_regexps_narrow_search(self):
q = r':\sS :^T'
q = r':baz :qux'
results = self.lib.items(q)
self.assert_matched(results, ['Lovers Who Uncover'])
self.assert_matched(results, ['baz qux'])
def test_mixed_terms_regexps_narrow_search(self):
q = r':\sS lily'
q = r':baz qux'
results = self.lib.items(q)
self.assert_matched(results, ['Littlest Things'])
self.assert_matched(results, ['baz qux'])
def test_single_year(self):
q = 'year:2006'
q = 'year:2001'
results = self.lib.items(q)
self.assert_matched(results, [
'Littlest Things',
'Lovers Who Uncover',
])
self.assert_matched(results, ['foo bar'])
def test_year_range(self):
q = 'year:2000..2010'
q = 'year:2000..2002'
results = self.lib.items(q)
self.assert_matched(results, [
'Littlest Things',
'Take Pills',
'Lovers Who Uncover',
'foo bar',
'baz qux',
])
def test_bad_year(self):
q = 'year:delete from items'
self.assertRaises(ValueError, self.lib.items, q)
class MemoryGetTest(unittest.TestCase, AssertsMixin):
def setUp(self):
self.album_item = _common.item()
@ -315,6 +324,7 @@ class MemoryGetTest(unittest.TestCase, AssertsMixin):
results = self.lib.items(q)
self.assertFalse(results)
class MatchTest(unittest.TestCase):
def setUp(self):
self.item = _common.item()
@ -359,6 +369,7 @@ class MatchTest(unittest.TestCase):
q = beets.library.NumericQuery('bitrate', '200000..300000')
self.assertFalse(q.match(self.item))
class PathQueryTest(unittest.TestCase, AssertsMixin):
def setUp(self):
self.lib = beets.library.Library(':memory:')
@ -418,45 +429,25 @@ class PathQueryTest(unittest.TestCase, AssertsMixin):
results = self.lib.items(q)
self.assert_matched(results, ['path item'])
class BrowseTest(unittest.TestCase, AssertsMixin):
def setUp(self):
self.lib = beets.library.Library(
os.path.join(_common.RSRC, 'test.blb')
)
def test_album_list(self):
albums = list(self.lib.albums())
album_names = [a.album for a in albums]
for aname in ['Alright, Still', 'Person Pitch', 'Sing Song',
'Terry Tales & Fallen Gates EP']:
self.assert_(aname in album_names)
self.assertEqual(len(albums), 4)
def test_item_list(self):
items = self.lib.items()
self.assert_matched(items, [
'Littlest Things',
'Take Pills',
'Lovers Who Uncover',
'Boracay',
])
class DefaultSearchFieldsTest(DummyDataTestCase):
def test_albums_matches_album(self):
albums = list(self.lib.albums('person'))
albums = list(self.lib.albums('baz'))
self.assertEqual(len(albums), 1)
def test_albums_matches_albumartist(self):
albums = list(self.lib.albums('panda'))
albums = list(self.lib.albums(['album artist']))
self.assertEqual(len(albums), 1)
def test_items_matches_title(self):
items = self.lib.items('boracay')
self.assert_matched(items, ['Boracay'])
items = self.lib.items('beets')
self.assert_matched(items, ['beets 4 eva'])
def test_items_does_not_match_year(self):
items = self.lib.items('2007')
items = self.lib.items('2001')
self.assert_matched(items, [])
class StringParseTest(unittest.TestCase):
def test_single_field_query(self):
q = beets.library.AndQuery.from_string(u'albumtype:soundtrack')
@ -466,8 +457,10 @@ class StringParseTest(unittest.TestCase):
self.assertEqual(subq.field, 'albumtype')
self.assertEqual(subq.pattern, 'soundtrack')
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
if __name__ == '__main__':
unittest.main(defaultTest='suite')