Spaces:
Build error
Build error
Update README and TODO files for improved clarity and organization - Revised the project structure in the README to enhance readability and reflect recent changes, including the addition of new components and services. Updated the TODO file to provide a comprehensive test design plan, outlining key testing strategies and directory structure for better organization. This update aims to streamline future development efforts and facilitate collaboration on the BeatDebate application.
15980e5 | """ | |
| Tests for metadata models. | |
| Validates data integrity and logic within data models including: | |
| - Unified track creation from LastFM and Spotify sources | |
| - Track metadata merging | |
| - Underground score calculation | |
| """ | |
| import pytest | |
| from datetime import datetime | |
| from unittest.mock import Mock | |
| from src.models.metadata_models import ( | |
| UnifiedTrackMetadata, | |
| MetadataSource, | |
| merge_track_metadata | |
| ) | |
| from src.api.lastfm_client import TrackMetadata | |
| from src.api.spotify_client import SpotifyTrack | |
| class TestUnifiedTrackMetadata: | |
| """Test UnifiedTrackMetadata functionality.""" | |
| def test_unified_track_from_lastfm(self): | |
| """Ensures correct mapping from LastFmTrack to UnifiedTrackMetadata.""" | |
| # Create mock LastFM track | |
| lastfm_track = TrackMetadata( | |
| name="Paranoid Android", | |
| artist="Radiohead", | |
| mbid="test-mbid-123", | |
| url="https://last.fm/music/Radiohead/_/Paranoid+Android", | |
| tags=["alternative rock", "experimental", "progressive rock"], | |
| similar_tracks=["Exit Music (For a Film)", "Karma Police"], | |
| listeners=500000, | |
| playcount=2000000, | |
| summary="A classic Radiohead track" | |
| ) | |
| # Convert to unified metadata | |
| unified_track = UnifiedTrackMetadata.from_lastfm(lastfm_track) | |
| # Verify mapping | |
| assert unified_track.name == "Paranoid Android" | |
| assert unified_track.artist == "Radiohead" | |
| assert unified_track.lastfm_mbid == "test-mbid-123" | |
| assert unified_track.external_urls == {"lastfm": "https://last.fm/music/Radiohead/_/Paranoid+Android"} | |
| assert unified_track.listeners == 500000 | |
| assert unified_track.playcount == 2000000 | |
| assert unified_track.tags == ["alternative rock", "experimental", "progressive rock"] | |
| assert unified_track.similar_tracks == ["Exit Music (For a Film)", "Karma Police"] | |
| assert unified_track.source == MetadataSource.LASTFM | |
| assert "lastfm" in unified_track.source_data | |
| assert unified_track.source_data["lastfm"]["name"] == "Paranoid Android" | |
| def test_unified_track_from_spotify(self): | |
| """Ensures correct mapping from SpotifyTrack to UnifiedTrackMetadata.""" | |
| # Create mock Spotify track | |
| spotify_track = SpotifyTrack( | |
| id="spotify-track-123", | |
| name="Paranoid Android", | |
| artist="Radiohead", | |
| album="OK Computer", | |
| preview_url="https://p.scdn.co/mp3-preview/123", | |
| external_urls={"spotify": "https://open.spotify.com/track/123"}, | |
| duration_ms=383000, | |
| popularity=85 | |
| ) | |
| # Convert to unified metadata | |
| unified_track = UnifiedTrackMetadata.from_spotify(spotify_track) | |
| # Verify mapping | |
| assert unified_track.name == "Paranoid Android" | |
| assert unified_track.artist == "Radiohead" | |
| assert unified_track.album == "OK Computer" | |
| assert unified_track.spotify_id == "spotify-track-123" | |
| assert unified_track.duration_ms == 383000 | |
| assert unified_track.preview_url == "https://p.scdn.co/mp3-preview/123" | |
| assert unified_track.external_urls == {"spotify": "https://open.spotify.com/track/123"} | |
| assert unified_track.popularity == 85 | |
| assert unified_track.source == MetadataSource.SPOTIFY | |
| assert "spotify" in unified_track.source_data | |
| assert unified_track.source_data["spotify"]["id"] == "spotify-track-123" | |
| def test_merge_track_metadata(self): | |
| """Validates that merging two UnifiedTrackMetadata objects correctly combines their data.""" | |
| # Create LastFM track | |
| lastfm_track = UnifiedTrackMetadata( | |
| name="Paranoid Android", | |
| artist="Radiohead", | |
| lastfm_mbid="test-mbid-123", | |
| external_urls={"lastfm": "https://last.fm/track/123"}, | |
| listeners=500000, | |
| playcount=2000000, | |
| tags=["alternative rock", "experimental"], | |
| source=MetadataSource.LASTFM, | |
| source_data={"lastfm": {"name": "Paranoid Android"}} | |
| ) | |
| # Create Spotify track | |
| spotify_track = UnifiedTrackMetadata( | |
| name="Paranoid Android", | |
| artist="Radiohead", | |
| album="OK Computer", | |
| spotify_id="spotify-123", | |
| duration_ms=383000, | |
| preview_url="https://preview.url", | |
| external_urls={"spotify": "https://spotify.com/track/123"}, | |
| popularity=85, | |
| tags=["progressive rock"], | |
| source=MetadataSource.SPOTIFY, | |
| source_data={"spotify": {"id": "spotify-123"}} | |
| ) | |
| # Merge tracks | |
| merged_track = lastfm_track.merge_with(spotify_track) | |
| # Verify merged data | |
| assert merged_track.name == "Paranoid Android" | |
| assert merged_track.artist == "Radiohead" | |
| assert merged_track.album == "OK Computer" # From Spotify | |
| assert merged_track.spotify_id == "spotify-123" # From Spotify | |
| assert merged_track.lastfm_mbid == "test-mbid-123" # From LastFM | |
| assert merged_track.duration_ms == 383000 # From Spotify | |
| assert merged_track.preview_url == "https://preview.url" # From Spotify | |
| assert merged_track.listeners == 500000 # From LastFM | |
| assert merged_track.playcount == 2000000 # From LastFM | |
| assert merged_track.popularity == 85 # From Spotify | |
| # Verify merged external URLs | |
| assert "lastfm" in merged_track.external_urls | |
| assert "spotify" in merged_track.external_urls | |
| assert merged_track.external_urls["lastfm"] == "https://last.fm/track/123" | |
| assert merged_track.external_urls["spotify"] == "https://spotify.com/track/123" | |
| # Verify merged tags (deduplicated) | |
| expected_tags = {"alternative rock", "experimental", "progressive rock"} | |
| assert set(merged_track.tags) == expected_tags | |
| # Verify merged source data | |
| assert "lastfm" in merged_track.source_data | |
| assert "spotify" in merged_track.source_data | |
| assert merged_track.source == MetadataSource.UNIFIED | |
| def test_merge_different_tracks_raises_error(self): | |
| """Confirms that attempting to merge two different tracks raises a ValueError.""" | |
| # Create two different tracks | |
| track1 = UnifiedTrackMetadata( | |
| name="Paranoid Android", | |
| artist="Radiohead" | |
| ) | |
| track2 = UnifiedTrackMetadata( | |
| name="Creep", | |
| artist="Radiohead" | |
| ) | |
| # Attempt to merge should raise ValueError | |
| with pytest.raises(ValueError, match="Cannot merge different tracks"): | |
| track1.merge_with(track2) | |
| def test_calculate_underground_score(self): | |
| """Checks the logic for calculating a track's underground score based on its popularity metrics.""" | |
| # Test high underground score (low popularity) | |
| underground_track = UnifiedTrackMetadata( | |
| name="Obscure Track", | |
| artist="Unknown Artist", | |
| listeners=500, # Very low listeners | |
| popularity=10, # Very low Spotify popularity | |
| tags=["experimental", "underground", "noise"] # Underground tags | |
| ) | |
| score = underground_track.calculate_underground_score() | |
| # Should be high underground score (close to 1.0) | |
| assert score > 0.7 | |
| assert underground_track.underground_score == score | |
| # Test low underground score (high popularity) | |
| mainstream_track = UnifiedTrackMetadata( | |
| name="Popular Song", | |
| artist="Famous Artist", | |
| listeners=5000000, # High listeners | |
| popularity=95, # High Spotify popularity | |
| tags=["pop", "mainstream", "radio"] # Mainstream tags | |
| ) | |
| score = mainstream_track.calculate_underground_score() | |
| # Should be low underground score (close to 0.0) | |
| assert score < 0.3 | |
| assert mainstream_track.underground_score == score | |
| # Test medium underground score | |
| medium_track = UnifiedTrackMetadata( | |
| name="Indie Track", | |
| artist="Indie Artist", | |
| listeners=50000, # Medium listeners | |
| popularity=50, # Medium Spotify popularity | |
| tags=["indie", "alternative"] # Some underground elements | |
| ) | |
| score = medium_track.calculate_underground_score() | |
| # Should be medium underground score | |
| assert 0.3 <= score <= 0.7 | |
| assert medium_track.underground_score == score | |
| def test_calculate_underground_score_no_data(self): | |
| """Test underground score calculation with no popularity data.""" | |
| track = UnifiedTrackMetadata( | |
| name="Unknown Track", | |
| artist="Unknown Artist" | |
| # No listeners, popularity, or tags | |
| ) | |
| score = track.calculate_underground_score() | |
| # Should default to 0.5 when no data available | |
| assert score == 0.5 | |
| assert track.underground_score == score | |
| def test_track_matching_logic(self): | |
| """Test the _matches_track method for track comparison.""" | |
| track1 = UnifiedTrackMetadata( | |
| name="Paranoid Android", | |
| artist="Radiohead" | |
| ) | |
| # Same track, different case | |
| track2 = UnifiedTrackMetadata( | |
| name="paranoid android", | |
| artist="RADIOHEAD" | |
| ) | |
| # Different track | |
| track3 = UnifiedTrackMetadata( | |
| name="Creep", | |
| artist="Radiohead" | |
| ) | |
| assert track1._matches_track(track2) is True | |
| assert track1._matches_track(track3) is False | |
| def test_post_init_normalization(self): | |
| """Test that __post_init__ properly normalizes and initializes fields.""" | |
| track = UnifiedTrackMetadata( | |
| name=" Paranoid Android ", # Extra whitespace | |
| artist=" Radiohead ", # Extra whitespace | |
| tags=None, # Should be initialized to empty list | |
| genres=None, # Should be initialized to empty list | |
| similar_tracks=None, # Should be initialized to empty list | |
| external_urls=None, # Should be initialized to empty dict | |
| source_data=None # Should be initialized to empty dict | |
| ) | |
| # Verify normalization | |
| assert track.name == "Paranoid Android" | |
| assert track.artist == "Radiohead" | |
| # Verify initialization of collections | |
| assert track.tags == [] | |
| assert track.genres == [] | |
| assert track.similar_tracks == [] | |
| assert track.external_urls == {} | |
| assert track.source_data == {} | |
| class TestMergeTrackMetadata: | |
| """Test the merge_track_metadata utility function.""" | |
| def test_merge_track_metadata_function(self): | |
| """Test the standalone merge_track_metadata function.""" | |
| # Create tracks with same name/artist but different data | |
| track1 = UnifiedTrackMetadata( | |
| name="Test Track", | |
| artist="Test Artist", | |
| listeners=1000, | |
| tags=["rock"] | |
| ) | |
| track2 = UnifiedTrackMetadata( | |
| name="Test Track", | |
| artist="Test Artist", | |
| popularity=75, | |
| tags=["alternative"] | |
| ) | |
| track3 = UnifiedTrackMetadata( | |
| name="Different Track", | |
| artist="Test Artist", | |
| popularity=50 | |
| ) | |
| tracks = [track1, track2, track3] | |
| merged_tracks = merge_track_metadata(tracks) | |
| # Should have 2 tracks (track1 and track2 merged, track3 separate) | |
| assert len(merged_tracks) == 2 | |
| # Find the merged track | |
| merged_track = next(t for t in merged_tracks if t.name == "Test Track") | |
| different_track = next(t for t in merged_tracks if t.name == "Different Track") | |
| # Verify merged data | |
| assert merged_track.listeners == 1000 # From track1 | |
| assert merged_track.popularity == 75 # From track2 | |
| assert set(merged_track.tags) == {"rock", "alternative"} # Merged tags | |
| assert merged_track.source == MetadataSource.UNIFIED | |
| # Verify separate track unchanged | |
| assert different_track.popularity == 50 | |
| assert different_track.name == "Different Track" |