[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 5-

Introduction

Nice to meet you, everyone. I'm going to publish a memorandum of the process of creating a voting (poll) application using Django. Since I am a beginner of Qiita, please understand that some parts may be difficult to read.

series

-[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-No. 0- -[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 1- -[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 2- -[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 3- -[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 4-

Start work

Introducing automated testing

I'll write the code to use with Django's automated testing feature.

Creating your first test

What code do you need to test Django? First, run the test interactively.

Test content: Confirm that the was_published_recently function is False when the Question pub_date is in the future date (30 days from today). Test result: FAILD (The expected behavior of was_published_recently is False, but the actual behavior is True)


(poll-HcNSSqhc) C:\django\poll>python manage.py shell
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:37:30) [MSC v.1927 32 bit (Intel)] on win32     
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
>>> import datetime
>>> from django.utils import timezone
>>> from polls.models import Question
>>>
>>> future_question = Question(pub_date=timezone.now()+datetime.timedelta(days=30))
>>> future_question.was_published_recently()
True
>>>

Code this. The expected behavior in self.assertIs is False.

polls/tests.py



from django.test import TestCase

import datetime
from django.utils import timezone
from .models import Question

# Create your tests here.


class QuestionModelTests(TestCase):
    def test_was_published_recently_whit_future_question(self):
        future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
        self.assertIs(future_question.was_published_recently(), False)

Now let's run the test. Of course it's not interactive.


(poll-HcNSSqhc) C:\django\poll>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_was_published_recently_whit_future_question (polls.tests.QuestionModelTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\django\poll\polls\tests.py", line 13, in test_was_published_recently_whit_future_question
    self.assertIs(future_question.was_published_recently(), False)
AssertionError: True is not False

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)
Destroying test database for alias 'default'...

(poll-HcNSSqhc) C:\django\poll>

It is returning FAILD firmly. (The expected behavior of was_published_recently is False, but the actual behavior is True)

Now let's debug.

polls/models.py



    def was_published_recently(self):
        return timezone.now() - datetime.timedelta(days=1) <= self.pub_date <= timezone.now()

(poll-HcNSSqhc) C:\django\poll>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
Destroying test database for alias 'default'...

(poll-HcNSSqhc) C:\django\poll>

It was OK. (The expected behavior of was_published_recently is False, and the actual behavior is False.)

More comprehensive testing

Let's add more test items for the same class. A limit value test item is added.

polls/tests.py



    def test_was_published_recently_with_old_question(self):
        old_question = Question(pub_date=timezone.now() - datetime.timedelta(days=1, seconds=1))
        self.assertIs(old_question.was_published_recently(), False)

    def test_was_published_recently_with_recently_question(self):
        recently_question = Question(pub_date=timezone.now(
        ) - datetime.timedelta(hours=23, minutes=59, seconds=59))
        self.assertIs(recently_question.was_published_recently(), True)

(poll-HcNSSqhc) C:\django\poll>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.004s

OK
Destroying test database for alias 'default'...

(poll-HcNSSqhc) C:\django\poll>

OK is displayed.

Test the view

Use the Client class to test your views in Django. First, run the test interactively.

Test content: The view "http://127.0.0.1/polls" exists Test result: HTTP200 and content can be obtained


(poll-HcNSSqhc) C:\django\poll>python manage.py shell
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:37:30) [MSC v.1927 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 
>>> 
>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()  
>>> from django.test import Client
>>> from django.urls import reverse
>>> client = Client()
>>> response = client.get(reverse('polls:index'))      
>>> 
>>> response.status_code
200
>>>
>>> response.content
b'\n    <ul>\n    \n        <li><a href="/polls/5/">What&#x27;s this?</a></li>\n    \n    </ul>\n'
>>>
>>> response.context['latest_question_list'] 
<QuerySet [<Question: What's this?>]>
>>>

Improve the view

There is a problem displaying votes that are dated in the future, so let's fix it.

Question.objects.filter () means to filter, and pub_date__lte = timezone.now () is a conditional expression whose pub_date is less than or equal to timezone.now () (less than equal).

polls/views.py



from django.utils import timezone

class IndexView(generic.ListView):
    ***
    def get_queryset(self):
        return Question.objects.filter(pub_date__lte=timezone.now()).order_by('-pub_date')[:5]

Test a new view

Prepare the test code.

polls/tests.py



from django.urls import reverse

def create_question(question_text, days):
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)


class QuestionIndexViewTest(TestCase):
    #HTTP200, screen message: No polls are available., Question list: empty
    def test_no_question(self):
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    #Question list: Past question.
    def test_past_question(self):
        create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(response.context['latest_question_list'], [
                                 '<Question: Past question.>'])

    #Question list: empty(Future questions are not displayed)
    def test_feature_question(self):
        create_question(question_text="Feature question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    #Question list: Past question.(Future questions are not displayed)
    def test_feature_question_and_past_question(self):
        create_question(question_text="Feature question.", days=30)
        create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(response.context['latest_question_list'], [
                                 '<Question: Past question.>'])

    #Question list: Past question1.、Past question2.
    #Note that the question list is retrieved in the order of the latest posts, so the creation order and retrieval order will be weak.
    def test_tow_past_question(self):
        create_question(question_text="Past question1.", days=-30)
        create_question(question_text="Past question2.", days=-10)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(response.context['latest_question_list'], [
                                 '<Question: Past question2.>', '<Question: Past question1.>'])

(poll-HcNSSqhc) C:\django\poll>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
........
----------------------------------------------------------------------
Ran 8 tests in 0.063s

OK
Destroying test database for alias 'default'...

(poll-HcNSSqhc) C:\django\poll>

OK is displayed.

DetailView test

The detail view is also ready to display question details for future dates, so let's fix it.

polls/views.py



class DetailView(generic.DetailView):
  ***
    def get_queryset(self):
        return Question.objects.filter(pub_date__lte=timezone.now())

polls/tests.py



class QuestionDetailViewTests(TestCase):
    def test_future_question(self):
        future_question = create_question(question_text="Future question.", days=5)
        url = reverse('polls:detail', args=(future_question.id,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

    def test_past_question(self):
        past_question = create_question(question_text="Past question.", days=-5)
        url = reverse('polls:detail', args=(past_question.id,))
        response = self.client.get(url)
        self.assertContains(response, past_question.question_text)

(poll-HcNSSqhc) C:\django\poll>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..........
----------------------------------------------------------------------
Ran 10 tests in 0.088s

OK
Destroying test database for alias 'default'...

(poll-HcNSSqhc) C:\django\poll>

That's all for today. Thank you very much.

Recommended Posts

[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 7-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 1-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 2-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 0-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 5-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 6-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 4-
[Beginner] [Python / Django] A fledgling web engineer tried a Django tutorial-Part 3-
Django python web framework
Deploy a Python 3.6 / Django / Postgres web app on Azure
(Python) Try to develop a web application using Django
CTF beginner tried to build a problem server (web) [Problem]
Web scraping beginner with python
[Django3] Display a web page in Django3 + WSL + Python virtual environment
A liberal arts engineer tried knocking 100 language processes in Python 02
A python beginner tried to intern at an IT company
A liberal arts engineer tried knocking 100 language processes in Python 01
A liberal arts engineer tried knocking 100 language processes in Python 00
If you know Python, you can make a web application with Django
[Python / Django] Create a web API that responds in JSON format
I tried web scraping with python.
Build a web application with Django
Python beginner tried 100 language processing knock 2015 (05 ~ 09)
web coder tried excel in Python
When a Python beginner tried using Bottle, it worked unexpectedly easily.
Python beginner tried 100 language processing knock 2015 (00 ~ 04)
A beginner of machine learning tried to predict Arima Kinen with python
An introduction to self-made Python web applications for a sluggish third-year web engineer
A note where a Python beginner got stuck
[Beginner] Python web scraping using Google Colaboratory
I have a question! (Python, django) Easy
Daemonize a Python web app with Supervisor
I tried a functional language with Python
[Python] A quick web application with Bottle!
I tried to make a Web API
Use Django from a local Python script
Run a Python web application with Docker
Let's make a web framework with Python! (1)
I tried benchmarking a web application framework
Let's make a web framework with Python! (2)
I made a WEB application with Django
A python beginner tried to intern at an IT company [Day 2 chatbot survey]
A python beginner tried to intern at an IT company [Day 1 development process]
Go beginner tried to create a cloud native web application using Datastore / GAE
[ES Lab] I tried to develop a WEB application with Python and Flask ②
I searched for the skills needed to become a web engineer in Python
Machine learning memo of a fledgling engineer Part 1
2-2. Input for becoming a WEB engineer (Linux basics)
I tried web scraping using python and selenium
I tried playing a typing game in Python
Start a simple Python web server with Docker
[Python] Build a Django development environment with Docker
[Memo] I tried a pivot table in Python
[Python] Draw a Mickey Mouse with Turtle [Beginner]
Create a web map using Python and GDAL
Steps to develop a web application in Python
[Python] Web development preparation (building a virtual environment)
I tried reading a CSV file using Python
Programming beginner Python3 engineer certification basic exam record
Launch a web server with Python and Flask
Machine learning memo of a fledgling engineer Part 2