From 9a1ff47acb9ea09d4232156da0dcfb5c7f8001ee Mon Sep 17 00:00:00 2001 From: eshaanagarwal Date: Wed, 29 Jun 2022 04:04:07 +0530 Subject: [PATCH 1/2] add test for views, models, and forms --- .gitignore | 3 +- .../0005_alter_book_maximum_retail_price.py | 18 ++ catalog/models.py | 2 +- catalog/tests.py | 3 - catalog/tests/__init__.py | 0 catalog/tests/test_forms.py | 35 +++ catalog/tests/test_models.py | 35 +++ catalog/tests/test_views.py | 264 ++++++++++++++++++ 8 files changed, 355 insertions(+), 5 deletions(-) create mode 100644 catalog/migrations/0005_alter_book_maximum_retail_price.py delete mode 100644 catalog/tests.py create mode 100644 catalog/tests/__init__.py create mode 100644 catalog/tests/test_forms.py create mode 100644 catalog/tests/test_models.py create mode 100644 catalog/tests/test_views.py diff --git a/.gitignore b/.gitignore index 653bf5c..150100a 100644 --- a/.gitignore +++ b/.gitignore @@ -122,4 +122,5 @@ dmypy.json # End of https://www.gitignore.io/api/django #Virtual environment -venv/ \ No newline at end of file +venv/ +my-project-env \ No newline at end of file diff --git a/catalog/migrations/0005_alter_book_maximum_retail_price.py b/catalog/migrations/0005_alter_book_maximum_retail_price.py new file mode 100644 index 0000000..b07dea3 --- /dev/null +++ b/catalog/migrations/0005_alter_book_maximum_retail_price.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0 on 2022-06-28 21:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalog', '0004_bookcopy_due_back'), + ] + + operations = [ + migrations.AlterField( + model_name='book', + name='maximum_retail_price', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/catalog/models.py b/catalog/models.py index 09018fe..b0725b0 100644 --- a/catalog/models.py +++ b/catalog/models.py @@ -9,7 +9,7 @@ class Book(models.Model): author = models.CharField(max_length=100) genre = models.CharField(max_length=100) description = models.TextField(null=True) - maximum_retail_price = models.PositiveIntegerField() + maximum_retail_price = models.PositiveIntegerField(null=True, blank=True) rating = models.FloatField(default=0.0) class Meta: diff --git a/catalog/tests.py b/catalog/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/catalog/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/catalog/tests/__init__.py b/catalog/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/catalog/tests/test_forms.py b/catalog/tests/test_forms.py new file mode 100644 index 0000000..87c5294 --- /dev/null +++ b/catalog/tests/test_forms.py @@ -0,0 +1,35 @@ +import datetime + +from django.test import TestCase +from django.utils import timezone + +from catalog.forms import RenewBookForm + +class RenewBookFormTest(TestCase): + def test_renew_form_date_field_label(self): + form = RenewBookForm() + self.assertTrue(form.fields['renewal_date'].label is None or form.fields['renewal_date'].label == 'renewal date') + + def test_renew_form_date_field_help_text(self): + form = RenewBookForm() + self.assertEqual(form.fields['renewal_date'].help_text, 'Enter a date between now and 4 weeks (default 3).') + + def test_renew_form_date_in_past(self): + date = datetime.date.today() - datetime.timedelta(days=1) + form = RenewBookForm(data={'renewal_date': date}) + self.assertFalse(form.is_valid()) + + def test_renew_form_date_too_far_in_future(self): + date = datetime.date.today() + datetime.timedelta(weeks=4) + datetime.timedelta(days=1) + form = RenewBookForm(data={'renewal_date': date}) + self.assertFalse(form.is_valid()) + + def test_renew_form_date_today(self): + date = datetime.date.today() + form = RenewBookForm(data={'renewal_date': date}) + self.assertTrue(form.is_valid()) + + def test_renew_form_date_max(self): + date = timezone.localtime() + datetime.timedelta(weeks=4) + form = RenewBookForm(data={'renewal_date': date}) + self.assertTrue(form.is_valid()) \ No newline at end of file diff --git a/catalog/tests/test_models.py b/catalog/tests/test_models.py new file mode 100644 index 0000000..a6e0d0e --- /dev/null +++ b/catalog/tests/test_models.py @@ -0,0 +1,35 @@ +from django.test import TestCase + +# Create your tests here. +from catalog.models import Book + +class BookModelTest(TestCase): + @classmethod + def setUpTestData(cls): + # Set up non-modified objects used by all test methods + Book.objects.create(title='Rich Dad Poor Dad', author='Robert Kiyoski') + + def test_title_label(self): + book = Book.objects.get(id=1) + field_label = book._meta.get_field('title').verbose_name + self.assertEqual(field_label, 'title') + + def test_author_label(self): + book = Book.objects.get(id=1) + field_label = book._meta.get_field('author').verbose_name + self.assertEqual(field_label, 'author') + + def test_genre_max_length(self): + book = Book.objects.get(id=1) + max_length = book._meta.get_field('genre').max_length + self.assertEqual(max_length, 100) + + def test_object_name_is_title_by_author(self): + book = Book.objects.get(id=1) + expected_object_name = f'{book.title} by {book.author}' + self.assertEqual(str(book), expected_object_name) + + def test_get_absolute_url(self): + book = Book.objects.get(id=1) + # This will also fail if the urlconf is not defined. + self.assertEqual(book.get_absolute_url(), '/catalog/book/1') diff --git a/catalog/tests/test_views.py b/catalog/tests/test_views.py new file mode 100644 index 0000000..461cf04 --- /dev/null +++ b/catalog/tests/test_views.py @@ -0,0 +1,264 @@ +from django.test import TestCase + +# Create your tests here. +from django.test import TestCase +from django.urls import reverse + +from catalog.models import Book + +class BookListViewTest(TestCase): + @classmethod + def setUpTestData(cls): + # Create 13 authors for pagination tests + number_of_books = 5 + + for book_id in range(number_of_books): + Book.objects.create( + title=f'Art of Making Money {book_id}', + author=f'Ronald', + ) + + def test_view_url_exists_at_desired_location(self): + response = self.client.get('/catalog/books/') + self.assertEqual(response.status_code, 200) + + def test_view_url_accessible_by_name(self): + response = self.client.get(reverse('books')) + self.assertEqual(response.status_code, 200) + + def test_view_uses_correct_template(self): + response = self.client.get(reverse('books')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'catalog/book_list.html') + + def test_pagination_is_ten(self): + response = self.client.get(reverse('books')) + self.assertEqual(response.status_code, 200) + self.assertTrue('is_paginated' in response.context) + self.assertTrue(response.context['is_paginated'] == True) + self.assertEqual(len(response.context['book_list']), 3) + + def test_lists_all_authors(self): + # Get second page and confirm it has (exactly) remaining 3 items + response = self.client.get(reverse('books')+'?page=2') + self.assertEqual(response.status_code, 200) + self.assertTrue('is_paginated' in response.context) + self.assertTrue(response.context['is_paginated'] == True) + self.assertEqual(len(response.context['book_list']), 2) + + +import datetime + +from django.utils import timezone +from django.contrib.auth.models import User # Required to assign User as a borrower + +from catalog.models import BookCopy, Book + +class LoanedBookInstancesByUserListViewTest(TestCase): + def setUp(self): + # Create two users + test_user1 = User.objects.create_user(username='testuser1', password='1X Date: Wed, 29 Jun 2022 06:52:43 +0530 Subject: [PATCH 2/2] bug fixes in test --- catalog/tests/test_views.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/catalog/tests/test_views.py b/catalog/tests/test_views.py index 461cf04..dfd2911 100644 --- a/catalog/tests/test_views.py +++ b/catalog/tests/test_views.py @@ -9,7 +9,7 @@ class BookListViewTest(TestCase): @classmethod def setUpTestData(cls): - # Create 13 authors for pagination tests + # Create 5 books for pagination tests number_of_books = 5 for book_id in range(number_of_books): @@ -31,14 +31,14 @@ def test_view_uses_correct_template(self): self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'catalog/book_list.html') - def test_pagination_is_ten(self): + def test_pagination_is_three(self): response = self.client.get(reverse('books')) self.assertEqual(response.status_code, 200) self.assertTrue('is_paginated' in response.context) self.assertTrue(response.context['is_paginated'] == True) self.assertEqual(len(response.context['book_list']), 3) - def test_lists_all_authors(self): + def test_lists_all_books(self): # Get second page and confirm it has (exactly) remaining 3 items response = self.client.get(reverse('books')+'?page=2') self.assertEqual(response.status_code, 200) @@ -64,9 +64,6 @@ def setUp(self): test_user2.save() # Create a book - # test_author = Book.objects.create(first_name='John', last_name='Smith') - # test_genre = Genre.objects.create(name='Fantasy') - # test_language = Language.objects.create(name='English') test_book = Book.objects.create( title='Book Title', author='Test Author', @@ -74,9 +71,6 @@ def setUp(self): ) - # Create genre as a post-step - # genre_objects_for_book = Genre.objects.all() - # test_book.genre.set(genre_objects_for_book) # Direct assignment of many-to-many types not allowed. test_book.save() # Create 30 BookInstance objects