笨鸟编程-零基础入门Pyhton教程

 找回密码
 立即注册

编写你的第一个 Django 程序 第5部分

发布者: 三寸日光



More comprehensive tests

While we’re here, we can further pin down the was_published_recently() method; in fact, it would be positively embarrassing if in fixing one bug we had introduced another.

Add two more test methods to the same class, to test the behavior of the method more comprehensively:

def test_was_published_recently_with_old_poll(self):
    """
    was_published_recently() should return False for polls whose pub_date
    is older than 1 day
    """
    old_poll = Poll(pub_date=timezone.now() - datetime.timedelta(days=30))
    self.assertEqual(old_poll.was_published_recently(), False)

def test_was_published_recently_with_recent_poll(self):
    """
    was_published_recently() should return True for polls whose pub_date
    is within the last day
    """
    recent_poll = Poll(pub_date=timezone.now() - datetime.timedelta(hours=1))
    self.assertEqual(recent_poll.was_published_recently(), True)

And now we have three tests that confirm that Poll.was_published_recently() returns sensible values for past, recent, and future polls.

Again, polls is a simple application, but however complex it grows in the future and whatever other code it interacts with, we now have some guarantee that the method we have written tests for will behave in expected ways.

Test a view

The polls application is fairly undiscriminating: it will publish any poll, including ones whose pub_date field lies in the future. We should improve this. Setting a pub_date in the future should mean that the Poll is published at that moment, but invisible until then.

A test for a view

When we fixed the bug above, we wrote the test first and then the code to fix it. In fact that was a simple example of test-driven development, but it doesn’t really matter in which order we do the work.

In our first test, we focused closely on the internal behavior of the code. For this test, we want to check its behavior as it would be experienced by a user through a web browser.

Before we try to fix anything, let’s have a look at the tools at our disposal.

The Django test client

Django provides a test Client to simulate a user interacting with the code at the view level. We can use it in tests.py or even in the shell.

We will start again with the shell, where we need to do a couple of things that won’t be necessary in tests.py. The first is to set up the test environment in the shell:

>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()

Next we need to import the test client class (later in tests.py we will use the django.test.TestCase class, which comes with its own client, so this won’t be required):

>>> from django.test.client import Client
>>> # create an instance of the client for our use
>>> client = Client()

With that ready, we can ask the client to do some work for us:

>>> # get a response from '/'
>>> response = client.get('/')
>>> # we should expect a 404 from that address
>>> response.status_code
404
>>> # on the other hand we should expect to find something at '/polls/'
>>> # we'll use 'reverse()' rather than a harcoded URL
>>> from django.core.urlresolvers import reverse
>>> response = client.get(reverse('polls:index'))
>>> response.status_code
200
>>> response.content
'\n\n\n    <p>No polls are available.</p>\n\n'
>>> # note - you might get unexpected results if your ``TIME_ZONE``
>>> # in ``settings.py`` is not correct. If you need to change it,
>>> # you will also need to restart your shell session
>>> from polls.models import Poll
>>> from django.utils import timezone
>>> # create a Poll and save it
>>> p = Poll(question="Who is your favorite Beatle?", pub_date=timezone.now())
>>> p.save()
>>> # check the response once again
>>> response = client.get('/polls/')
>>> response.content
'\n\n\n    <ul>\n    \n        <li><a href="/polls/1/">Who is your favorite Beatle?</a></li>\n    \n    </ul>\n\n'
>>> response.context['latest_poll_list']
[<Poll: Who is your favorite Beatle?>]

Improving our view

The list of polls shows polls that aren’t published yet (i.e. those that have a pub_date in the future). Let’s fix that.

In Tutorial 4 we deleted the view functions from views.py in favor of a ListView in urls.py:

url(r'^$',
    ListView.as_view(
        queryset=Poll.objects.order_by('-pub_date')[:5],
        context_object_name='latest_poll_list',
        template_name='polls/index.html'),
    name='index'),

response.context_data['latest_poll_list'] extracts the data this view places into the context.

We need to amend the line that gives us the queryset:

queryset=Poll.objects.order_by('-pub_date')[:5],

Let’s change the queryset so that it also checks the date by comparing it with timezone.now(). First we need to add an import:

from django.utils import timezone

and then we must amend the existing url function to:

url(r'^$',
    ListView.as_view(
        queryset=Poll.objects.filter(pub_date__lte=timezone.now) \
            .order_by('-pub_date')[:5],
        context_object_name='latest_poll_list',
        template_name='polls/index.html'),
    name='index'),

Poll.objects.filter(pub_date__lte=timezone.now) returns a queryset containing Polls whose pub_date is less than or equal to - that is, earlier than or equal to - timezone.now. Notice that we use a callable queryset argument, timezone.now, which will be evaluated at request time. If we had included the parentheses, timezone.now() would be evaluated just once when the web server is started.


Archiver|手机版|笨鸟自学网 ( 粤ICP备20019910号 )

GMT+8, 2024-12-27 00:27 , Processed in 0.016196 second(s), 17 queries .

© 2001-2020

返回顶部