(转) Twisted : 第十五部分 测试诗歌

简介

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

幸运地是,Twisted包含本身的测试框架,叫 trial,它支持测试异步代码(固然你也能够用它测试同步代码).python

咱们假设你已经熟悉了 unittest 的机理和类似的测试框架,它容许你经过定义类建立测试.这个类一般是一个父类(一般叫"TestCase")的子类,类中的方法以"test"开头并被视做一个测试.框架负责发现全部的测试,一个接一个地运行它们,并伴有可选项 setUp 和 tearDown 步骤,以后报告结果.react


例子
git

你能够在 tests/test_poetry.py 中找到一些关于测试的例子.为了确保咱们全部的例子是自包含的(以便你不用担忧PYTHONPAYH设置),咱们将全部须要的代码拷贝到测试模块中.固然正常状况,你只需导入须要测试的模块.github

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

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显示了一个正在进行中的假想测试:

_static/p15_test-1.png

图33: 进行中的trial测试

若是你以前使用过相似的框架,这是一个熟悉的模型,除了全部测试相关的方法可能返回 deferreds.

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

  1. 非阻塞而且,一般

  2. 返回一个 deferred.

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


总结

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

在 :doc:`p16` 中,咱们将使用Twisted工具将诗歌服务器转化为一个真正的守护进程.

相关文章
相关标签/搜索