作者:dave@http://krondo.com/tested-poetry/  译者: Cheng Luo

你可以从”第一部分 Twist理论基础“开始阅读;也可以从”Twisted 入门!“浏览索引.

简介

在我们探索Twisted的过程中写了很多代码,但目前我们却忽略了一些重要的东西 —— 测试.你也是会怀疑怎样用像 unittest 这样Python自带的同步框架测试异步代码.答案是你不能.正如我们已经发现的,同步代码和异步代码是不能混合的,至少不容易.

幸运地是,Twisted包含自己的测试框架,叫 trial,它支持测试异步代码(当然你也可以用它测试同步代码).

我们假设你已经熟悉了 unittest 的机理和相似的测试框架,它允许你通过定义类创建测试.这个类通常是一个父类(通常叫”TestCase”)的子类,类中的方法以”test“开头并被视作一个测试.框架负责发现所有的测试,一个接一个地运行它们,并伴有可选项 setUp 和 tearDown 步骤,之后报告结果.

例子

你可以在 tests/test_poetry.py 中找到一些关于测试的例子.为了确保我们所有的例子是自包含的(以便你不用担心PYTHONPAYH设置),我们将所有需要的代码拷贝到测试模块中.当然正常情况,你只需导入需要测试的模块.

这个例子既测试诗歌客户端又测试服务器,通过使用客户端从测试服务器抓取一首诗. 为了提供一个可供测试的诗歌服务器, 我们在测试案例中实现 setUp 方法:

class PoetryTestCase(TestCase):
def setUp(self):
factory = PoetryServerFactory(TEST_POEM)
from twisted.internet import reactor
self.port = reactor.listenTCP(0, factory, interface="127.0.0.1")
self.portnum = self.port.getHost().port 

这个 setUp 方法用一首测试诗建立诗歌服务器,然后监听一个随机开放端口.我们保存了端口号,以便实际测试需要时可以利用.当然测试结束时我们会用 tearDown 清除测试服务器:

def tearDown(self):
port, self.port = self.port, None
return port.stopListening()

这把我们带到了第一个测试, test_client, 用 get_poetry 从测试服务器获取诗歌并且验证这就是我们所期望的诗歌:

def test_client(self):
"""The correct poem is returned by get_poetry."""
d = get_poetry('127.0.0.1', self.portnum) def got_poem(poem):
self.assertEquals(poem, TEST_POEM) d.addCallback(got_poem) return d

注意我们的测试函数返回一个 deferred.在 trial 中,每个测试方法都以回调的方式运行.这意味着 reactor 正在运行并且我们可以以测试的一部分执行异步操作.我们仅仅需要让框架知道测试是异步的,这可以通过采用常规的Twisted方式 —— 返回 deferred 来实现.

trial 框架在调用 tearDown 方法之前将等待直到 deferred 激发,并且当 deferred 失败时将使测试失败(如,最后一个回调/错误回调对失败).如果我们的 deferred 反应太慢(默认2分钟)它同样会使测试失败.这意味着如果测试完成,我们知道 deferred 激发了,因此我们的回调激发了并且运行了 assertEquals 测试方法.

我们的第二个测试, test_failure, 证实 get_poetry 以适当的方式失败了,如果不能连接到服务器:

def test_failure(self):
"""The correct failure is returned by get_poetry when
connecting to a port with no server."""
d = get_poetry('127.0.0.1', -1)
return self.assertFailure(d, ConnectionRefusedError)

这里我们打算连接到一个无效端口,之后使用trial提供的 assertFailure 方法.这个方法类似于熟悉的 assertRaises 方法但是是针对异步代码的.它返回一个 deferred,如果给定的deferred 失败则返回成功,否则返回失败.

你可以用trial脚本自己运行这些测试,如下:

trial tests/test_poetry.py

你将看到显示每个测试案例的输出,OK表示测试通过了.

讨论

由于当谈到基本API时,trial与unittest十分相似,所以开始写测试十分容易.如果你的测试使用异步代码,仅仅返回 deferred 就可以了,trial将负责其余的事情.你也可以从 setUp或 tearDown 方法返回一个 deferred,如果它们也需要异步.

任何来自测试的日志消息将被收集到当前文件夹下的一个文件中,即”_trial_temp”, trial会自动创建它. 除了打印到屏幕的错误,日志是调试失败测试的实用入口.

图33显示了一个正在进行中的假想测试:

图33: 进行中的trial测试

如果你之前使用过类似的框架,这是一个熟悉的模型,除了所有测试相关的方法可能返回 deferreds.

trial框架是一个关于如何”异步运作”的很好例子,包括级联在整个程序中的变化.为了使一个测试(或任何函数,方法)是异步的,它必须:

  1. 非阻塞并且,通常
  2. 返回一个 deferred.

但这意味着无论什么调用,那个函数必须愿意接收一个 deferred,并且非阻塞(如此又好像返回了一个 deferred).如此这般一层又一层.这样就呼唤出现trial一样的框架,可以处理返回 deferreds 的异步测试.

总结

这就是关于单元测试的内容.如果你想了解更多关于如何为Twisted代码写单元测试的例子,你只需要看看Twisted代码本身.Twisted框架自带了一套非常庞大的单元测试,而且每个新的发布又会加入很多.由于这些测试在被接受入代码库之前,经过严格的代码评论以及Twisted专家们的仔细审查,故而它们是告诉你如何以正确方式测试Twisted代码的极好例子.

在 第十六部分 Twisted 进程守护 中,我们将使用Twisted工具将诗歌服务器转化为一个真正的守护进程.

参考练习

  1. 改变测试之一使其失败,然后再次运行 trial 看看输出结果.
  2. 阅读 trial 在线文档.
  3. 为我们这个系列中所创建的其他诗歌服务写测试.
  4. 探索Twisted中的 一些测试.
 

Python Twisted系列教程15:测试诗歌的更多相关文章

  1. Python Twisted系列教程3:初步认识Twisted

    作者:dave@http://krondo.com/our-eye-beams-begin-to-twist/ 译者:杨晓伟(采用意译) 可以从这里从头开始阅读这个系列. 用twisted的方式实现前 ...

  2. Python Twisted系列教程12:改进诗歌下载服务器

    作者:dave@http://krondo.com/a-poetry-transformation-server/  译者:杨晓伟(采用意译) 你可以从这里从头阅读这个系列. 新的服务器实现 这里我们 ...

  3. Python Twisted系列教程11:改进诗歌下载服务器

    作者:dave@http://krondo.com/your-poetry-is-served/ 译者:杨晓伟(采用意译) 你可以从这里从头阅读这个系列. 诗歌下载服务器 到目前为止,我们已经学习了大 ...

  4. Python Twisted系列教程8:使用Deferred的诗歌下载客户端

    作者:dave@http://krondo.com/deferred-poetry/  译者:杨晓伟(采用意译) 可以从这里从头开始阅读这个系列. 客户端4.0 我们已经对deferreds有些理解了 ...

  5. Python Twisted系列教程5:由Twisted支持的诗歌客户端

    作者:dave@http://krondo.com/twistier-poetry/  译者:杨晓伟(采用意译) 你可以从这里从头开始阅读这个系列 抽象地构建客户端 在第四部分中,我们构建了第一个使用 ...

  6. Python Twisted系列教程4:由Twisted支持的诗歌客户端

    作者:dave@http://krondo.com/twisted-poetry/  译者:杨晓伟(采用意译) 你可以在这里从头开始阅读这个系列. 第一个twisted支持的诗歌服务器 尽管Twist ...

  7. Python Twisted系列教程17:造”回调”的另一种方法

    作者:dave@http://krondo.com/just-another-way-to-spell-callback/  译者: Cheng Luo 你可以从”第一部分 Twist理论基础“开始阅 ...

  8. Python Twisted系列教程9:第二个小插曲,Deferred

    作者:dave@http://krondo.com/a-second-interlude-deferred/ 译者:杨晓伟(采用意译) 可以从这里从头来阅读这个系列 更多关于回调的知识 稍微停下来再思 ...

  9. Python Twisted系列教程6:抽象地利用Twisted

    作者:dave@http://krondo.com/and-then-we-took-it-higher/  译者:杨晓伟(采用意译) 你可以从这里从头开始阅读这个系列. 打造可以复用的诗歌下载客户端 ...

随机推荐

  1. python中*和**的打包和解包

    python中的*和**,能够让函数支持任意数量的参数,它们在函数定义和调用中,有着不同的目的 一. 打包参数 * 的作用:在函数定义中,收集所有的位置参数到一个新的元组,并将这个元组赋值给变量arg ...

  2. lightoj1213推公式

    很容易推出来的公式ans=n^(k-1)*k*sum 然后快速幂就好了 #include<map> #include<set> #include<cmath> #i ...

  3. 牛客比赛-Wannafly9-A/B/C

    A-链接:https://www.nowcoder.com/acm/contest/71/A来源:牛客网 给定n个正整数,请找出其中有多少个数x满足:在这n个数中存在数y=kx,其中k为大于1的整数 ...

  4. window.location与window.open()的区别

    "top.location.href"是最外层的页面跳转"window.location.href"."location.href"是本页面 ...

  5. Java 学习笔记(121208)

    Java 修饰符 访问修饰符 修饰符 当前类 同一包内 子孙类 其他包 public Y Y Y Y protected Y Y Y N default Y Y N N private Y N N N ...

  6. Selenium-xapth定位

    xpath 的定位方法, 非常强大.  使用这种方法几乎可以定位到页面上的任意元素. 什么是xpath xpath 是XML Path的简称, 由于HTML文档本身就是一个标准的XML页面,所以我们可 ...

  7. 使用Python 2.7实现的垃圾短信识别器

    最近参加比赛,写了一个垃圾短信识别器,在这里做一下记录. 官方提供的数据是csv文件,其中训练集有80万条数据,测试集有20万条数据,训练集的格式为:行号 标记(0为普通短信,1为垃圾短信) 短信内容 ...

  8. flowable 6.1.2 命令行完成请假审批流程的例子

    一.创建 eclipse maven新项目 1.设置项目选项 其中,Create a simple project 要选中. 2.填写项目包名和项目名称 这里的Group id:必须是 org.flo ...

  9. C++11 Lambda表达式(匿名函数)

    http://www.cnblogs.com/RainyBear/p/5733399.html http://blog.163.com/lvan100@yeah/blog/static/6811721 ...

  10. linux 段错误常见处理方法

    1.如果没有产生core文件,可以查询系统log 通过 sudo cat /var/log/messages |grep segfault 或者 sudo dmesg|grep segfault 获得 ...