extended and improved tests; unit tests now mock the DB, integration tests use an empty DB with test values that is reset for each test function

This commit is contained in:
eclipse 2025-07-24 10:49:01 +02:00
parent 0522c5660e
commit a7244942ed
5 changed files with 100 additions and 1 deletions

View File

@ -4,7 +4,7 @@ FLASK_APP = "the_works"
FLASK_ENV = "development" FLASK_ENV = "development"
FLASK_SECRET_KEY = "f8148ee5d95b0a67122b1cab9993f637a6bf29528f584a9f1575af1a55566748" FLASK_SECRET_KEY = "f8148ee5d95b0a67122b1cab9993f637a6bf29528f584a9f1575af1a55566748"
FLASK_TESTING = False FLASK_TESTING = False
FLASK_MAX_CONTENT_LENGTH = 1024 * 1024 #FLASK_MAX_CONTENT_LENGTH = 1024 * 1024
FLASK_DEBUG = True FLASK_DEBUG = True
FLASK_SQLALCHEMY_DATABASE_URI = "sqlite:///../the_works.sqlite" FLASK_SQLALCHEMY_DATABASE_URI = "sqlite:///../the_works.sqlite"

View File

@ -1,5 +1,6 @@
import pytest import pytest
from the_works import create_app from the_works import create_app
from the_works.database import db as _db
TEST_DATABASE_URI = "sqlite:///:memory:" TEST_DATABASE_URI = "sqlite:///:memory:"
@ -8,6 +9,7 @@ def app():
test_config = { test_config = {
"ENV": "Testing", "ENV": "Testing",
"SQLALCHEMY_DATABASE_URI": TEST_DATABASE_URI, "SQLALCHEMY_DATABASE_URI": TEST_DATABASE_URI,
"SECRET_KEY": "This is my very secret key",
"TESTING": True "TESTING": True
} }
app = create_app(test_config) app = create_app(test_config)
@ -19,6 +21,14 @@ def app():
# clean up / reset resources here # clean up / reset resources here
@pytest.fixture(scope="function")
def db(app):
with app.app_context():
yield _db
_db.drop_all()
_db.create_all()
@pytest.fixture() @pytest.fixture()
def client(app): def client(app):
return app.test_client() return app.test_client()

View File

@ -0,0 +1,27 @@
from sqlalchemy import select
from the_works.database import db
from the_works.models import Genre
from sqlalchemy.exc import IntegrityError
import pytest
def test_genre_create(client, app):
"""Integrated testing of adding a Genre record."""
response = client.post("/genre/create", data={"form_Genre": "Test-Genre"}, follow_redirects=True)
# assert there was exactly 1 redirect
assert len(response.history) == 1
# assert the redirect led to the correct page
assert response.request.path == "/genre/all"
assert response.status_code == 200
# assert record was successfully added to DB
with app.app_context():
genre = db.session.scalars(select(Genre).where(Genre.Genre == "Test-Genre")).all()
assert len(genre) == 1
assert isinstance(genre[0], Genre)
# assert uniqueness of records
with pytest.raises(IntegrityError) as excinfo:
response = client.post("/genre/create", data={"form_Genre": "Test-Genre"})
assert "UNIQUE constraint failed" in str(excinfo.value)

View File

@ -0,0 +1,58 @@
from the_works.models import Genre
import pytest
def test_genre_all(client, db, mocker):
"""Test view all() from genre.py."""
# mock database function
# Note: The original method returns an sqlalchemy.engine.Result.ScalarResult, not a list, but the template code
# uses the return value in a way that works for both ScalarResult and list
mocker.patch("the_works.database.db.session.scalars", return_value=[
Genre(ID=4, Genre="bla"),
Genre(ID=26, Genre="blubb")
])
# test case: get request
response = client.get("/genre")
assert response.status_code == 200
assert response.data.count(b'<tr id="genre-') == 2
# test case: post request
response = client.post("/genre")
assert response.status_code == 405
def test_genre_create(client, db, mocker):
"""Test view create() from genre.py."""
# mock database function
mocker.patch("the_works.database.db.session.add")
# test a POST request with good data
response = client.post("/genre/create", data={"form_Genre": "Testname"}, follow_redirects=True)
# exactly 1 redirect
assert len(response.history) == 1
# redirect to the right page
assert response.request.path == "/genre/all"
assert response.status_code == 200
# test a POST request with no form data
with pytest.raises(ValueError) as excinfo:
response = client.post("/genre/create", data={})
assert "value can't be empty" in str(excinfo.value)
# test a POST request with bad form data
with pytest.raises(ValueError) as excinfo:
response = client.post("/genre/create", data={"wrong_key": "Genrename"})
assert "value can't be empty" in str(excinfo.value)
# test a POST request with empty form data
with pytest.raises(ValueError) as excinfo:
response = client.post("/genre/create", data={"form_genre": ""})
assert "value can't be empty" in str(excinfo.value)
# test a GET request
response = client.get("/genre/create", query_string={"form_Genre": "GET-Genre"})
assert response.status_code == 405

View File

@ -0,0 +1,4 @@
def test_home_startpage(client):
response = client.get("/")
assert response.status_code == 200
assert response.data.startswith(b"<!DOCTYPE html>\n")