Python Web开发:测试驱动方法(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-22 14:44:30

点击下载

作者:珀西瓦尔(Harry J.W. Percival)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python Web开发:测试驱动方法

Python Web开发:测试驱动方法试读:

前言

我试图通过这本书与世人分享我从黑客变成软件工程师的过程。本书主要介绍测试,但很快你就会发现,除此之外还有很多其他内容。

感谢你阅读本书。

如果你购买了本书,我十分感激。如果你看的是免费在线版,我仍然要感谢你,因为你确定这本书值得花时间来阅读。谁知道呢,说不定等你读完之后,会决定为自己或朋友买一本实体书。

如果你有任何评论、疑问或建议,希望你能写信告诉我。你可以通过电子邮件直接和我联系,地址是 obeythetestinggoat@gmail.com;或者在 Twitter 上联系我,我的用户名是 @hjwp。你还可以访问本书的网站和博客(http://www.obeythetestinggoat.com/),以及邮件列表(https://groups.google.com/forum/#!forum/obey-the-testing-goat-book)。

希望阅读本书能让你身心愉悦,就像我在写作本书时感到享受一样。为什么要写一本关于测试驱动开发的书

我知道你会问:“你是谁,为什么要写这本书,我为什么要读这本书?”

我至今仍然处在编程事业的初期。人们说,不管从事什么工作,都要历经从新手到熟手的过程,最终有可能成为大师。我要说的是,我最多算是个熟练的程序员。但我很幸运,在事业的早期阶段就结识了一群测试驱动开发(Test-Driven Development,TDD)的狂热爱好者,这对我的编程事业产生了极大影响,让我迫不及待地想和所有人分享这段经历。可以说,我很积极地做出了最近这次转变,而且这段学习经历现在还历历在目,我希望能让初学者感同身受。

我在开始学习 Python 时(看的是 Mark Pilgrim 写的 Dive Into Python),偶然知道了 TDD 的概念。我当时就认为:“是的,我绝对知道这个概念的意义所在。”或许你第一次听说 TDD 时也有类似的反应吧。它听起来像是一个非常合理的方案,一个需要养成的非常好的习惯——就像经常刷牙之类的习惯。

随后我做了第一个大型项目。你可能猜到了,有项目就会有客户,有最后期限,有很多事情要做。于是,所有关于 TDD 的好想法被抛诸脑后。

的确,这对项目没什么影响,对我也没影响。

但只是在初期如此。

一开始,我知道并不真的需要使用 TDD,因为我做的是个小网站,手动检查就能轻易测试出是否能用。在这儿点击链接,在那儿选中下拉菜单选项,就应该有预期的效果。很简单。编写整套测试程序听起来似乎要花费很长时间,而且,经过整整三周成熟的代码编写经历,我自负地认为自己已经成为一名出色的程序员了。我能顺利完成这个项目。这没什么难度。

随后,项目变得复杂得可怕,这很快暴露了我的经验不足。

项目不断变大。系统的不同部分之间要开始相互依赖。我尽量遵守良好的开发原则,例如“不要自我重复”(Don't Repeat Yourself,DRY),却被带进了一片危险地带。我很快就用到了多重继承,类的继承有八个层级深,还用到了 eval 语句。

我不敢修改代码,不再像以前一样知道什么依赖什么,也不知道修改某处的代码可能会导致什么后果。噢,天呐,我觉得那部分继承自这里,不,不是继承,是重新定义了,可是却依赖那个类变量。嗯,好吧,如果我再次重定义以前重定义的部分,应该就可以了。我会检查的,可是检查变得更难了。网站中的内容越来越多,手动点击变得不切实际了。最好别动这些能运行的代码,不要重构,就这么凑合吧。

很快,代码就变得像一团麻,丑陋不堪。开发新功能变得很痛苦。

在此之后不久,我幸运地在 Resolver Systems 公司(现在叫 PythonAnywhere,https://www.pythonanywhere.com/)找到了一份工作。这个公司遵循极限编程(Extreme Programming,XP)开发理念。他们向我介绍了严密的 TDD。

虽然之前的经验的确让我认识到自动化测试的好处,但我在每个阶段都心存疑虑。“我的意思是,测试通常来说可能是个不错的主意,但果真如此吗?全部都要测试吗?有些测试看起来完全是在浪费时间……什么?除了单元测试之外还要做功能测试?得了吧,这是多此一举!还要走一遍测试驱动开发中的‘测试 / 小幅度代码改动 / 测试 ’ 循环?太荒谬了!我们不需要这种婴儿学步般的过程!既然我们知道正确的答案是什么,为什么不直接跳到最后一步呢?”

相信我!我审视过每一条规则,给每一条捷径提出过建议,为 TDD 的每一个看似毫无意义的做法寻找过理由,最终,我发现了采用 TDD 的明智之处。我记不清在心里说过多少次“谢谢你,测试”,因为功能测试能揭示我们可能永远都无法预测的回归,单元测试能让我避免犯很愚蠢的逻辑错误。从心理学上讲,TDD 大大减少了开发过程中的压力,而且写出的代码让人赏心悦目。

那么,让我告诉你关于 TDD 的一切吧!写作本书的目的

我写这本书的主要目的是要传授一种用于 Web 开发的方法,它可以让 Web 应用变得更好,也能让开发者更愉快。一本书如果只包含一些上网搜索就能找到的知识,那它就没多大的意思了,所以本书不是 Python 句法指南,也不是 Web 开发教程。我希望教会你的,是如何使用 TDD 理念,更加稳妥地实现我们共同的神圣目标——简洁可用的代码。

即便如此,我仍会从零开始使用 Django、Selenium、jQuery 和 Mock 等工具开发一个 Web 应用,不断提到一个真实可用的示例。阅读本书之前,你无需了解这些工具。读完本书后,你会充分了解这些工具,并掌握 TDD 理念。

在极限编程实践中,我们总是结对编程。写这本书时,我设想自己和以前的自己结成对子,向以前的我解释如何使用这些工具,回答为什么要用这种特别的方式编写代码。所以,如果我表现得有点儿屈尊俯就,那是因为我不是那么聪明,我要对自己很有耐心。如果觉得我说话冒犯了你,那是因为我有点儿烦人,经常不认同别人的说法,所以有时要花很多时间论证,说服自己接受他人的观点。本书结构

我将这本书分成了三个部分。● 第一部分(第1~6章):基础知识

开门见山,介绍如何使用 TDD 开发一个简单的 Web 应用。我们

会先(用 Selenium)写一个功能测试,然后介绍 Django 的基础

知识,包括模型、视图和模板。在每个阶段,我们都会编写严格

的单元测试。除此之外,我还会向你引荐测试山羊。● 第二部分(第7~14章):Web 开发要素

介绍 Web 开发过程中一些棘手但不可避免的问题,并展示如何

通过测试解决这些问题,包括静态文件、部署到生产环境、表单

数据验证、数据库迁移和令人畏惧的 JavaScript。● 第三部分(第15~20章):高级话题

介绍模拟技术、集成第三方认证系统、Ajax、测试固件、由外而

内的 TDD 流程,以及持续集成(Continuous Integration,CI)。

下面说明一些杂务。排版约定

本书使用了下列排版约定。● 楷体

表示新术语或强调的内容。● 等宽字体(Constant width)

表示程序片段,以及正文中出现的变量、函数名、数据库、数据

类型、环境变量、语句和关键字等。● 加粗等宽字体(Constant width bold)

表示应该由用户输入的命令或其他文本。

偶尔使用 [...] 符号表示省略了一些内容,截断较长的输出,或者跳到相关的内容。 该图标表示提示或建议。 该图标表示提示、建议或一般注记。 该图标表示警告或警示。使用代码示例

代码示例可到 https://github.com/hjwp/book-example/ 下载,各章的代码都放在单独的分支中(例如,https://github.com/hjwp/book-example/tree/chapter_03)。每一章的结尾都有一些建议,告诉你如何使用这个仓库。

本书是要帮你完成工作的。一般来说,如果本书提供了示例代码,你可以把它用在你的程序或文档中。除非你使用了很大一部分代码,否则无需联系我们获得许可。比如,用本书的几个代码片段写一个程序就无需获得许可,销售或分发 O'Reilly 图书的示例光盘则需要获得许可;引用本书中的示例代码回答问题无需获得许可,将书中大量的代码放到你的产品文档中则需要获得许可。

我们很希望但并不强制要求你在引用本书内容时加上引用说明。引用说明一般包括书名、作者、出版社和 ISBN。比如:“Test-Driven Development with Python by Harry Percival (O'Reilly). Copyright 2014 Harry Percival, 978-1-449-36482-3.”

如果你觉得自己对示例代码的用法超出了上述许可的范围,欢迎你通过 permissions@oreilly.com 与我们联系。®Safari Books Online

Safari Books Online(http://www.safaribooksonline.com)是应运而生的数字图书馆。它同时以图书和视频的形式出版世界顶级技术和商务作家的专业作品。技术专家、软件开发人员、Web 设计师、商务人士和创意专家等,在开展调研、解决问题、学习和认证培训时,都将 Safari Books Online 视作获取资料的首选渠道。

对于组织团体、政府机构和个人,Safari Books Online 提供各种产品组合和灵活的定价策略。用户可通过一个功能完备的数据库检索系统访问 O'Reilly Media、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett、Course Technology 以及其他几十家出版社的上千种图书、培训视频和正式出版之前的书稿。要了解 Safari Books Online 的更多信息,我们网上见。联系我们

请把对本书的评价和问题发给出版社。

美国:

  O'Reilly Media, Inc.

  1005 Gravenstein Highway North

  Sebastopol, CA 95472

中国:

  北京市西城区西直门南大街2号成铭大厦 C 座807室(100035)

  奥莱利技术咨询(北京)有限公司

O'Reilly 的每一本书都有专属网页,你可以在那儿找到本书的相关信息,包括勘误表、示例代码以及其他信息。本书的网站地址是:

 http://shop.oreilly.com/product/0636920029533.do

对于本书的评论和技术性问题,请发送电子邮件到:bookquestions@oreilly.com。

要了解更多 O'Reilly 图书、培训课程、会议和新闻的信息,请访问以下网站:

 http://www.oreilly.com

我们在 Facebook 的地址如下:http://facebook.com/oreilly

请关注我们的 Twitter 动态:http://twitter.com/oreillymedia

我们的 YouTube 视频地址如下:http://www.youtube.com/oreillymedia准备工作和应具备的知识

我假设读者具备了如下的知识,电脑中还应该安装一些软件。了解Python 3,会编程

写这本书时,我考虑到了初学者。但如果你刚接触编程,我假设你已经学习了 Python 基础知识。如果还没学,请阅读一份 Python 初学者教程,或者买一本入门书,比如 Dive Into Python(http://www.diveintopython.net/)或 Learn Python the Hard Way(http://learnpythonthehardway.org/),或者出于兴趣,看一下 Invent Your Own Computer Games with Python(http://inventwithpython.com/)。这三本都是很好的入门书。

如果你是经验丰富的程序员,但刚接触 Python,阅读本书应该没问题。Python 简单易懂。

本书中我用的是 Python 3。我在2013~2014年写这本书时,Python 3已经发布好几年了,全世界的开发者正处在一个拐点上,他们更倾向于选择使用 Python 3。可以参照本书内容在 Mac、Windows 和 Linux 中实践。在各种操作系统中安装 Python 的详细说明后文会介绍。 本书内容在 Python 3.3和 Python 3.4中测试过。如果出于某些原因,你使用的是 Python 3.2,可能会发现细微的差别,所以如果可以,最好升级 Python。

我不建议使用 Python 2,因为它和 Python 3之间的区别太大。如果碰巧你的下一个项目使用的是 Python 2,仍然可以运用从本书中学到的知识。不过,当你得到的程序输出和本书不一样时,要花时间判断是因为用了 Python 2,还是因为你确实犯了错——这么做太浪费时间了。

如果你想使用 PythonAnywhere(https://www.pythonanywhere.com/,这是我就职的 PaaS 创业公司),不愿在本地安装 Python,可以先快速阅读一遍附录 A。

无论如何,我希望你能使用 Python,知道如何从命令行启动 Python(一般使用 python3 命令),也知道如何编辑和运行 Python 文件。再次提醒,如果你有任何疑问,看一下我在前面推荐的三本书。 如果你已经安装了 Python 2,担心再安装 Python 3会破坏之前的版本,那大可以放心,Python 3和 Python 2可以相安无事地共存于同一个系统中,而且这两个版本存储代码包的位置完全不一样。你只需确保有一个启动 Python 3的命令(python3),还有一个启动 Python 2的命令(通常就是 python)。类似地,在 Python 3中安装 pip 时,我们要保证它的命令(通常是 pip3)和 Python 2的不一样。HTML的工作方式

我还假定你基本了解 Web 的工作方式,知道什么是 HTML、什么是 POST 请求等。如果你对这些概念不熟悉,那么需要找一份 HTML 基础教程看一下,http://www.webplatform.org/ 上列出了一些。如果你知道如何在电脑中创建 HTML 页面,并在浏览器中查看,也知道表单以及它的工作方式,那么或许你就符合我的要求。JavaScript

本书后半部分有少量 JavaScript。如果你不了解 JavaScript,先别担心。如果你觉得有些看不懂,到时我会推荐一些参考资料给你。需要安装的软件

除了 Python 之外,还要安装以下软件。● Firefox Web 浏览器

在谷歌中搜索一下就能找到适合你所用平台的安装程序。

Selenium 其实能驱动任意一款主流浏览器,不过以 Firefox 举例

最简单,因为它跨平台。而且使用 Firefox 还有另外一个好处

——和公司利益没有多少关联。● Git 版本控制系统

Git 可在任何一个平台上使用,下载地址是 http://git-scm.com/。● Python 包管理工具 pip

Python 3.4集成了 pip(之前的版本都没集成,这是一大进步)。

为确保使用 Python 3中的 pip,我总是会在命令行中使用可执行

文件 pip3。在你使用的系统中,这个可执行文件可能是 pip-3.4

或者 pip-3.3。更多信息请阅读针对各种操作系统的详细说明。针对 Windows 的说明Windows 用户有时会觉得被忽略了,因为 OS X 和 Linux 的存在很容易让人忘记在 Unix 之外还有一个世界。使用反斜线作为目录分隔符?盘符?这些是什么?不过,阅读本书时仍然可以在 Windows 中实践。下面是一些小提示。1. 在 Windows 中安装 Git 时,一定要选择“Run Git and included Unix tools from the Windows command prompt”(在 Windows 命令提示符中运行 Git 和所含的 Unix 工具)。选择这个选项之后就能使用 Git Bash 了。把 Git Bash 作为主要命令提示符,你就能使用所有实用的 GNU 命令行工具,例如 ls、touch 和 grep,而且目录分隔符也使用斜线表示。2. 安装 Python 3时,一定要选中“Add python.exe to Path”(把 python.exe 添加到系统路径中),这么做才能在命令行中运行 Python。如图 P-1所示。图 P-1:从安装程序将 Python 加入系统路径3. 在 Windows 中,Python 3的可执行文件是 python.exe,和 Python 2的完全一样。为了避免混淆,请在 Git Bash 的二进制文件夹中创建一个符号链接,方法如下:ln -s /c/Python34/python.exe /bin/python3.exe你可能需要在 Git-Bash 上点击右键,选择“以管理员身份运行”,这么做上述命令才能生效。还要注意,这个符号链接只在 Git Bash 中有效,在常规的 DOS 命令提示符中不可用。4. Python 3.4集成了包管理工具 pip。你可以在命令行中执行 which pip3 查看是否安装了 pip,这个命令应该返回 /c/Python34/Scripts/pip3。如果出于某种原因,在 Python 3.3中遇到了问题,或者没有安装 pip3,请访问 http://www.pip-installer.org/,查看安装说明。写作本书时,安装 pip3 的方法是,下载一个文件,然后执行 python3 get-pip.py 命令。运行安装脚本时,确保使用的是 python3。 测试所有软件是否正确安装的方法是,打开 Git Bash 命令提示符,在任意一个文件夹中执行命令 python3 或 pip3。

 针对 MacOS 的说明MacOS 比 Windows 稍微正常一点儿,不过在 Python 3.4之前,安装 pip3 还是一项极具挑战性的任务。Python 3.4发布后,安装方法变得简单明了。● 使用下载的安装程序(https://www.python.org/)就能安装 Python 3.4,省去了很多麻烦。而且,这个安装程序也会自动安装 pip。● Git 安装程序也能顺利运行。测试这些软件是否正常安装的方法和 Windows 类似:打开一个终端,然后在任意位置执行命令 git、python3 或 pip3。如果遇到问题,搜索关键字“system path”和“command not found”,就能找到解决问题的合适资源。 或许你还应该检验一下 Homebrew(http://brew.sh//)。在 Mac 安装众多 Unix 工具的方式中,它是唯一可信赖的。虽然现在 Python 安装程序做得不错,但将来你可能会用到 Homebrew。要使用 Homebrew,需下载大小为1.1 GB 的 Xcode。不过这有个好处——你得到了一个 C 编译器。Git默认使用的编辑器和其他基本配置

后文我会逐步介绍如何使用 Git,不过现在最好做些配置。例如,首次提交时,默认情况下会弹出 vi,这可能让你手足无措。鉴于 vi 有两种模式,你有两个选择。其一,学一些基本的 vi 命令(按 i 键进入插入模式,输入文本后再按 键返回常规模式,然后输入 :wq 写入文件并退出)。学会这些命令后,你就加入了一个互助会,这里的人们知道怎么使用这个古老而让人崇敬的文本编辑器。

另外一个选择是直接拒绝这种穿越到20世纪70年代的荒唐行为,而是配置 Git,让它使用你选择的编辑器。按 键,再输入 :q!,退出 vi,然后修改 Git 使用的默认编辑器。具体方法参见介绍 Git 基本配置的文档,网址是 http://git-scm.com/book/zh/Customizing-Git-Git-Configuration。需要安装的Python模块

安装好 pip 之后,再安装新的 Python 模块就简单了。接下来,我们会陆续安装一些模块,但有几个模块一开始就需要,所以现在就应该安装。● Django 1.7,sudo pip3 install django==1.7(在 Windows 中不需

要 sudo)。这是我们要使用的 Web 框架。要保证你安装的是1.7

版,而且能在命令行中使用可执行文件 django-admin.py。如果

需要帮助,可以查看 Django 的文档,其中有安装说明,网址是

https://docs.djangoproject.com/en/1.7/intro/install/。1 截至2014年5月,Django 1.7还在测试阶段 。如果上述命令无效,请执行 sudo pip3 install https://github.com/django/django/archive/stable/1.7.x.zip。● Selenium,sudo pip3 install --upgrade selenium(在 Windows 中

不需要 sudo)。Selenium 是浏览器自动化工具,我们要用它来

驱动功能测试。确保你安装的是最新版。Selenium 一直紧跟主

流浏览器的更新步伐,尝试使用最新功能。如果你发现

Selenium 由于某些原因表现异常,通常都是因为 Firefox 的版本

太新,此时你应该升级到最新版的 Selenium。 除非确切知道你在做什么,否则不要使用 virtualenv。从第8章开始才会用到 virtualenv。1Django 1.7于2014年9月2日正式发布,此时本书中文版正在翻译中。——译者注关于 IDE如果你来自 Java 或 .NET 领域,可能非常想使用 IDE(集成开发环境)编写 Python 代码。IDE 中有各种实用的工具,例如 VCS 集成。Python 领域也有一些很棒的 IDE。刚开始我也用过一个 IDE,我发现它对我最初的几个项目很有用。我能建议(只是建议)你别用 IDE 吗?至少在阅读本书时别用。在 Python 领域,IDE 不是那么重要。写作这本书时,我假定你只使用一个简单的文本编辑器和命令行。某些时候,它们是你所能使用的全部工具(例如在服务器中),所以刚开始时值得花时间学习使用基本的工具,理解它们是如何工作的。即便当你读完本书后决定继续使用 IDE 和其中的实用工具,这些基本的工具还是随手可得。

  上述说明对你没什么用吗?或者你有更好的说明?请给我发电子邮件吧,地址是 obeythetestinggoat@gmail.com。致谢

要感谢的人很多,没有他们就不会有这本书,就算有也会写得比现在差。

首先感谢某出版社的 Greg,他是第一个鼓励我、让我相信我能写完这本书的人。虽然你们公司在版权问题上思想过于退化,但我还是要感激你个人对我的信任。

感谢 Michael Foord,他以前也是 Resolver Systems 的员工。我写书的最初灵感便来自于他,因为他自己也写了一本书。感谢他一直支持这个项目。感谢我的老板 Giles Thomas,他傻傻地允许他的另一位员工也去写书(不过,我觉得他现在已经修改了标准的雇佣合同,加上了“禁止写书”的条款)。同样也感谢你不断增长的智慧,把我带入了测试领域。

感谢我的另外两位同事,Glenn Jones 和 Hansel Dunlop。你们总是给我提供非常宝贵的意见,而且在过去一年中耐心地陪我录制单轨对话。

感谢我的妻子 Clementine 和家人,没有他们的支持和耐心,我绝对无法写完这本书。很多时间本该和家人在一起难忘地度过,我却把它们都花在了电脑上,为此我感到抱歉。开始写作时,我不知道这本书会对我的生活产生什么影响(“在闲暇时间写怎么样?听起来可行……”)。没有你们的支持,我写不完这本书。

感谢技术审校人员,Jonathan Hartley、Nicholas Tollervey 和 Emily Bache。感谢你们的鼓励和珍贵的反馈。尤其是 Emily,她认真阅读了每一章。感谢 Nick 和 Jon,由衷感谢。感谢你们在我身旁,让写作的过程变得不那么孤单。没有你们,这本书的内容会像傻瓜一样废话连篇。

感谢每个放弃自己的时间把意见反馈给我的人,感谢你们的热心肠:Gary Bernhardt、Mark Lavin、Matt O'Donnell、Michael Foord、Hynek Schlawack、Russell Keith-Magee、Andrew Godwin 和 Kenneth Reitz。你们比我聪慧得多,让我避免说一些愚蠢的事情。当然,书中还有很多愚蠢的内容,不过责任肯定不在你们。

感谢我的编辑 Meghan Blanchette,她是一位非常友善可爱的监工。谢谢你为我规划时间,制止我愚蠢的想法,让本书的写作在正确的轨道上行进。感谢 O'Reilly 出版社其他所有为我提供帮助的人,包括 Sarah Schneider、Kara Ebrahim 和 Dan Fauxsmith,感谢你们让我继续使用英式英语。感谢 Charles Roumeliotis 在行文风格和语法上给我的帮助。虽然我们对芝加哥学派引用和标点符号规则的优势有不同观点,但有你在身边我仍然高兴。感谢设计部门为封面绘制了一头山羊。

特别感谢预览版的读者,感谢你们挑出拼写错误,给我反馈和建议,感谢你们提出各种有助于使本书学习曲线变平滑的方法,感谢你们中的大多数人给我鼓励和支持,让我一直写下去。感谢 Jason Wirth、Dave Pawson、Jeff Orr、Kevin De Baere、crainbf、dsisson、Galeran、Michael Allan、James O'Donnell、Marek Turnovec、Sooner Bourne、julz、Cody Farmer、William Vincent、Trey Hunner、David Souther、Tom Perkin、Sorcha Bowler、Jon Poler、Charles Quast、Siddhartha Naithani、Steve Young、Roger Camargo、Wesley Hansen、Johansen Christian Vermeer、Ian Laurain、Sean Robertson、Hari Jayaram、Bayard Randel、Konrad Kor el、Matthew Waller、Julian Harley、Barry McClendon、Simon Jakobi、Angelo Cordon、Jyrki Kajala、Manish Jain、Mahadevan Sreenivasan、Konrad Kor el、Deric Crago、Cosmo Smith、Markus Kemmerling、Andrea Costantini、Daniel Patrick、Ryan Allen、Jason Selby、Greg Vaughan、Jonathan Sundqvist、Richard Bailey、Diane Soini、Dale Stewart、Mark Keaton、Johan Wärlander、Simon Scarfe、Eric Grannan、Marc-Anthony Taylor、Maria McKinley 和 John McKenna 等很多人。如果我遗漏了谁的名字,你绝对有权感到委屈。我当然非常感激你,请给我写封信,我会尽我所能把你的名字加上。

最后,我要感谢你,现在的读者,感谢你决定阅读这本书,希望你喜欢。▶▶第一部分TDD 和 Django 基础

第一部分我要介绍测试驱动开发(Test-Driven Development,TDD)的基础知识。我们会从零开始开发一个真实的 Web 应用,而且每个阶段都要先写测试。

这一部分涵盖使用 Selenium 完成的功能测试,以及单元测试,还会介绍二者之间的区别。我会介绍 TDD 流程,我称之为“单元测试 / 编写代码”循环。我们还要做些重构,说明怎么结合 TDD 使用。因为版本控制对重要的软件工程来说是基本需求,所以我们还会用到版本控制系统(Git)。我会介绍何时以及如何提交,如何把提交集成到 TDD 和 Web 开发的流程中。

我们要使用 Django,它(或许)是 Python 领域之中最受欢迎的 Web 框架。我会试着慢慢介绍 Django 的概念,一次一个,除此之外还会提供很多扩展阅读资料的链接。如果你完全是刚接触 Django,那么我极力推荐你花时间阅读这些资料。如果你感觉有点儿茫然,花几小时读一遍 Django 的官方教程,然后再回来阅读本书。

你还会结识测试山羊…… 复制粘贴时要小心如果你看的是电子版,那么在阅读的过程之中就会很自然地会想要复制粘贴书中的代码清单。如果不这么做的话效果会更好:动手输入能形成肌肉记忆,感觉也更真实。你偶尔会打错字,这是无法避免的,调试错误也是一项需要学习的重要技能。除此之外,你还会发现 PDF 格式相当诡异,复制粘贴时经常会有意想不到的事情发生……第1章 使用功能测试协助安装 Django

TDD 不是天生就会的技术,和武术一样是一种技能。而且就像在功夫电影中一样,你需要一个脾气不好、不可理喻的师傅来强制你学习。我们的师傅是测试山羊。1.1 遵从测试山羊的教诲,没有测试什么也别做

在 Python 测试社区中,测试山羊是 TDD 的非官方吉祥物。测试山羊对不同的人有不同的意义。对我来说,它是我脑海中的一个声音,告诉我要一直走在测试这条正确的道路上,就像卡通片中在肩膀上浮现的天使或魔鬼一样,只是没那么咄咄逼人。我希望借由这本书,让测试山羊也扎根于你的脑海中。

虽然还不太确定要做什么,但我们已经决定要开发一个网站。Web 开发的第一步通常是安装和配置 Web 框架。下载这个,安装那个,配置那个,运行这个脚本……但是,使用 TDD 时要转换思维方式。做测试驱动开发时,你的心里要一直记着测试山羊,像山羊一样专注,咩咩地叫着:“先测试,先测试!”

在 TDD 的过程中,第一步始终一样:编写测试。

首先要编写测试,然后运行,看是否和预期一样失败,只有失败了才能继续下一步——编写应用程序。请模仿山羊的声调复述这个过程。我就是这么做的。

山羊的另一个特点是一次只迈一步。因此,不管山壁多么陡峭,它们都不会跌落。看看图1-1里的这只山羊!

图1-1:山羊比你想象的要机敏(来源:Flickr 用户 Caitlin Stewart,http://www.flickr.com/photos/caitlinstewart/2846642630/)

我们会碎步向前。使用流行的 Python Web 框架 Django 开发这个应用。

首先,要检查是否安装了 Django,并且能够正常运行。检查的方法是,在本地电脑中能否启动 Django 的开发服务器,并在浏览器中查看能否打开网页。使用浏览器自动化工具 Selenium 完成这个任务。

在你想保存项目代码的地方新建一个 Python 文件,命名为 functional_tests.py,并输入以下代码。如果你喜欢一边输入代码一边像山羊那样轻声念叨,或许会有所帮助:from selenium import webdriverbrowser = webdriver.Firefox()browser.get('http://localhost:8000')assert 'Django' in browser.title别了,罗马数字很多介绍 TDD 的文章都喜欢以罗马数字为例,闹了笑话,甚至我一开始也是这么写的。如果你好奇,可以查看我在 GitHub 的页面,地址是 https://github.com/hjwp/。以罗马数字为例有好也有坏。把问题简化,合理地限制在某一范围内,让你能很好地解说 TDD。但问题是不切实际。因此我才决定要从零开始开发一个真实的 Web 应用,以此为例介绍 TDD。这是一个简单的 Web 应用,我希望你能把从中学到的知识运用到下一个真实的项目中。

这是我们编写的第一个功能测试(Functional Test,FT)。后面我会深入说明什么是功能测试,以及它和单元测试的区别。现在,只要能理解这段代码做了什么就行:● 启动一个 Selenium webdriver,打开一个真正的 Firefox 浏览器窗

口;● 在这个浏览器中打开我们期望本地电脑伺服的网页;● 检查(做一个测试断言)这个网页的标题中是否包含单词“Django”。

我们尝试运行一下:$ python3 functional_tests.pyTraceback (most recent call last): File "functional_tests.py", line 6, in assert 'Django' in browser.titleAssertionError

你应该会看到弹出了一个浏览器窗口,尝试打开 localhost:8000,然后会看到上述 Python 错误消息。接着,会看到 Firefox 窗口停留在桌面上,等待你关闭。这可能会让你生气,我们稍后会修正这个问题。 如果看到关于导入 Selenium 的错误,或许你应该往前翻,看一下“准备工作和应具备的知识”。

现在,得到了一个失败测试。这意味着,我们可以开始开发应用了。1.2 让Django运行起来

你肯定已经读过“准备工作和应具备的知识”了,也安装了 Django。使用 Django 的第一步是创建项目,我们的网站就放在这个项目中。Django 为此提供了一个命令行工具:$ django-admin.py startproject superlists

这个命令会创建一个名为 superlists 的文件夹,并在其中创建一些文件和子文件夹:.├─ functional_tests.py└─ superlists ├─ manage.py └─ superlists ├─ __init__.py ├─ settings.py ├─ urls.py └─ wsgi.py

在 superlists 文件夹中还有一个名为 superlists 的文件夹。这有点让人困惑,不过确实需要如此。回顾 Django 的历史,你会找到出现这种结构的原因。现在,重要的是知道 superlists/superlists 文件夹的作用是保存应用于整个项目的文件,例如 settings.py 的作用是存储网站的全局配置信息。

你还会注意到 manage.py。这个文件是 Django 的瑞士军刀,作用之一是运行开发服务器。我们来试一下。执行命令 cd superlists,进入顶层文件夹 superlists(我们会经常在这个文件夹中工作),然后执行:$ python3 manage.py runserverValidating models...0 errors foundDjango version 1.7, using settings 'superlists.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.

让这个命令一直运行着,再打开一个命令行窗口,在其中再次尝试运行测试(进入刚刚打开的文件夹):$ python3 functional_tests.py$

我们在命令行中没执行多少操作,但你应该注意两件事:第一,没有丑陋的 AssertionError 了;第二,Selenium 弹出的 Firefox 窗口中显示的页面不一样了。

这虽然看起来没什么大不了,但毕竟是我们第一个通过的测试啊!值得庆祝。

如果感觉有点神奇,不太现实,为什么不手动查看开发服务器,打开浏览器访问 http://localhost:8000呢?你会看到如图1-2所示的页面。

图1-2:Django 可用了

如果想退出开发服务器,可以回到第一个 shell 中,按 Ctrl-C 键。1.3 创建Git仓库

结束这章之前,还要做一件事:把作品提交到版本控制系统(Version Control System,VCS)。如果你是一名经验丰富的程序员,就无需再听我宣讲版本控制了。如果你刚接触 VCS,请相信我,它是必备工具。当项目在几周内无法完成,代码越来越多时,你需要一个工具查看旧版代码、撤销改动、放心地试验新想法,或者只是做个备份。测试驱动开发和版本控制关系紧密,所以我一定要告诉你如何在开发流程中使用版本控制系统。

好的,来做第一次提交。如果现在提交已经晚了,我表示歉意。我们使用 Git 作为 VCS,因为它是最棒的。

我们先把 functional_tests.py 移到 superlists 文件夹中。然后执行 git init 命令,创建仓库:$ lssuperlists functional_tests.py$ mv functional_tests.py superlists/$ cd superlists$ git init .Initialised empty Git repository in /workspace/superlists/.git/ 从此往后,我们会把顶层文件夹 superlists 作为工作目录。我提供的输入命令,都假定在这个目录中执行。类似地,如果我提到一个文件的路径,也是相对于这个顶层目录而言。因此,superlists/settings.py 是指次级文件夹 superlists 中的 settings.py。理解了吗?如果有怀疑,就查找 manage.py,你要和这个文件在同一个目录中。

现在,添加想提交的文件——其实所有文件都要提交:$ lsdb.sqlite3 manage.py superlists functional_tests.py

db.sqlite3 是数据库文件。不想把这个文件纳入版本控制,因此要将其添加到一个特殊的文件 .gitignore 中,告诉 Git 将其忽略:$ echo "db.sqlite3" >> .gitignore

接下来,我们可以添加当前文件夹(“.”)中的其他内容了:$ git add .$ git statusOn branch masterInitial commitChanges to be committed: (use "git rm --cached ..." to unstage) new file: .gitignore new file: functional_tests.py new file: manage.py new file: superlists/__init__.py new file: superlists/__pycache__/__init__.cpython-34.pyc new file: superlists/__pycache__/settings.cpython-34.pyc new file: superlists/__pycache__/urls.cpython-34.pyc new file: superlists/__pycache__/wsgi.cpython-34.pyc new file: superlists/settings.py new file: superlists/urls.py new file: superlists/wsgi.py

糟糕,添加了很多 .pyc 文件,这些文件没必要提交。将其从 Git 中删掉,并添加到 .gitignore 中:$ git rm -r --cached superlists/__pycache__rm 'superlists/__pycache__/__init__.cpython-34.pyc'rm 'superlists/__pycache__/settings.cpython-34.pyc'rm 'superlists/__pycache__/urls.cpython-34.pyc'rm 'superlists/__pycache__/wsgi.cpython-34.pyc'$ echo "__pycache__" >> .gitignore$ echo "*.pyc" >> .gitignore

现在,来看一下进展到哪里了(你会看到,我使用 git status 的次数太多了,所以经常会使用别名 git st。我不会告诉你怎么做,你要自己探索 Git 别名的秘密!):$ git statusOn branch masterInitial commitChanges to be committed: (use "git rm --cached ..." to unstage) new file: .gitignore new file: functional_tests.py new file: manage.py new file: superlists/__init__.py new file: superlists/settings.py new file: superlists/urls.py new file: superlists/wsgi.py

看起来不错,可以做第一次提交了:$ git commit

输入 git commit 后,会弹出一个编辑器窗口,让你输入提交消息。1我写的消息如图1-3所示。1是不是 vi 弹出后你不知道该做什么?或者,你是不是看到了一个消息,内容是关于账户识别的,其中还显示了 git config --global user.username ?再次看一下“准备工作和应具备的知识”,里面有一些简单说明。

图1-3:首次 Git 提交

如果你迫切想完成整个 Git 操作,此时还要学习如何把代码推送到云端的 VCS 托管服务中,例如 GitHub 或 BitBucket。如果阅读本书的过程中使用不同的电脑,你会发现这么做很有用。具体的操作留给你去发掘,GitHub 和 BitBucket 的文档写得都很好。要不,你可以等到第8章,到时我们会使用其中一个服务做部署。

对 VCS 的介绍结束。祝贺你!你使用 Selenium 编写了一个功能测试,安装了 Django,并且使用 TDD 方式,以测试山羊赞许的、先写测试这种有保障的方式运行了 Django。在继续阅读第2章之前,先表扬一下自己吧,这是你应得的奖励。第2章 使用 unittest 模块扩展功能测试

测试目前检查的是 Django 默认的“可用了”页面,修改一下,让其检查我们想在真实的网站首页中看到的内容。

是时候公布我们要开发什么类型的 Web 应用了——一个待办事项清单网站。开发这种网站说明我们始终追随时尚:很多年前所有的 Web 开发教程都介绍如何开发博客,后来一窝蜂地又介绍论坛和投票应用,现在时兴的是待办事项清单。

不过待办事项清单是个很好的例子。很明显,这种应用简单,只显示一个由文本字符串组成的列表,因此很容易得到一个最简可用的应用。而且可以使用各种方式扩展功能,例如使用不同的持久模型、添加最后期限、提醒和分享功能,还可以改进客户端 UI。另外,不必只局限于列出待办事项,这种应用可以列出任何事项。最重要的一点是,通过这种应用,可以演示 Web 开发过程中的所有主要步骤,以及如何在各个步骤中运用 TDD 理念。2.1 使用功能测试驱动开发一个最简可用的应用

使用 Selenium 实现的测试可以驱动真正的网页浏览器,让我们能从用户的角度查看应用是如何运作的。因此,我们把这类测试叫作“功能测试”。

这意味着,功能测试在某种程度上可以作为应用的说明书。功能测试的作用是跟踪“用户故事”(User Story),模拟用户使用某个功能的过程,以及应用应该如何响应用户的操作。术语:功能测试 = 验收测试 = 端到端测试我所说的功能测试,有些人喜欢称之为验收测试(Acceptance Test)或端到端测试(End-to-End Test)。这类测试最重要的作用是从外部观察整个应用是如何运作的。另一个术语是黑箱测试(Black Box Test),因为这种测试对所要测试的系统内部一无所知。

功能测试应该有一个人类可读、容易理解的故事。为了叙事清楚,可以把测试代码和代码注释结合起来使用。编写新功能测试时,可以先写注释,勾勒出用户故事的重点。这样写出的测试人类可读,甚至可以作为一种讨论应用需求和功能的方式分享给非程序员看。

TDD 常与敏捷软件开发方法结合在一起使用,我们经常提到的一个概念是“最简可用的应用”,即我们能开发出来的最简单的而且可以使用的应用。下面我们就来开发一个最简可用的应用,尽早试水。

最简可用的待办事项清单其实只要能让用户输入一些待办事项,并且用户下次访问应用时这些事项还在即可。

打开 functional_tests.py,编写一个类似下面的故事:functional_tests.pyfrom selenium import webdriverbrowser = webdriver.Firefox()# 伊迪丝听说有一个很酷的在线待办事项应用# 她去看了这个应用的首页browser.get('http://localhost:8000')# 她注意到网页的标题和头部都包含“To-Do”这个词assert 'To-Do' in browser.title# 应用邀请她输入一个待办事项# 她在一个文本框中输入了“Buy peacock feathers”(购买孔雀羽毛)# 伊迪丝的爱好是使用假蝇做饵钓鱼# 她按回车键后,页面更新了# 待办事项表格中显示了“1: Buy peacock feathers”# 页面中又显示了一个文本框,可以输入其他的待办事项# 她输入了“Use peacock feathers to make a fly”(使用孔雀羽毛做假蝇)# 伊迪丝做事很有条理# 页面再次更新,她的清单中显示了这两个待办事项# 伊迪丝想知道这个网站是否会记住她的清单# 她看到网站为她生成了一个唯一的URL# 而且页面中有一些文字解说这个功能# 她访问那个URL,发现她的待办事项列表还在# 她很满意,去睡觉了browser.quit()我们有个词来形容注释我开始在 Resolver 工作时,出于善意习惯在代码中加入密密麻麻的详细注释。我的同事告诉我:“哈利,我们有个词来形容注释,我们把注释叫作谎言。”我很诧异:可我在学校学到的是,注释是好的习惯啊?他们说得夸张了。注释有其作用,可以添加上下文,说明代码的目的。他们的意思是,简单重复代码意图的注释毫无意义,例如:# 把wibble的值增加1wibble += 1这样的注释不仅毫无意义,还有一定危险,如果更新代码后没有修改注释,会误导别人。我们要努力做到让代码可读,使用有意义的变量名和函数名,保持代码结构清晰,这样就不再需要通过注释说明代码做了什么,只要偶尔写一些注释说明为什么这么做。有些情况下注释很重要。后文会看到,Django 在其生成的文件中用到了很多注释,这是解说 API 的一种方式。而且还在功能测试中使用注释描述用户故事——把测试提炼成一个连贯的故事,确保我们始终从用户的角度测试。这个领域中还有很多有趣的知识,例如行为驱动开发(Behaviour Driven Development)和测试 DSL(Domain Specific Language,领域特定语言)。这些知识已经超出本书的范畴了。

你可能已经发现了,除了在测试中加入注释之外,我还修改了 assert 这行代码,让其查找单词“To-Do”,而不是“Django”。这意

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载