-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Testing for views, models, and forms in Django Application #11
Open
eshaanagarwal
wants to merge
2
commits into
COPS-IITBHU:main
Choose a base branch
from
eshaanagarwal:testing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -122,4 +122,5 @@ dmypy.json | |
# End of https://www.gitignore.io/api/django | ||
|
||
#Virtual environment | ||
venv/ | ||
venv/ | ||
my-project-env |
18 changes: 18 additions & 0 deletions
18
catalog/migrations/0005_alter_book_maximum_retail_price.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
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 5 books 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_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_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) | ||
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<ISRUkw+tuK') | ||
test_user2 = User.objects.create_user(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
|
||
test_user1.save() | ||
test_user2.save() | ||
|
||
# Create a book | ||
test_book = Book.objects.create( | ||
title='Book Title', | ||
author='Test Author', | ||
genre='Horror' | ||
|
||
) | ||
|
||
test_book.save() | ||
|
||
# Create 30 BookInstance objects | ||
number_of_book_copies = 30 | ||
for book_copy in range(number_of_book_copies): | ||
return_date = timezone.localtime() + datetime.timedelta(days=book_copy%5) | ||
the_borrower = test_user1 if book_copy % 2 else test_user2 | ||
status = True | ||
BookCopy.objects.create( | ||
book=test_book, | ||
due_back=return_date, | ||
borrower=the_borrower, | ||
status=status, | ||
) | ||
|
||
def test_redirect_if_not_logged_in(self): | ||
response = self.client.get(reverse('my-borrowed')) | ||
self.assertRedirects(response, '/accounts/login/?next=/catalog/mybooks/') | ||
|
||
def test_logged_in_uses_correct_template(self): | ||
login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') | ||
response = self.client.get(reverse('my-borrowed')) | ||
|
||
# Check our user is logged in | ||
self.assertEqual(str(response.context['user']), 'testuser1') | ||
# Check that we got a response "success" | ||
self.assertEqual(response.status_code, 200) | ||
|
||
# Check we used correct template | ||
self.assertTemplateUsed(response, 'catalog/bookcopy_list_borrowed_user.html') | ||
|
||
def test_only_borrowed_books_in_list(self): | ||
login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') | ||
response = self.client.get(reverse('my-borrowed')) | ||
|
||
# Check our user is logged in | ||
self.assertEqual(str(response.context['user']), 'testuser1') | ||
# Check that we got a response "success" | ||
self.assertEqual(response.status_code, 200) | ||
|
||
# Check that initially we don't have any books in list (none on loan) | ||
self.assertTrue('bookcopy_list' in response.context) | ||
self.assertEqual(len(response.context['bookcopy_list']), 0) | ||
|
||
# Now change all books to be on loan | ||
books = BookCopy.objects.all()[:10] | ||
|
||
for book in books: | ||
book.status = 'o' | ||
book.save() | ||
|
||
# Check that now we have borrowed books in the list | ||
response = self.client.get(reverse('my-borrowed')) | ||
# Check our user is logged in | ||
self.assertEqual(str(response.context['user']), 'testuser1') | ||
# Check that we got a response "success" | ||
self.assertEqual(response.status_code, 200) | ||
|
||
self.assertTrue('bookcopy_list' in response.context) | ||
|
||
# Confirm all books belong to testuser1 and are on loan | ||
for bookitem in response.context['bookcopy_list']: | ||
self.assertEqual(response.context['user'], bookitem.borrower) | ||
self.assertEqual(bookitem.status, 'o') | ||
|
||
def test_pages_ordered_by_due_date(self): | ||
# Change all books to be on loan | ||
for book in BookCopy.objects.all(): | ||
book.status= False | ||
book.save() | ||
|
||
login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') | ||
response = self.client.get(reverse('my-borrowed')) | ||
|
||
# Check our user is logged in | ||
self.assertEqual(str(response.context['user']), 'testuser1') | ||
# Check that we got a response "success" | ||
self.assertEqual(response.status_code, 200) | ||
|
||
# Confirm that of the items, only 10 are displayed due to pagination. | ||
self.assertEqual(len(response.context['bookcopy_list']), 10) | ||
|
||
last_date = 0 | ||
for book in response.context['bookcopy_list']: | ||
if last_date == 0: | ||
last_date = book.due_back | ||
else: | ||
self.assertTrue(last_date <= book.due_back) | ||
last_date = book.due_back | ||
|
||
|
||
## Testing View with Forms | ||
import uuid | ||
|
||
from django.contrib.auth.models import Permission # Required to grant the permission needed to set a book as returned. | ||
|
||
class RenewBookInstancesViewTest(TestCase): | ||
def setUp(self): | ||
# Create a user | ||
test_user1 = User.objects.create_user(username='testuser1', password='1X<ISRUkw+tuK') | ||
test_user2 = User.objects.create_user(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
|
||
test_user1.save() | ||
test_user2.save() | ||
|
||
|
||
# Create a book | ||
test_book = Book.objects.create( | ||
title='Book Title', | ||
author='test_author', | ||
) | ||
|
||
test_book.save() | ||
|
||
# Create a BookInstance object for test_user1 | ||
return_date = datetime.date.today() + datetime.timedelta(days=5) | ||
self.test_bookinstance1 = BookCopy.objects.create( | ||
book=test_book, | ||
due_back=return_date, | ||
borrower=test_user1, | ||
status='o', | ||
) | ||
|
||
# Create a BookInstance object for test_user2 | ||
return_date = datetime.date.today() + datetime.timedelta(days=5) | ||
self.test_bookinstance2 = BookCopy.objects.create( | ||
book=test_book, | ||
due_back=return_date, | ||
borrower=test_user2, | ||
status='o', | ||
) | ||
|
||
def test_redirect_if_not_logged_in(self): | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) | ||
# Manually check redirect (Can't use assertRedirect, because the redirect URL is unpredictable) | ||
self.assertEqual(response.status_code, 302) | ||
self.assertTrue(response.url.startswith('/accounts/login/')) | ||
|
||
def test_forbidden_if_logged_in_but_not_correct_permission(self): | ||
login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) | ||
self.assertEqual(response.status_code, 403) | ||
|
||
def test_logged_in_with_permission_borrowed_book(self): | ||
login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance2.pk})) | ||
|
||
# Check that it lets us login - this is our book and we have the right permissions. | ||
self.assertEqual(response.status_code, 200) | ||
|
||
def test_logged_in_with_permission_another_users_borrowed_book(self): | ||
login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) | ||
|
||
# Check that it lets us login. We're a librarian, so we can view any users book | ||
self.assertEqual(response.status_code, 200) | ||
|
||
def test_HTTP404_for_invalid_book_if_logged_in(self): | ||
# unlikely UID to match our bookinstance! | ||
test_uid = uuid.uuid4() | ||
login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk':test_uid})) | ||
self.assertEqual(response.status_code, 404) | ||
|
||
def test_uses_correct_template(self): | ||
login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) | ||
self.assertEqual(response.status_code, 200) | ||
|
||
# Check we used correct template | ||
self.assertTemplateUsed(response, 'catalog/book_renew_librarian.html') | ||
|
||
def test_form_renewal_date_initially_has_date_three_weeks_in_future(self): | ||
login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) | ||
self.assertEqual(response.status_code, 200) | ||
|
||
date_3_weeks_in_future = datetime.date.today() + datetime.timedelta(weeks=3) | ||
self.assertEqual(response.context['form'].initial['renewal_date'], date_3_weeks_in_future) | ||
|
||
def test_redirects_to_all_borrowed_book_list_on_success(self): | ||
login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') | ||
valid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=2) | ||
response = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':valid_date_in_future}) | ||
self.assertRedirects(response, reverse('all-borrowed')) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you should use a linter also to avoid lint issue like missing newline an end or any other lint issues. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to have import at top (one place). here you are also reimporting book that should not be done.