Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:
The project employs a testing strategy centered around Django's built-in testing framework, which extends Python's standard unittest module. The tests are organized by component type (models, views, forms) within the catalog/tests/ directory. This approach ensures that individual parts of the application function correctly in isolation and that key user-facing features, such as authentication and data presentation, behave as expected.
The tests are executed using the standard Django management command python3 manage.py test. This command discovers and runs all tests within the project, providing a simple and effective way to validate the application's integrity.
Sources: README.md:21, catalog/tests/test_models.py, catalog/tests/test_forms.py, catalog/tests/test_views.py
Test Structure
Tests are encapsulated in classes that inherit from django.test.TestCase. Each test file corresponds to a specific application component.
| Test File | Description |
|---|---|
test_models.py | Contains tests for the catalog app's models, verifying field attributes and method behavior. |
test_forms.py | Contains tests for form validation logic, specifically for the RenewBookForm. |
test_views.py | The most extensive set of tests, covering view-layer logic including URL routing, template usage, authentication, permissions, pagination, and form handling. |
Sources: catalog/tests/test_models.py:7, catalog/tests/test_forms.py:7, catalog/tests/test_views.py:6
The following diagram illustrates the primary test classes used for view testing.
This diagram shows the inheritance structure of the main test classes in test_views.py, all deriving from Django's TestCase.
Sources: catalog/tests/test_views.py
Model Testing
Model tests focus on validating the schema definition and custom methods of the Django models. The tests for the Author model serve as a representative example.
Sources: catalog/tests/test_models.py
Author Model Tests
The AuthorModelTest class verifies the metadata and behavior of the Author model. Test data is created once for the entire class using the setUpTestData class method to improve efficiency.
The following aspects of the Author model are tested:
- Field Labels: Ensures
verbose_namefor fields likefirst_name,last_name,date_of_birth, anddate_of_deathare user-friendly. - Field Lengths: Validates that
max_lengthconstraints are correctly set for character fields. - Object Representation: Checks that the
__str__method returns the name in the format "Last Name, First Name". - URL Generation: Verifies that the
get_absolute_url()method returns the correct URL for an author's detail view.
| Test Method | Assertion | Source File |
|---|---|---|
test_first_name_label() | field_label == 'first name' | catalog/tests/test_models.py:15-17 |
test_last_name_label() | field_label == 'last name' | catalog/tests/test_models.py:19-21 |
test_first_name_max_length() | max_length == 100 | catalog/tests/test_models.py:31-33 |
test_object_name_is_last_name_comma_first_name() | str(author) == 'Bob, Big' | catalog/tests/test_models.py:41-44 |
test_get_absolute_url() | author.get_absolute_url() == '/catalog/author/1' | catalog/tests/test_models.py:46-48 |
Sources: catalog/tests/test_models.py:7-48, catalog/models.py:184-199
Form Testing
Form tests validate the data cleaning and validation logic. The RenewBookForm is tested to ensure that only valid renewal dates can be submitted.
Sources: catalog/tests/test_forms.py
RenewBookForm Validation
The RenewBookFormTest class contains tests for the renewal_date field's validation rules. The form should reject dates in the past and dates more than 4 weeks in the future.
The validation logic is summarized in the flowchart below:
This flowchart illustrates the validation checks performed on the renewal_date field.
Sources: catalog/tests/test_forms.py:7-44, catalog/tests/test_views.py:361-369
Key validation tests include:
test_renew_form_date_in_past: Assertsform.is_valid()isFalsefor a past date.test_renew_form_date_too_far_in_future: Assertsform.is_valid()isFalsefor a date more than 4 weeks away.test_renew_form_date_today: Assertsform.is_valid()isTruefor today's date.test_renew_form_date_max: Assertsform.is_valid()isTruefor a date exactly 4 weeks in the future.
Sources: catalog/tests/test_forms.py:10-29
View Testing
View tests are the most comprehensive, covering URL accessibility, template rendering, authentication, permissions, and data handling logic like pagination. The Django test client (self.client) is used to simulate HTTP requests (GET and POST) to the application's views.
Sources: catalog/tests/test_views.py
Public and Authenticated Views
Tests for public list views, like AuthorListViewTest, confirm several key behaviors:
- The view is accessible at its hardcoded URL (
/catalog/authors/). - The view is accessible via its named URL (
reverse('authors')). - The correct template (
catalog/author_list.html) is used. - Pagination is active and limits the number of items per page to 10.
For views requiring authentication, such as LoanedBooksByUserListView, tests verify:
- Redirect for Anonymous Users: An unauthenticated request to
/catalog/mybooks/results in a redirect to the login page. - Correct Data for Logged-in User: Once logged in, the view only displays
BookInstanceobjects borrowed by that specific user and with a status of 'On loan' (o). - Correct Ordering: The list of borrowed books is ordered by
due_backdate.
Sources: catalog/tests/test_views.py:9-52, catalog/tests/test_views.py:77-222
Permission-Protected Views
Views that require specific permissions, such as renew_book_librarian and AuthorCreate, have a more complex set of tests to cover different access control scenarios.
The sequence diagram below shows the test flow for accessing the renew-book-librarian view.
This diagram shows the different responses from the renew_book_librarian view based on user authentication and permission status.
Sources: catalog/tests/test_views.py:292-321
Key tests for permission-protected views include:
- Redirect if not logged in: Asserts a 302 redirect to the login URL.
- Forbidden if logged in without permission: Asserts a 403 Forbidden status code for users lacking the required permission (e.g.,
catalog.can_mark_returned). - Success if logged in with permission: Asserts a 200 OK status code for authorized users.
- Form Validation: For views with forms, tests submit both invalid and valid data via POST requests and check for expected outcomes, such as re-rendering the form with an error message or redirecting upon success.
# Example: Testing an invalid form submission
def test_form_invalid_renewal_date_past(self):
login = self.client.login(
username='testuser2', password='2HJ1vRV0Z&3iD')
date_in_past = datetime.date.today() - datetime.timedelta(weeks=1)
response = self.client.post(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk}),
{'renewal_date': date_in_past})
self.assertEqual(response.status_code, 200)
self.assertFormError(
response.context['form'], 'renewal_date', 'Invalid date - renewal in past')
This code snippet from RenewBookInstancesViewTest demonstrates how form errors are tested by POSTing invalid data and checking the response context.
Sources: catalog/tests/test_views.py:355-369