Django tutorial part5

本文介绍如何为Django应用编写测试代码,包括单元测试和视图测试。通过具体示例展示了如何确保应用逻辑正确并验证视图按预期工作。

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
'\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 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
'\n\n\n    <ul>\n    \n        <li><a href="/polls/1/">Who is your favorite Beatle?</a></li>\n    \n    </ul>\n\n'
>>> # 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

转载于:https://www.cnblogs.com/jolin123/p/4352991.html

嗯,用户想要找从Python入门到全栈开发的免费学习网站。我先看看参考内容里的信息有没有合适的资源。 第一个参考内容提到腾讯课堂的星越教育课程,但看起来是付费的,可能不符合用户的免费需求。第二个和第五个参考内容提到了优快云博客里的资源,里面有很多免费视频,比如B站的千锋教育和黑马程序员的教程链接,这些应该都是免费的。第三个和第六个参考内容推荐了官方文档、w3school、菜鸟教程,这些网站都是经典的学习资源,完全免费。还有ProgramCreek和LearnPython这样的英文网站,可能适合有一定英语基础的学习者。 另外,第五个参考内容里提到百度网盘的资料,但链接可能需要提取密码,用户可能需要注册或关注才能获取,不过也是免费资源。Udacity的免费课程和Google的Python课程也是不错的选项,尤其是Google的课程质量应该很高。 需要确认的是这些资源是否都还在线,比如B站的视频链接是否有效。用户可能需要自行访问确认,但大部分应该是可用的。总结的时候应该分门别类,比如视频教程、文档网站、实战项目等,让用户方便选择。要确保涵盖从基础到全栈的不同阶段,包括Web开发、爬虫、数据库等内容。需要注意用户要的是全栈,所以后端和前端的内容都要包含。比如Django框架、数据库持久化部分,这些在参考内容里有提到,可以整合进去。 还要注意时效性,虽然参考内容发布时间在2024到2025年之间,但大部分资源比如官方文档和B站教程通常长期有效。可能建议用户优先选择中文资源,如果英语好可以看英文网站。同时提醒用户实践的重要性,结合项目来学习。最后整理成一个结构清晰的回答,列出每个资源类型和对应的链接,方便用户使用。 以下是针对Python从入门到全栈开发的免费学习资源推荐,结合权威性与时效性,覆盖基础语法、Web开发、数据库、爬虫等全栈方向:   一、系统化视频教程(免费) 1. B站千锋教育Python教程      ○ 特点:700集零基础课程,涵盖基础语法、Web开发、爬虫、数据分析、AI基础。      ○ 链接:B站700集教程 2. B站黑马程序员Python教程      ○ 特点:600集系统课程,基于Linux环境,包含基础语法、面向对象、游戏开发。      ○ 链接:B站600集教程 3. Udacity Python入门课(英文)           ○ 特点:免费入门课程,结合搜索引擎与网络爬虫项目,适合动手实践。      ○ 链接:Intro to Computer Science   二、官方文档与中文社区 1. Python官方中文文档      ○ 特点:最权威的语法参考,覆盖基础语法、标准库及进阶指南。      ○ 链接:Python中文文档 2. 菜鸟教程 & W3School           ○ 特点:新手友好,提供Python语法、实例及操作步骤详解。      ○ 链接:          ● 菜鸟教程Python          ● W3School Python   三、实战项目与案例 1. ProgramCreek Python代码实例      ○ 特点(英文):海量模块实例(如 datetime 、 requests ),直接搜索函数名称即可查看用法。      ○ 链接:Python Code Examples 2. Github开源项目           ○ 推荐:搜索关键词“Python全栈项目”,如Django博客系统、电商平台。      ○ 学习方式:阅读代码 → 复现功能 → 参与Issue讨论。   四、专项技能提升 1. Web开发(Django/Flask)      ○ 资源推荐:          ● B站Django教程:全栈开发教程          ● Flask官方文档:Flask中文指南 2. 数据库与数据持久化      ○ 免费课:B站搜索“MySQL+Python”或“SQLAlchemy教程”,如SQLAlchemy ORM教程。 3. 爬虫开发(Scrapy/Requests)           ○ B站爬虫框架Scrapy实战:Scrapy框架教程   五、综合学习平台 1. LearnPython(英文)      ○ 特点:交互式学习,涵盖初级到高级语法,附带在线代码编辑器。      ○ 链接:LearnPython 2. Google Python Class           ○ 特点:Google官方课程,包含文本与视频教程,适合快速上手。      ○ 链接:Google Python课程   六、国内免费资源包 1. 优快云博主共享资料      ○ 内容:Python零基础入门、爬虫开发、Web全栈资料包(需百度网盘提取)。      ○ 获取方式:访问此链接 按指引领取。   学习建议 1. 路线:先掌握基础语法(变量、循环、函数)→ 学习数据库与Web框架 → 实战项目 → 深入爬虫/数据分析。 2. 实践:每学完一个知识点,用代码实现小功能(如爬取天气、搭建个人博客)。 3. 社区:加入Python技术群或Stack Overflow,遇到问题及时提问。 希望这些资源能助你从入门到全栈!
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值