pylast/tests/test_pylast.py

139 lines
4 KiB
Python
Executable file

#!/usr/bin/env python
"""
Integration (not unit) tests for pylast.py
"""
import os
import time
import pytest
from flaky import flaky
import pylast
WRITE_TEST = False
def load_secrets(): # pragma: no cover
secrets_file = "test_pylast.yaml"
if os.path.isfile(secrets_file):
import yaml # pip install pyyaml
with open(secrets_file) as f: # see example_test_pylast.yaml
doc = yaml.load(f)
else:
doc = {}
try:
doc["username"] = os.environ["PYLAST_USERNAME"].strip()
doc["password_hash"] = os.environ["PYLAST_PASSWORD_HASH"].strip()
doc["api_key"] = os.environ["PYLAST_API_KEY"].strip()
doc["api_secret"] = os.environ["PYLAST_API_SECRET"].strip()
except KeyError:
pytest.skip("Missing environment variables: PYLAST_USERNAME etc.")
return doc
class PyLastTestCase:
def assert_startswith(self, s, prefix, start=None, end=None) -> None:
assert s.startswith(prefix, start, end)
def assert_endswith(self, s, suffix, start=None, end=None) -> None:
assert s.endswith(suffix, start, end)
def _no_xfail_rerun_filter(err, name, test, plugin):
for _ in test.iter_markers(name="xfail"):
return False
@flaky(max_runs=3, min_passes=1, rerun_filter=_no_xfail_rerun_filter)
class TestPyLastWithLastFm(PyLastTestCase):
secrets = None
def unix_timestamp(self):
return int(time.time())
@classmethod
def setup_class(cls) -> None:
if cls.secrets is None:
cls.secrets = load_secrets()
cls.username = cls.secrets["username"]
password_hash = cls.secrets["password_hash"]
api_key = cls.secrets["api_key"]
api_secret = cls.secrets["api_secret"]
cls.network = pylast.LastFMNetwork(
api_key=api_key,
api_secret=api_secret,
username=cls.username,
password_hash=password_hash,
)
def helper_is_thing_hashable(self, thing) -> None:
# Arrange
things = set()
# Act
things.add(thing)
# Assert
assert thing is not None
assert len(things) == 1
def helper_validate_results(self, a, b, c) -> None:
# Assert
assert a is not None
assert b is not None
assert c is not None
assert isinstance(len(a), int)
assert isinstance(len(b), int)
assert isinstance(len(c), int)
assert a == b
assert b == c
def helper_validate_cacheable(self, thing, function_name) -> None:
# Arrange
# get thing.function_name()
func = getattr(thing, function_name, None)
# Act
result1 = func(limit=1, cacheable=False)
result2 = func(limit=1, cacheable=True)
result3 = list(func(limit=1))
# Assert
self.helper_validate_results(result1, result2, result3)
def helper_at_least_one_thing_in_top_list(self, things, expected_type) -> None:
# Assert
assert len(things) > 1
assert isinstance(things, list)
assert isinstance(things[0], pylast.TopItem)
assert isinstance(things[0].item, expected_type)
def helper_only_one_thing_in_top_list(self, things, expected_type) -> None:
# Assert
assert len(things) == 1
assert isinstance(things, list)
assert isinstance(things[0], pylast.TopItem)
assert isinstance(things[0].item, expected_type)
def helper_only_one_thing_in_list(self, things, expected_type) -> None:
# Assert
assert len(things) == 1
assert isinstance(things, list)
assert isinstance(things[0], expected_type)
def helper_two_different_things_in_top_list(self, things, expected_type) -> None:
# Assert
assert len(things) == 2
thing1 = things[0]
thing2 = things[1]
assert isinstance(thing1, pylast.TopItem)
assert isinstance(thing2, pylast.TopItem)
assert isinstance(thing1.item, expected_type)
assert isinstance(thing2.item, expected_type)
assert thing1 != thing2