Test-Driven Development Principles
TDD consists of writing test cases that cover a desired feature, then writing the feature itself. In other words, the usage examples are written before the code even exists.
For example, a developer who is asked to write a function that provides the average value of a sequence of numbers will first write a few examples on how to use it, and
the expected results:
assert average(1, 2, 3) == 2
assert average(1, -3) == -1
These examples can be provided by another person as well. From there, the function can be implemented until the two examples work:
>>> def average(*numbers):
...    return sum(numbers) / len(numbers)
...
>>> assert average(1, 2, 3) == 2
>>> assert average(1, -3) == -1
A bug or an unexpected result is a new example of usage the function should be able to deal with:
>>> assert average(0, 1) == 0.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
The code can be changed accordingly, until the new test passes:
>>> def average(*numbers):
...    # makes sure all numbers can be used as floats
...    numbers = [float(number) for number in numbers]
...    return sum(numbers) / float(len(numbers))
...
>>> assert average(0, 1) == 0.5
And more cases will make the code evolve:
>>> try:
...    average()
...  except TypeError:
...    # we want an empty sequence to throw a type error
...    pass
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 3, in average
ZeroDivisionError: integer division or modulo by zero
>>>
>>> def average(*numbers):
...  if numbers == ():
...  raise TypeError(('You need to provide at '
...  'least one number'))
...  numbers = [float(number) for number in numbers]
...  return sum(numbers) / len(numbers)
...
>>> try:

...  average()
...  except TypeError:
... pass
...
From there all tests can be gathered in a test function, which is run
every time the code evolves:
>>> def test_average():
...  assert average(1, 2, 3) == 2
...  assert average(1, -3) == -1
...  assert average(0, 1) == 0.5
...  try:
...    average()
...  except TypeError:
...    pass
...
>>> test_average()
Every time a change is made, test_average is changed together with average,then run again to make sure all cases still work. The usage is to gather all tests in the tests folder of the current package. Each module can have a corresponding test module there.This approach provides a lot of benefits by:
• Preventing software regression
• Improving code quality
• Providing the best low-level documentation
• Producing robust code faster

Preventing Software Regression
We all face software regression issues in our developer lives. Software regression is a new bug introduced by a change. Regressions happen because of the simple fact that it is impossible at some point to guess what a single change in a codebase might lead to. Changing some code might break some other features, and sometimes lead to vicious side effects, such as silently corrupting data.
To avoid regression, the whole set of features software provides should be tested every time a change occurs.
Opening a codebase to several developers amplifies the problem, since each person will not be fully aware of all development activities. While having a version control system prevents conflicts, it does not prevent all unwanted interactions.
TDD helps reduce software regression. The whole software can be automatically tested after each change. This will work as long as each feature has the proper set of
tests. When TDD is properly done, the test base grows together with the codebase. Since a full test campaign can last for quite a long time, it is a good practice to delegate it to a buildbot, which can do the work in the background (this is described in Chapter 8). But local re-launching of the tests should be done manually by the user, at least for the concerned modules.
Improving Code Quality
When a new module, class, or a function is written, a developer focuses on how to write it and how to produce the best piece of code he or she can. But while he or she
is concentrating on algorithms, he or she might lose the user's point of view: How and when will his or her function be used? Are the arguments easy and logical to use? Is the name of the API right?
This is done by applying the tips described in the previous chapters, such as Choosing Good Names. But the only way to do it efficiently is to write usage examples. This is when the developer realizes if the code he or she wrote is logical and easy to use. Often, the first refactoring occurs right after the module, class, or function is finished.
Writing tests, which are use cases for the code, helps in having this user point of view. Developers will, therefore, often produce a better code when they use TDD.  It is difficult to test gigantic functions that both calculate things as well as have side effects. Code that is written with testing in mind tends to be architected more cleanly
and modularly.
Providing the Best Developer Documentation
Tests are the best place for a developer to learn how software works. They are the use cases the code was primarily created for. Reading them provides a quick and deep
insight into how the code works. Sometimes, an example is worth a thousand words. The fact that these tests are always up to date with the codebase makes them the best
developer documentation a piece of software can have. Tests don't go stale in the same way documentation does, otherwise they would fail.
Producing Robust Code Faster
Writing without tests leads to extensive debugging sessions. A bug in one part of the software might be felt in a distant part of that software. Since you don't know who to
blame, you spend an inordinate amount of time debugging. It's better to fight small bugs one at a time when a test fails, because you'll have a better clue as to where the
real problem is. And testing is often more fun that debugging because it is coding.
If you measure the time taken to fix the code together with the time taken to write it, it will usually be longer than the time a TDD approach would take. This is not obvious when you start a new piece of code. This is because the time taken to set up  test environment and write the first few tests is extremely long compared to the time taken just to write the first pieces of code.
But there are some test environments that are really hard to set up. For instance, when your code interacts with an LDAP or an SQL server, writing tests is not obvious at all. This is covered in the Fakes and Mocks section in this chapter.

TDD in Expert Python Programmin的更多相关文章

  1. Expert Python programming - Reading Notes

    1. MRO: method resolution order lookup order: L(MyClass) = [MyClass, merged(L(Base1), L(Base2), Base ...

  2. python BDD&TDD

    教程一:行为驱动开发(BDD) 基于Python的行为驱动开发实战: http://python.jobbole.com/81303/ 基于Python的行为驱动开发实战 英语原文地址: http:/ ...

  3. [Python] 学习资料汇总

    Python是一种面向对象的解释性的计算机程序设计语言,也是一种功能强大且完善的通用型语言,已经有十多年的发展历史,成熟且稳定.Python 具有脚本语言中最丰富和强大的类库,足以支持绝大多数日常应用 ...

  4. Python学习资料下载地址(转)

    [转]Python学习资料和教程pdf 开发工具: Python语言集成开发环境 Wingware WingIDE Professional v3.2.12 Python语言集成开发环境 Wingwa ...

  5. [转]Python学习资料和教程pdf

    开发工具: Python语言集成开发环境 Wingware WingIDE Professional v3.2.12 Python语言集成开发环境 Wingware WingIDE Professio ...

  6. 原创翻译-测试驱动开发(TDD)

    测试驱动开发原则 翻译自<<Expert Python Programming>> 测试驱动开发是指首先编写包含所有测试软件特点的测试集,然后再去开发软件.也就是说,在编写软件 ...

  7. 关于Python编程的一些问答

    关于Python编程的一些问答 导语 大约1个月前,oschina.net和华章图书一起合作做了一个活动:OSC第51期高手问答--聊聊python那些事,来推广我参与撰写的书<编写高质量代码: ...

  8. 转:Python语言编程学习资料(电子书+视频教程)下载汇总

    开发工具: Python语言集成开发环境 Wingware WingIDE Professional v3.2.12 Python语言集成开发环境 Wingware WingIDE Professio ...

  9. 关于Python Package下的Module import方式[转]

    2012年有一个目标我没有达成,那就是深入学习和使用Python语言.这个目标被其他学习任务和工作无情的抢占了,当然最主要的原因还是我重视不够^_^. 近期恰逢有一些Python工程的开发工作要做,就 ...

随机推荐

  1. git 使用笔记(二)

    续 2.15 删除文件 $ rm testDel.txt删除掉工作区的testDel.txt文件, 1)这时可以通过git checkout -- testDel.txt从版本库恢复该文件到工作区 2 ...

  2. java多线程(三)——锁机制synchronized(同步语句块)

    用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解 ...

  3. 开源VS扩展CodeMaid介绍

         CodeMaid是一个开源的Visual Studio的扩展插件,用于整理与优化代码等.功能类似于商业软件ReSharper,但它是免费的,并且开放源代码.它能帮助你更容易的理解你的代码,支 ...

  4. java service wrapper 级别为info导致内存剧增直至溢出

    上周,公司某一环境发生java service wrapper内存剧增导致最后被自动killed的情况,经过分析,确定导致java service wrapper(后续简称wrapper)守护进程内存 ...

  5. React入门--------JSX

    React学习网站 React官方英文网站:http://reactjs.cn/react/docs/top-level-api.html React官方中文网站:http://www.css88.c ...

  6. 今天发现新大陆:haml和Emmet

    其实一开始小渣渣我只是想接触一下(css预处理器)sass,可是突然冒出一个haml. 原文是酱紫的. Sass 是采用 Ruby 语言编写的一款 CSS 预处理语言,它诞生于2007年,是最大的成熟 ...

  7. Android项目实战(二):安卓应用程序退出的三种方法

    现在的APP退出的时候都不是让用户点击了“后退键”就退出.防止用户点错了后退键而造成的用户体检不好. 一年前搞的Demo代码不见了,重新写下就当是复习和以后直接拿来用把 目前流行的解决一般分为两种: ...

  8. 【转】IOS开发资源汇总

    转自:http://blog.csdn.net/favormm/article/details/6664970 如何用Facebook graphic api上传视频: http://develope ...

  9. Android网络编程基础

    Android网络编程只TCP通信 TCP 服务器端工作的主要步骤如下.步骤1 调用ServerSocket(int port)创建一个ServerSocket,并绑定到指定端口上.步骤2 调用acc ...

  10. iOS开发之网络编程--2、NSURLSessionDownloadTask文件下载

    本文内容大纲: 1.回顾NSURLSessionTask 2.NSURLSessionDownloadTask大文件之block下载 3.NSURLSessionDownloadTask大文件之代理方 ...