之前写的lists/tests.py中的单元测试,要查找特定的HTML字符串,但这不是测试HTML的高效方法。

单元测试规则之一“不测试常量”,编写断言检测HTML字符串中是否有制定的字符串序列,不是单元测试应该做的。

单元测试要测试的其实时逻辑,流程控制和配置。

Python代码中插入原始字符串不是处理HTML的正确方式,我们有更好的方式,就是使用模板。把HTML放在一个扩展名为.html的文件中。

让视图函数返回一样的HTML,但使用不同的处理方式,这个过程叫重构,即在功能不变的前提下改进代码。重构的首要原则时不能没有测试,检查一下测试是否通过,测试通过才能保证前后的表现一致。

$ python manage.py test
[...]
OK

把HTML字符串提取出来写入单独的文件,新建用于保存模板的文件夹lists/templates,然后新建文件lists/templates/home.html

<html>
<title>To-Do lists</title>
</html>
高亮显示,漂亮多了

修改视图函数lists/views.py

from django.shortcuts import render

# Create your views here.在这儿编写视图
def home_page(request):
return render(request, 'home.html') # render函数中第一个参数是请求对象的,第二个参数是渲染的模板名

现在不构建HttpResponse对象了,转而使用Django中的render函数。Django会自动在所有的应用目录中搜索名为templates的文件夹,然后根据模板中的内容构建一个HttpResponse对象

单元测试

python manage.py test

======================================================================
ERROR: test_home_page_returns_correct_html (lists.tests.HomePageTest) # 1
----------------------------------------------------------------------
Traceback (most recent call last):
File "/studydisk/Python_web_TDD/django1x/subperlists/lists/tests.py", line 19, in test_home_page_returns_correct_html
response = home_page(request) #
File "/studydisk/Python_web_TDD/django1x/subperlists/lists/views.py", line 5, in home_page
return render(request, 'home.html') # 3
File "/root/anaconda3/envs/django1.0/lib/python3.5/site-packages/django/shortcuts.py", line 30, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "/root/anaconda3/envs/django1.0/lib/python3.5/site-packages/django/template/loader.py", line 67, in render_to_string
template = get_template(template_name, using=using)
File "/root/anaconda3/envs/django1.0/lib/python3.5/site-packages/django/template/loader.py", line 25, in get_template
raise TemplateDoesNotExist(template_name, chain=chain)
django.template.exceptions.TemplateDoesNotExist: home.html # 4 ----------------------------------------------------------------------
Ran 2 tests in 0.103s FAILED (errors=1)
Destroying test database for alias 'default'...

分析错误

1、先看错误是什么测试无法找到模板(#4)

2、确认是哪个测试失败,显然时测试视图HTML的测试(#1)

3、找到导致失败的是测试中哪一行:调用home_page函数那行(# 2)

4、在应用的代码中找到导致失败的部分:调用render函数那段(#3)

为什么Django找不到模板呢?模板的确是在lists/templates文件夹中。

原因是还没有正式在Django中注册lists应用,执行startapp命令以及在项目文件夹中存放一个应用还不够,要告诉Django确实要开发一个应用,并把这个应用添加到文件settings.py中,这样才能保证。

打开setting.py,找到变量INSTALLED_APPS,把lists加进去。

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'lists',
]

再次运行测试

$ python manage.py test
[...]
OK

Django学习系列7:使用模板解决“不测试常量”规则,使用模板重构的更多相关文章

  1. Django学习系列之Form基础

     Django学习系列之Form基础 2015-05-15 07:14:57 标签:form django 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追 ...

  2. Django学习系列17:在模板中渲染待办事项

    前面提到的问题中在表格中显示多个待办事项 是最后一个容易解决的问题.要编写一个新单元测试,检查模板是否也能显示多个待办事项: lists/tests.py def test_displays_all_ ...

  3. Django学习系列之模板系统

    一.模板标签 if/else {%  if  %}标签检查一个变量的值是否为真或者等于另外一个值,如果为真,系统会执行{%  if  %}和{%  endif  %}之间的代码块,例如: {% if ...

  4. Django学习系列之模板

    什么是django模板 模板是一个文本,用于分离文档的表现形式和内容,模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签) 模板通常用于产生HTML 如何使用模板 创建一个Tem ...

  5. Django学习之十三:提高页面开发效率减少冗余的模板系统

    目录 Django 模板 模板语法 逻辑语法 函数式过滤器 内置filter 功能tag 注释 内置tag 导入三方tag and filter(load) 过滤器和功能tag的区别 自定义tag和f ...

  6. Django学习系列6:使用selenium测试用户交互

    学习系列5中的单元测试有报错信息,这儿来编写functional_tests.py文件,扩充其中的功能测试 # File: functional_test.py # Author: Rxf # Cre ...

  7. Django学习系列之Form验证

    django表单基础 django表单分类 基于django.forms.Form:所有表单类的父类 基于django.forms.ModelForm:可以和模型类绑定的Form Form验证流程 定 ...

  8. Django学习系列21:为每一个清单添加唯一URL

    现在让我们来解决我们真正的问题,即我们的设计只允许一个全局列表. 我将演示一个关键的TDD技术:如何使用一个渐进的.循序渐进的过程来适应现有的代码,这些过程将您从工作状态转移到工作状态.测试山羊,而不 ...

  9. Django学习系列12:把Python变量传入模板中渲染

    从视图的Python代码中把变量传入HTML模板. 模板中使用哪种句法引入Python对象,要使用的符号{{...}},它会以字符串的形式显示对象: <html> <head> ...

随机推荐

  1. Array 操作

    一.数组拉平 function arrayFlat(arr) { return arr.reduce((pre, cur) => { const temp = Array.isArray(cur ...

  2. C#的语音识别 using System.Speech.Recognition;

    using System; using System.Collections.Generic; using System.Linq; using System.Speech.Recognition; ...

  3. c++中字符输入函数cin.getline在输入char与string时的不同

    cin.getline在输入char时: using namespace std; ; char name[ArSize]; char dessert[ArSize]; cout << & ...

  4. NSIS打包electron程序为exe安装包

    在我的上一篇博客已经介绍了将electron程序生成一个exe可执行文件,但是这并不是最终能够发给用户用来安装的最终安装包,下面我们就介绍如何使用NISI将我们的应用程序打包成安装包: 上一篇博客我们 ...

  5. linux(centOS7)的基本操作(五) 磁盘、分区、挂载、卸载

    linux的磁盘类型和分区简介 linux的磁盘分为IDE和SCSI,目前以后者居多. 1. IDE磁盘的分区:hd+盘号+分区数字 盘号 |-a:基本盘 |-b:基本从属盘 |-c:辅助主盘 |-d ...

  6. 在Spring容器外调用bean

    这个东西源于这种需求:一个应用丢到服务其后,不管用户有没有访问项目,这个后台线程都必须给我跑,而且这个线程还调用了Spring注入的bean,这样自然就会想到去监听Servlet的状态,当Servle ...

  7. Python学习之协程

    8.8 协程 ​ 我们都知道线程间的任务切换是由操作系统来控制的,而协程的出现,就是为了减少操作系统的开销,由协程来自己控制任务的切换 ​ 协程本质上就是线程.既然能够切换任务,所以线程有两个最基本的 ...

  8. Python基础语法之文件操作

    1 读文件 1.1 简单读文件 f = open('text', 'r') # f是文件句柄 data = f.read() # read方法可以加整型参数,是几就读几个字符 print(data) ...

  9. Win10 开启 热点的简单办法

  10. olap和Oltp(转)

    OLAP和OLTP的区别(基础知识) 联机分析处理 (OLAP) 的概念最早是由关系数据库之父E.F.Codd于1993年提出的,他同时提出了关于OLAP的12条准则.OLAP的提出引起了很大的反响, ...