echonest: test different methods to fetch songs

This commit is contained in:
Thomas Scholtes 2014-12-02 11:19:47 +01:00
parent f4fdd66b81
commit 575740f5a5
2 changed files with 107 additions and 28 deletions

3
.gitignore vendored
View file

@ -7,6 +7,7 @@
.tox .tox
.coverage .coverage
.idea .idea
.ackrc
# file patterns # file patterns
@ -32,4 +33,6 @@ beets.egg-info/*
build/* build/*
docs/_build/* docs/_build/*
man man
htmlcov/*
.noseids
*.egg *.egg

View file

@ -13,9 +13,10 @@
# included in all copies or substantial portions of the Software. # included in all copies or substantial portions of the Software.
import os.path
from mock import Mock, patch from mock import Mock, patch
from _common import unittest from _common import unittest, RSRC
from helper import TestHelper from helper import TestHelper
from beets.library import Item from beets.library import Item
@ -30,6 +31,8 @@ class EchonestCliTest(unittest.TestCase, TestHelper):
self.setup_beets() self.setup_beets()
self.load_plugins('echonest') self.load_plugins('echonest')
# Prevent 'beet echonest' from writing files
self.config['import']['write'] = False
def tearDown(self): def tearDown(self):
self.teardown_beets() self.teardown_beets()
@ -38,49 +41,122 @@ class EchonestCliTest(unittest.TestCase, TestHelper):
@patch.object(Item, 'write') @patch.object(Item, 'write')
@patch('pyechonest.song.profile') @patch('pyechonest.song.profile')
@patch('pyechonest.track.track_from_id') @patch('pyechonest.track.track_from_id')
def test_store_data(self, echonest_track, echonest_profile, item_write): def test_mbid_profile(self, echonest_track, echonest_profile, item_write):
profile = Mock( """Retrieve song info from MusicBrainz ID."""
artist_name='artist', item = self.add_item(title='title', length=10, mb_trackid='1')
title='title', profile = self.profile(item, energy=0.5, tempo=120, key=2, mode=0)
id='echonestid',
audio_summary={
'duration': 10,
'energy': 0.5,
'liveness': 0.5,
'loudness': 0.5,
'speechiness': 0.5,
'danceability': 0.5,
'tempo': 120,
'key': 2,
'mode': 0
},
)
echonest_profile.return_value = [profile] echonest_profile.return_value = [profile]
echonest_track.return_value = Mock(song_id='echonestid') echonest_track.return_value = Mock(song_id='echonestid')
item = Item( self.assertNotIn('energy', item)
mb_trackid='01234', self.assertNotEqual(item['bpm'], 120)
artist='artist',
title='title',
length=10,
)
item.add(self.lib)
self.assertNotIn('danceability', item)
self.assertNotIn('initialkey', item) self.assertNotIn('initialkey', item)
self.run_command('echonest') self.run_command('echonest')
item.load() item.load()
self.assertEqual(item['danceability'], 0.5) self.assertEqual(item['energy'], 0.5)
self.assertEqual(item['liveness'], 0.5)
self.assertEqual(item['bpm'], 120) self.assertEqual(item['bpm'], 120)
self.assertEqual(item['initial_key'], 'C#m') self.assertEqual(item['initial_key'], 'C#m')
@patch('pyechonest.track.track_from_id')
@patch('pyechonest.song.search')
def test_song_search(self, echonest_search, echonest_track):
item = self.add_item(title='title', length=10, mb_trackid='1')
echonest_search.return_value = [self.profile(item, energy=0.1)]
echonest_track.return_value = []
self.run_command('echonest')
item.load()
self.assertEqual(item['energy'], 0.1)
self.assertEqual(1, echonest_track.call_count)
@patch('pyechonest.song.profile')
@patch('pyechonest.song.search')
@patch('pyechonest.track.track_from_filename')
def test_analyze(self, echonest_track, echonest_search, echonest_profile):
item = self.add_item(title='title', length=10,
path=os.path.join(RSRC, 'min.mp3'))
echonest_search.return_value = []
echonest_profile.return_value = [self.profile(item, energy=0.2)]
echonest_track.return_value = self.track(item)
self.run_command('echonest')
item.load()
self.assertEqual(item['energy'], 0.2)
self.assertEqual(1, echonest_search.call_count)
self.assertEqual(item.path,
echonest_track.call_args[1]['filename'])
@patch('pyechonest.song.profile')
@patch('pyechonest.song.search')
@patch('pyechonest.track.track_from_filename')
def test_analyze_convert(self, echonest_track, echonest_search,
echonest_profile):
item = self.add_item(title='title', length=10, format='FLAC',
path=os.path.join(RSRC, 'min.flac'))
echonest_search.return_value = []
echonest_profile.return_value = [self.profile(item, energy=0.2)]
echonest_track.return_value = self.track(item)
self.run_command('echonest')
item.load()
self.assertEqual(item['energy'], 0.2)
# Assert uploaded file was converted
self.assertNotEqual(item.path,
echonest_track.call_args[1]['filename'])
@patch('pyechonest.song.profile')
@patch('pyechonest.song.search')
@patch('pyechonest.track.track_from_filename')
# Force truncation
@patch('beetsplug.echonest.UPLOAD_MAX_SIZE', 0)
def test_analyze_truncate(self, echonest_track, echonest_search,
echonest_profile):
item = self.add_item(title='title', length=10, format='MP3',
path=os.path.join(RSRC, 'min.mp3'))
echonest_search.return_value = []
echonest_profile.return_value = [self.profile(item, energy=0.2)]
echonest_track.return_value = self.track(item)
self.run_command('echonest')
item.load()
self.assertEqual(item['energy'], 0.2)
self.assertEqual(1, echonest_search.call_count)
self.assertNotEqual(item.path,
echonest_track.call_args[1]['filename'])
def test_custom_field_range_query(self): def test_custom_field_range_query(self):
item = Item(liveness=2.2) item = Item(liveness=2.2)
item.add(self.lib) item.add(self.lib)
item = self.lib.items('liveness:2.2..3').get() item = self.lib.items('liveness:2.2..3').get()
self.assertEqual(item['liveness'], 2.2) self.assertEqual(item['liveness'], 2.2)
def profile(self, item, **values):
"""Return a mock Echonest Profile object.
The fields are set to match the item. Additional values are
passed to the `audio_summary` dictionary of the profile.
"""
audio_summary = {'duration': item.length}
audio_summary.update(values)
return Mock(
artist_name=item.artist,
title=item.title,
id='echonestid',
audio_summary=audio_summary
)
def track(self, item, **values):
"""Return a mock Echonest Track object.
"""
values.update(
duration=item.length,
artist_name=item.artist,
title=item.title,
song_id='echonestid',
)
return Mock(**values)
def suite(): def suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)