import bz2 from pathlib import Path from unittest.mock import AsyncMock import bs4 import pytest from unwind import imdb from unwind.imdb import imdb_rating_from_score, score_from_imdb_rating testsdir = Path(__file__).parent fixturesdir = testsdir / "fixtures" @pytest.mark.parametrize("rating", (x / 10 for x in range(10, 101))) def test_rating_conversion(rating: float): assert rating == imdb_rating_from_score(score_from_imdb_rating(rating)) @pytest.mark.parametrize("score", range(0, 101)) def test_score_conversion(score: int): # Because our score covers 101 discrete values and IMDb's rating only 91 # discrete values, the mapping is non-injective, i.e. 10 values can't be # mapped uniquely. non_injective = set(range(5, 100, 10)) if score in non_injective: pytest.skip(f"Score cannot be mapped back correctly: {score}") assert score == score_from_imdb_rating(imdb_rating_from_score(score)) @pytest.mark.asyncio async def test_load_most_popular_100(monkeypatch): with bz2.open(fixturesdir / "most_popular_100.html.bz2", "rb") as f: html = f.read() soup = bs4.BeautifulSoup(html, "html5lib") monkeypatch.setattr(imdb, "asoup_from_url", AsyncMock(return_value=soup)) movie_ids = await imdb.load_most_popular_100() assert len(movie_ids) == 100 assert all(id_.startswith("tt") for id_ in movie_ids) @pytest.mark.asyncio async def test_load_bottom_100(monkeypatch): with bz2.open(fixturesdir / "bottom_100.html.bz2", "rb") as f: html = f.read() soup = bs4.BeautifulSoup(html, "html5lib") monkeypatch.setattr(imdb, "asoup_from_url", AsyncMock(return_value=soup)) movie_ids = await imdb.load_bottom_100() assert len(movie_ids) == 100 assert all(id_.startswith("tt") for id_ in movie_ids) @pytest.mark.asyncio async def test_load_top_250(monkeypatch): with bz2.open(fixturesdir / "top250.gql.json.bz2", "rb") as f: jsonstr = f.read() monkeypatch.setattr(imdb, "adownload", AsyncMock(return_value=jsonstr)) movie_ids = await imdb.load_top_250() assert len(movie_ids) == 250 assert all(id_.startswith("tt") for id_ in movie_ids)