refactored module to use class structure with a better separation between unit and integration tests; rewrote existing tests, added new ones
This commit is contained in:
parent
67259d689b
commit
7cad11981e
@ -1,26 +1,83 @@
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
import pytest
|
||||
from the_works.database import db
|
||||
from the_works.models import Genre
|
||||
|
||||
def test_genre_create(client, _app):
|
||||
"""Integrated testing of adding a Genre record."""
|
||||
response = client.post("/genre/create", data={"form_Genre": "spam"}, 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"
|
||||
class TestIntGenreRead:
|
||||
"""Integrated tests for reading all records."""
|
||||
|
||||
def test_records_read(self, client, db):
|
||||
"""test reading records"""
|
||||
response = client.get("/genre/all", follow_redirects=True)
|
||||
# good status code
|
||||
assert response.status_code == 200
|
||||
# two records returned
|
||||
assert response.data.count(b'<tr id="genre-') == 2
|
||||
# assert records were correctly read from DB
|
||||
assert b'spam' in response.data
|
||||
assert b'eggs' in response.data
|
||||
|
||||
# assert record was successfully added to DB
|
||||
with _app.app_context():
|
||||
genre = db.session.scalars(select(Genre).where(Genre.Genre == "spam")).all()
|
||||
assert len(genre) == 1
|
||||
assert isinstance(genre[0], Genre)
|
||||
|
||||
# assert uniqueness of records
|
||||
class TestIntGenreCreate:
|
||||
"""Integrated tests for adding a Genre record."""
|
||||
|
||||
def test_record_added(self, client, db):
|
||||
"""test record creation"""
|
||||
client.post("/genre/create", data={"form_Genre": "spam & eggs"}, follow_redirects=True)
|
||||
genres = db.session.scalars(select(Genre).where(Genre.Genre == "spam & eggs")).all()
|
||||
assert len(genres) == 1
|
||||
assert isinstance(genres[0], Genre) and genres[0].Genre == "spam & eggs"
|
||||
|
||||
def test_uniqueness_constraint(self, client, db):
|
||||
"""assert uniqueness constraint when adding records"""
|
||||
with pytest.raises(IntegrityError) as excinfo:
|
||||
response = client.post("/genre/create", data={"form_Genre": "spam"})
|
||||
client.post("/genre/create", data={"form_Genre": "spam"})
|
||||
assert "UNIQUE constraint failed" in str(excinfo.value)
|
||||
|
||||
def test_notempty_constraint(self, client):
|
||||
"""assert non-empty constraint when adding record"""
|
||||
with pytest.raises(IntegrityError) as excinfo:
|
||||
client.post("/genre/create", data={"form_Genre": ""})
|
||||
assert "CHECK constraint failed" in str(excinfo.value)
|
||||
|
||||
|
||||
class TestIntGenreUpdate:
|
||||
"""Integrated tests for updating a Genre record."""
|
||||
|
||||
def test_record_updated(self, client, db):
|
||||
"""test record updating"""
|
||||
# get test record id
|
||||
g = db.session.scalar(select(Genre).where(Genre.Genre == "spam"))
|
||||
# update record
|
||||
client.post(f"/genre/update/{g.ID}", data={"form_Genre": "spam & eggs"})
|
||||
# get updated record
|
||||
g = db.session.get(Genre, g.ID)
|
||||
assert g.Genre == "spam & eggs"
|
||||
|
||||
def test_uniqueness_constraint(self, client, db):
|
||||
"""assert uniqueness constraint when updating records"""
|
||||
g = db.session.scalar(select(Genre).where(Genre.Genre == "spam"))
|
||||
with pytest.raises(IntegrityError) as excinfo:
|
||||
client.post(f"/genre/update/{g.ID}", data={"form_Genre": "eggs"})
|
||||
assert "UNIQUE constraint failed" in str(excinfo.value)
|
||||
|
||||
def test_notempty_constraint(self, client, db):
|
||||
"""assert non-empty constraint when updating record"""
|
||||
g = db.session.scalar(select(Genre).where(Genre.Genre == "spam"))
|
||||
with pytest.raises(IntegrityError) as excinfo:
|
||||
client.post(f"/genre/update/{g.ID}", data={"form_Genre": ""})
|
||||
assert "CHECK constraint failed" in str(excinfo.value)
|
||||
|
||||
|
||||
class TestIntGenreDelete:
|
||||
"""Integrated tests for deleting a Genre record."""
|
||||
|
||||
def test_record_deleted(self, client, db):
|
||||
"""test record deletion"""
|
||||
# get test record id
|
||||
g = db.session.scalar(select(Genre).where(Genre.Genre == "spam"))
|
||||
# delete record
|
||||
client.get(f"/genre/delete/{g.ID}")
|
||||
g = db.session.scalars(select(Genre).where(Genre.Genre == "spam")).all()
|
||||
assert g == []
|
||||
|
||||
@ -1,58 +1,147 @@
|
||||
import pytest
|
||||
from the_works.models import Genre
|
||||
|
||||
|
||||
def test_genre_all(client, mocker):
|
||||
class TestUnitGenreRead:
|
||||
"""Test view all() from genre.py."""
|
||||
|
||||
def test_get_request(self, client, mocker):
|
||||
"""test GET request"""
|
||||
|
||||
# mock database function
|
||||
# Note: The original scalars() method returns an sqlalchemy.engine.Result.ScalarResult, not a list
|
||||
# Note: scalars() should return an sqlalchemy.engine.Result.ScalarResult, not a list
|
||||
# but the template code uses the return value in a way which works for both ScalarResult and list
|
||||
mocker.patch("flask_sqlalchemy.session.Session.scalars", return_value=[
|
||||
Genre(ID=4, Genre="spam"),
|
||||
Genre(ID=26, Genre="eggs")
|
||||
Genre(ID=4, Genre="SpAm"),
|
||||
Genre(ID=26, Genre="eGgS")
|
||||
])
|
||||
|
||||
# test case: get request
|
||||
response = client.get("/genre")
|
||||
# assert good HTTP response
|
||||
assert response.status_code == 200
|
||||
# assert two records read
|
||||
assert response.data.count(b'<tr id="genre-') == 2
|
||||
# assert records were correctly read from DB
|
||||
assert b'SpAm' in response.data
|
||||
assert b'eGgS' in response.data
|
||||
|
||||
# test case: post request
|
||||
def test_get_request_with_query(self, client):
|
||||
response = client.get("/genre", query_string={"id": 1, "form_genre": "spam"})
|
||||
# assert good HTTP response
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_post_request(self, client):
|
||||
"""test POST request"""
|
||||
response = client.post("/genre")
|
||||
assert response.status_code == 405
|
||||
|
||||
|
||||
def test_genre_create(client, mocker):
|
||||
class TestUnitGenreCreate:
|
||||
"""Test view create() from genre.py."""
|
||||
|
||||
# mock database function
|
||||
def test_good_data_request(self, client, mocker):
|
||||
"""test a POST request with good data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.add")
|
||||
|
||||
# test a POST request with good data
|
||||
response = client.post("/genre/create", data={"form_Genre": "spam"}, 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)
|
||||
def test_no_data(self, client, mocker):
|
||||
"""test a POST request with no form data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.add")
|
||||
response = client.post("/genre/create", data={}, follow_redirects=True)
|
||||
assert response.status_code == 200 # note: a real DB would have raised an IntegrityError
|
||||
|
||||
# test a POST request with bad form data
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
response = client.post("/genre/create", data={"wrong_key": "eggs"})
|
||||
assert "value can't be empty" in str(excinfo.value)
|
||||
def test_bad_data(self, client, mocker):
|
||||
"""test a POST request with bad form data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.add")
|
||||
response = client.post("/genre/create", data={"wrong_key": "eggs"}, follow_redirects=True)
|
||||
assert response.status_code == 200 # same
|
||||
|
||||
# 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)
|
||||
def test_empty_data(self, client, mocker):
|
||||
"""test a POST request with empty form data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.add")
|
||||
response = client.post("/genre/create", data={"form_genre": ""}, follow_redirects=True)
|
||||
assert response.status_code == 200 # same
|
||||
|
||||
# test a GET request
|
||||
response = client.get("/genre/create", query_string={"form_Genre": "spam eggs"})
|
||||
def test_get_request(self, client):
|
||||
"""test a GET request"""
|
||||
response = client.get("/genre/create", query_string={"form_Genre": "spam & eggs"})
|
||||
assert response.status_code == 405
|
||||
|
||||
|
||||
class TestUnitGenreUpdate:
|
||||
"""Test view update() from genre.py."""
|
||||
|
||||
def test_good_data_request(self, client, mocker):
|
||||
"""test a POST request with good data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=Genre(ID=1, Genre="spam"))
|
||||
response = client.post("/genre/update/1", data={"form_Genre": "eGgS"}, follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_no_data(self, client, mocker):
|
||||
"""test a POST request with no form data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=Genre(ID=1, Genre="spam"))
|
||||
response = client.post("/genre/update/1", data={}, follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_bad_data(self, client, mocker):
|
||||
"""test a POST request with bad form data"""
|
||||
# mock database function
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=Genre(ID=1, Genre="spam"))
|
||||
response = client.post("/genre/update/1", data={"wrong_key": "eggs"}, follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_empty_data(self, client, mocker):
|
||||
"""test a POST request with empty form data"""
|
||||
# mock database function
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=Genre(ID=1, Genre="spam"))
|
||||
response = client.post("/genre/update/1", data={"form_genre": ""}, follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_no_id(self, client):
|
||||
"""test POST request without id"""
|
||||
response = client.post("/genre/update/", data={"form_Genre": "spam & eggs"}, follow_redirects=True)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_bad_id(self, client, mocker):
|
||||
"""test method call with an id that doesn't exist"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=None)
|
||||
response = client.post("/genre/update/123", data={"form_Genre": "spam & eggs"}, follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_get_request(self, client):
|
||||
"""test a GET request"""
|
||||
response = client.get("/genre/update/1", query_string={"form_Genre": "spam & eggs"})
|
||||
assert response.status_code == 405
|
||||
|
||||
|
||||
class TestUnitGenreDelete:
|
||||
"""Test view delete() from genre.py."""
|
||||
|
||||
def test_get_request(self, client, mocker):
|
||||
"""test a GET request with good data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=Genre(ID=1, Genre="spam"))
|
||||
mocker.patch("flask_sqlalchemy.session.Session.delete")
|
||||
response = client.get("/genre/delete/1", follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_get_request_with_query(self, client, mocker):
|
||||
"""test a GET request with good data"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.get", return_value=Genre(ID=1, Genre="spam"))
|
||||
mocker.patch("flask_sqlalchemy.session.Session.delete")
|
||||
response = client.get("/genre/delete/1", query_string={"spam": 1, "eggs": "important stuff"}, follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_no_id(self, client):
|
||||
"""test a GET request with no id"""
|
||||
response = client.get("/genre/delete", follow_redirects=True)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_bad_id(self, client, mocker):
|
||||
"""test a GET request with a non-existing id"""
|
||||
mocker.patch("flask_sqlalchemy.session.Session.delete")
|
||||
response = client.get("/genre/delete/123", follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_post_request(self, client):
|
||||
"""test a POST request"""
|
||||
response = client.post("/genre/delete/1")
|
||||
assert response.status_code == 405
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user