Skip to content

Commit

Permalink
added circle CI config with basic unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xerexcoded committed Jun 9, 2024
1 parent fab1548 commit 2c4a7f3
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 2 deletions.
38 changes: 38 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: 2.1

jobs:
setup:
docker:
- image: circleci/python:3.10
steps:
- checkout
- run:
name: Install dependencies
command: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest pytest-mock
test:
docker:
- image: circleci/python:3.10
steps:
- checkout
- run:
name: Install dependencies
command: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest pytest-mock
- run:
name: Run tests
command: pytest

workflows:
version: 2
test_workflow:
jobs:
- setup
- test:
requires:
- setup
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ dependencies = [
"tidalapi==0.7.6",
"pyyaml~=6.0",
"tqdm~=4.64",
"sqlalchemy~=2.0"
"sqlalchemy~=2.0",
"pytest~=7.0",
"pytest-mock~=3.8"
]

[tools.setuptools.packages."spotify_to_tidal"]
where = "src"
include = "spotify_to_tidal*"

[project.scripts]
spotify_to_tidal = "spotify_to_tidal.__main__:main"
spotify_to_tidal = "spotify_to_tidal.__main__:main"
6 changes: 6 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[pytest]
addopts = --maxfail=1 --disable-warnings
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
5 changes: 5 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import sys
import os

# Add the src directory to the Python path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../src")))
Empty file added tests/unit/__init__.py
Empty file.
73 changes: 73 additions & 0 deletions tests/unit/test_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# tests/unit/test_auth.py

import pytest
import spotipy
import tidalapi
import yaml
import sys
from unittest import mock
from spotify_to_tidal.auth import open_spotify_session, open_tidal_session


def test_open_spotify_session(mocker):
# Mock the SpotifyOAuth class
mock_spotify_oauth = mocker.patch(
"spotify_to_tidal.auth.spotipy.SpotifyOAuth", autospec=True
)
mock_spotify_instance = mocker.patch(
"spotify_to_tidal.auth.spotipy.Spotify", autospec=True
)

# Define a mock configuration
mock_config = {
"username": "test_user",
"client_id": "test_client_id",
"client_secret": "test_client_secret",
"redirect_uri": "http://localhost/",
}

# Create a mock SpotifyOAuth instance
mock_oauth_instance = mock_spotify_oauth.return_value
mock_oauth_instance.get_access_token.return_value = "mock_access_token"

# Call the function under test
spotify_instance = open_spotify_session(mock_config)

# Assert that the SpotifyOAuth was called with correct parameters
mock_spotify_oauth.assert_called_once_with(
username="test_user",
scope="playlist-read-private",
client_id="test_client_id",
client_secret="test_client_secret",
redirect_uri="http://localhost/",
requests_timeout=2,
)

# Assert that the Spotify instance was created
mock_spotify_instance.assert_called_once_with(oauth_manager=mock_oauth_instance)
assert spotify_instance == mock_spotify_instance.return_value


def test_open_spotify_session_oauth_error(mocker):
# Mock the SpotifyOAuth class and simulate an OAuth error
mock_spotify_oauth = mocker.patch(
"spotify_to_tidal.auth.spotipy.SpotifyOAuth", autospec=True
)
mock_spotify_oauth.return_value.get_access_token.side_effect = (
spotipy.SpotifyOauthError("mock error")
)

# Define a mock configuration
mock_config = {
"username": "test_user",
"client_id": "test_client_id",
"client_secret": "test_client_secret",
"redirect_uri": "http://localhost/",
}

# Mock sys.exit to prevent the test from exiting
mock_sys_exit = mocker.patch("sys.exit")

# Call the function under test and assert sys.exit is called
open_spotify_session(mock_config)
mock_sys_exit.assert_called_once()
80 changes: 80 additions & 0 deletions tests/unit/test_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# tests/unit/test_cache.py

import pytest
import datetime
import sqlalchemy
from sqlalchemy import create_engine, select
from unittest import mock
from spotify_to_tidal.cache import MatchFailureDatabase, TrackMatchCache


# Setup an in-memory SQLite database for testing
@pytest.fixture
def in_memory_db():
engine = create_engine("sqlite:///:memory:")
return engine


# Test MatchFailureDatabase
def test_cache_match_failure(in_memory_db, mocker):
mocker.patch(
"spotify_to_tidal.cache.sqlalchemy.create_engine", return_value=in_memory_db
)
failure_db = MatchFailureDatabase()

track_id = "test_track"
failure_db.cache_match_failure(track_id)

with failure_db.engine.connect() as connection:
result = connection.execute(
select(failure_db.match_failures).where(
failure_db.match_failures.c.track_id == track_id
)
).fetchone()
assert result is not None
assert result.track_id == track_id


def test_has_match_failure(in_memory_db, mocker):
mocker.patch(
"spotify_to_tidal.cache.sqlalchemy.create_engine", return_value=in_memory_db
)
failure_db = MatchFailureDatabase()

track_id = "test_track"
failure_db.cache_match_failure(track_id)

assert failure_db.has_match_failure(track_id) is True


def test_remove_match_failure(in_memory_db, mocker):
mocker.patch(
"spotify_to_tidal.cache.sqlalchemy.create_engine", return_value=in_memory_db
)
failure_db = MatchFailureDatabase()

track_id = "test_track"
failure_db.cache_match_failure(track_id)
failure_db.remove_match_failure(track_id)

with failure_db.engine.connect() as connection:
result = connection.execute(
select(failure_db.match_failures).where(
failure_db.match_failures.c.track_id == track_id
)
).fetchone()
assert result is None


# Test TrackMatchCache
def test_track_match_cache_insert():
track_cache = TrackMatchCache()
track_cache.insert(("spotify_id", 123))
assert track_cache.get("spotify_id") == 123


def test_track_match_cache_get():
track_cache = TrackMatchCache()
track_cache.insert(("spotify_id", 123))
assert track_cache.get("spotify_id") == 123
assert track_cache.get("nonexistent_id") is None

0 comments on commit 2c4a7f3

Please sign in to comment.