From 4bece2f73f69452233588c19cb48f9a36870530f Mon Sep 17 00:00:00 2001 From: Chris Fulljames Date: Mon, 31 Mar 2025 18:55:09 -0400 Subject: [PATCH] Start breaking up tests --- test/__init__.py | 0 test/conftest.py | 42 ++++++++++++++++++++++++++++++++++++ test/test_offline.py | 33 +--------------------------- test/test_online.py | 51 ++++++++++++++++---------------------------- test/utils.py | 10 +++++++++ 5 files changed, 71 insertions(+), 65 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/conftest.py create mode 100644 test/utils.py diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 0000000..3e03cf0 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,42 @@ +import sqlite3 +import tempfile +from pathlib import Path +from unittest.mock import patch +import littlesongplace as lsp + +import bcrypt +import requests +import pytest + +from .utils import login + +@pytest.fixture +def app(): + # Use temporary data directory + with tempfile.TemporaryDirectory() as data_dir: + lsp.DATA_DIR = Path(data_dir) + + # Initialize Database + with lsp.app.app_context(): + db = sqlite3.connect(lsp.DATA_DIR / "database.db") + with lsp.app.open_resource('sql/schema.sql', mode='r') as f: + db.cursor().executescript(f.read()) + db.commit() + db.close() + + yield lsp.app + +@pytest.fixture +def client(app): + # Mock bcrypt to speed up tests + with patch.object(bcrypt, "hashpw", lambda passwd, salt: passwd), \ + patch.object(bcrypt, "checkpw", lambda passwd, saved: passwd == saved): + yield app.test_client() + +@pytest.fixture(scope="module") +def session(): + session = requests.Session() + # User may already exist, but that's fine - we'll just ignore the signup error + login(session, "user", "1234asdf!@#$") + yield session + diff --git a/test/test_offline.py b/test/test_offline.py index 3908efe..495b009 100644 --- a/test/test_offline.py +++ b/test/test_offline.py @@ -1,45 +1,14 @@ import html import json -import os import re -import sqlite3 -import sys -import tempfile from pathlib import Path -from unittest.mock import patch -import bcrypt import pytest from flask import session -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) - -TEST_DATA = Path(__file__).parent / "data" - import littlesongplace as lsp -@pytest.fixture -def app(): - # Use temporary data directory - with tempfile.TemporaryDirectory() as data_dir: - lsp.DATA_DIR = Path(data_dir) - - # Initialize Database - with lsp.app.app_context(): - db = sqlite3.connect(lsp.DATA_DIR / "database.db") - with lsp.app.open_resource('sql/schema.sql', mode='r') as f: - db.cursor().executescript(f.read()) - db.commit() - db.close() - - yield lsp.app - -@pytest.fixture -def client(app): - # Mock bcrypt to speed up tests - with patch.object(bcrypt, "hashpw", lambda passwd, salt: passwd), \ - patch.object(bcrypt, "checkpw", lambda passwd, saved: passwd == saved): - yield app.test_client() +TEST_DATA = Path(__file__).parent / "data" ################################################################################ # Signup diff --git a/test/test_online.py b/test/test_online.py index 6bc3474..3502562 100644 --- a/test/test_online.py +++ b/test/test_online.py @@ -3,33 +3,18 @@ import json import re from pathlib import Path -import requests +from .utils import url, login + import pytest -HOST = "http://littlesong.place:8000" TEST_DATA = Path(__file__).parent / "data" -def url(path): - return HOST + path - -@pytest.fixture(scope="module") -def s(): - s = requests.Session() - # User may already exist, but that's fine - we'll just ignore the signup error - _login(s, "user", "1234asdf!@#$") - yield s - -def _login(s, username, password): - s.post(url("/signup"), data={"username": username, "password": password, "password_confirm": password}) - response = s.post(url("/login"), data={"username": username, "password": password}) - response.raise_for_status() - def _get_song_list_from_page(page_contents): matches = re.findall('data-song="(.*)">', page_contents) return [json.loads(html.unescape(m)) for m in matches] -def test_upload_and_delete_song(s): - response = s.post( +def test_upload_and_delete_song(session): + response = session.post( url("/upload-song"), files={"song-file": open(TEST_DATA/"sample-3s.mp3", "rb")}, data={ @@ -51,14 +36,14 @@ def test_upload_and_delete_song(s): # Delete song songid = song["songid"] - response = s.get(url(f"/delete-song/{songid}"), headers={"referer": "/users/user"}) + response = session.get(url(f"/delete-song/{songid}"), headers={"referer": "/users/user"}) response.raise_for_status() songs = _get_song_list_from_page(response.text) assert not any(song["songid"] == songid for song in songs) -def test_comments_and_activity(s): +def test_comments_and_activity(session): # Upload song - response = s.post( + response = session.post( url("/upload-song"), files={"song-file": open(TEST_DATA/"sample-3s.mp3", "rb")}, data={"title": "song title", "description": "", "tags": "", "collabs": ""}, @@ -70,14 +55,14 @@ def test_comments_and_activity(s): threadid = song["threadid"] try: - _login(s, "user1", "1234asdf!@#$") + login(session, "user1", "1234asdf!@#$") # Comment on song as new user - response = s.get( + response = session.get( url(f"/comment?threadid={threadid}"), headers={"referer": "/users/user"}) response.raise_for_status() - response = s.post( + response = session.post( url(f"/comment?threadid={threadid}"), headers={"referer": f"/comment?threadid={threadid}"}, data={"content": "hey cool song"}) @@ -85,26 +70,26 @@ def test_comments_and_activity(s): assert "hey cool song" in response.text # Check activity status as original user - _login(s, "user", "1234asdf!@#$") - response = s.get(url("/new-activity")) + login(session, "user", "1234asdf!@#$") + response = session.get(url("/new-activity")) assert response.json()["new_activity"] is True # Check activity page - response = s.get(url("/activity")) + response = session.get(url("/activity")) assert "hey cool song" in response.text finally: # Delete song - response = s.get(url(f"/delete-song/{songid}"), headers={"referer": "/users/user"}) + response = session.get(url(f"/delete-song/{songid}"), headers={"referer": "/users/user"}) response.raise_for_status() songs = _get_song_list_from_page(response.text) assert not any(song["songid"] == songid for song in songs) @pytest.mark.skip -def test_upload_song_from_youtube(s): - _login(s, "user", "1234asdf!@#$") +def test_upload_song_from_youtube(session): + login(session, "user", "1234asdf!@#$") - response = s.post( + response = session.post( url("/upload-song"), data={"title": "yt-song", "description": "", "tags": "", "collabs": "", "song-url": "https://youtu.be/5e5Z6gZWiEs"}, ) @@ -115,6 +100,6 @@ def test_upload_song_from_youtube(s): try: assert song["title"] == "yt-song" finally: - response = s.get(url(f"/delete-song/{songid}"), headers={"referer": "/users/user"}) + response = session.get(url(f"/delete-song/{songid}"), headers={"referer": "/users/user"}) response.raise_for_status() diff --git a/test/utils.py b/test/utils.py new file mode 100644 index 0000000..622e218 --- /dev/null +++ b/test/utils.py @@ -0,0 +1,10 @@ +HOST = "http://littlesong.place:8000" + +def url(path): + return HOST + path + +def login(session, username, password): + session.post(url("/signup"), data={"username": username, "password": password, "password_confirm": password}) + response = session.post(url("/login"), data={"username": username, "password": password}) + response.raise_for_status() + -- 2.39.5