zoukankan      html  css  js  c++  java
  • Django tutorial part5

    writing_first_django_app_part5

    Automated Testing

    解决问题一个很好的方法是首先描述这个问题,然后写出代码来实现它。但是很多人习惯先写好代码然后再进行调试找问题。也许在写代码之前先写好一些测试会是更好的选择。

    A little bug

    前面在我们的Question.was_published_recently()函数中有一个小问题,如果它是一天之内创建的则会返回True,但是如果pub_date是未来的时间也会返回True

    通常应用的测试会放到tests.py文件中,现在在polls/tests.py里添加测试:

    import datetime
    
    from django.utils import timezone
    from django.test import TestCase
    
    from polls.models import Question
    
    class QuestionMethodTests(TestCase):
    
        def test_was_published_recently_with_future_question(self):
            """
            was_published_recently() should return False for questions whose
            pub_date is in the future.
            """
            time = timezone.now() + datetime.timedelta(days=30)
            future_question = Question(pub_date=time)
            self.assertEqual(future_question.was_published_recently(), False)
    

    这个测试类是继承于TestCase类,它创建了一个将来时间的Question,然后self.assertEqual()函数是测试函数的返回结果,正确应该返回False

    运行这个测试:

    $ python manage.py test polls
    

    得到如下结果:

    Creating test database for alias 'default'...
    F
    ======================================================================
    FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionMethodTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/path/to/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_question
        self.assertEqual(future_question.was_published_recently(), False)
    AssertionError: True != False
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.001s
    
    FAILED (failures=1)
    Destroying test database for alias 'default'...
    

    首先test polls会在polls应用下查找测试,然后找到TestCase类的子类,就会创建一个特定的数据库来进行测试。测试类中测试的函数会以'test'开头,即上面的test_was published_...,最后就是运行assertEqual函数看结果是否与预想的一致,上面的结果是FAILED

    修正polls/models.py:

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

    再次运行测试:

    Creating test database for alias 'default'...
    .
    ----------------------------------------------------------------------
    Ran 1 test in 0.001s
    
    OK
    Destroying test database for alias 'default'...
    

    测试异常的情况之后,还要加上一个正确的例子,函数应该返回True:

    def test_was_published_recently_with_recent_question(self):
        """
        was_published_recently() should return True for questions whose
        pub_date is within the last day.
        """
        time = timezone.now() - datetime.timedelta(hours=1)
        recent_question = Question(pub_date=time)
        self.assertEqual(recent_question.was_published_recently(), True)
    
    Test a view

    Django提供一个测试Client来模拟一个用户在view测层面与代码进行交互。可以通过tests.py或者shell来进行。

    用shell来测试:

    # 设置测试环境
    >>> from django.test.utils import setup_test_environment
    >>> setup_test_environment()
    
    # 建立一个client来进行测试
    >>> from django.test import Client
    >>> # create an instance of the client for our use
    >>> client = Client()
    
    # 一些测试用例
    >>> # 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 hardcoded URL
    >>> from django.core.urlresolvers import reverse
    >>> response = client.get(reverse('polls:index'))
    >>> response.status_code
    200
    >>> response.content
    '
    
    
        <p>No polls are available.</p>
    
    '
    >>> # 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 Question
    >>> from django.utils import timezone
    >>> # create a Question and save it
    >>> q = Question(question_text="Who is your favorite Beatle?", pub_date=timezone.now())
    >>> q.save()
    >>> # check the response once again
    >>> response = client.get('/polls/')
    >>> response.content
    '
    
    
        <ul>
        
            <li><a href="/polls/1/">Who is your favorite Beatle?</a></li>
        
        </ul>
    
    '
    >>> # If the following doesn't work, you probably omitted the call to
    >>> # setup_test_environment() described above
    >>> response.context['latest_question_list']
    [<Question: Who is your favorite Beatle?>]
    

    前面我们使用了generic.ListView来创建view,如下:

    # polls/views.py
    
    class IndexView(generic.ListView):
        template_name = 'polls/index.html'
        context_object_name = 'latest_question_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            return Question.objects.order_by('-pub_date')[:5]
    

    最后返回Question并没有对时间在现在之后的进行筛选,我们作出修改:

    from django.utils import timezone
    
    def get_queryset(self):
        """
        Return the last five published questions (not including those set to be
        published in the future).
        """
        return Question.objects.filter(
            pub_date__lte=timezone.now()
        ).order_by('-pub_date')[:5]
    

    filter(pub_date__lte=timezone.now()返回时间早于或者等于now的Questions

    Testing the view

    在tests.py中添加对index的测试:

    from django.core.urlresolvers import reverse
    
    def create_question(question_text, days):
        """
        Creates a question with the given `question_text` published the given
        number of `days` offset to now (negative for questions published
        in the past, positive for questions that have yet to be published).
        """
        time = timezone.now() + datetime.timedelta(days=days)
        return Question.objects.create(question_text=question_text,
                                       pub_date=time)
    
    class QuestionViewTests(TestCase):
        def test_index_view_with_no_questions(self):
            """
            If no questions exist, an appropriate message should be displayed.
            """
            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'], [])
    
    self.assertQuerysetEqual(response.context['latest_question_list'], [])
    
    def test_index_view_with_a_past_question(self):
            """
            Questions with a pub_date in the past should be displayed on the
            index page.
            """
            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.>']
            )
    
    def test_index_view_with_a_future_question(self):
            """
            Questions with a pub_date in the future should not be displayed on
            the index page.
            """
            create_question(question_text="Future question.", days=30)
            response = self.client.get(reverse('polls:index'))
            self.assertContains(response, "No polls are available.",
                                status_code=200)
    
    self.assertQuerysetEqual(response.context['latest_question_list'], [])
    
        def test_index_view_with_future_question_and_past_question(self):
            """
            Even if both past and future questions exist, only past questions
            should be displayed.
            """
            create_question(question_text="Past question.", days=-30)
            create_question(question_text="Future question.", days=30)
            response = self.client.get(reverse('polls:index'))
            self.assertQuerysetEqual(
                response.context['latest_question_list'],
                ['<Question: Past question.>']
            )
    
    def test_index_view_with_two_past_questions(self):
            """
            The questions index page may display multiple questions.
            """
            create_question(question_text="Past question 1.", days=-30)
            create_question(question_text="Past question 2.", days=-5)
            response = self.client.get(reverse('polls:index'))
            self.assertQuerysetEqual(
                response.context['latest_question_list'],
                ['<Question: Past question 2.>', '<Question: Past question 1.>']
            )
    

    首先为了方便在测试的时候创建question,先定义函数create_question. 下面几个函数分别对几个情况进行测试,注意函数命名要体现测试的内容。

    Test DetailView
    class DetailView(generic.DetailView):
        ...
        def get_queryset(self):
            """
            Excludes any questions that aren't published yet.
            """
            return Question.objects.filter(pub_date__lte=timezone.now())
    
    # polls/tests.py
    
    class QuestionIndexDetailTests(TestCase):
        def test_detail_view_with_a_future_question(self):
            """
            The detail view of a question with a pub_date in the future should
            return a 404 not found.
            """
            future_question = create_question(question_text='Future question.',
                                              days=5)
            response = self.client.get(reverse('polls:detail',
                                       args=(future_question.id,)))
            self.assertEqual(response.status_code, 404)
    
        def test_detail_view_with_a_past_question(self):
            """
            The detail view of a question with a pub_date in the past should
            display the question's text.
            """
            past_question = create_question(question_text='Past Question.',
                                            days=-5)
            response = self.client.get(reverse('polls:detail',
                                       args=(past_question.id,)))
            self.assertContains(response, past_question.question_text,
                                status_code=200)
    

    上面就是一些测试的例子,测试代码可能看起来很多,但其实它们都是非常有用的。When testing, more is better

  • 相关阅读:
    Spring Cloud Hystrix Dashboard的使用 5.1.3
    Spring Cloud Hystrix 服务容错保护 5.1
    Spring Cloud Ribbon 客户端负载均衡 4.3
    Spring Cloud 如何实现服务间的调用 4.2.3
    hadoop3.1集成yarn ha
    hadoop3.1 hdfs的api使用
    hadoop3.1 ha高可用部署
    hadoop3.1 分布式集群部署
    hadoop3.1伪分布式部署
    KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机
  • 原文地址:https://www.cnblogs.com/jolin123/p/4352991.html
Copyright © 2011-2022 走看看