## page was renamed from PyLons/UnitTest <> = 使用 paste.fixture 进行单元测试 = PyLons 使用 [[http://pythonpaste.org/testing-applications.html#the-tests-themselves|paste.fixture]] 来模拟向应用程序发起请求,为你的应用程序提供了强大的单元测试的能力。这样你就可以保证响应是被正确的处理了,(You can then ensure that the response was handled appropriately and that the controller set things up properly.) PyLons 利用 [[http://somethingaboutorange.com/mrl/projects/nose/|nose]] (测试执行/发现软件包) 来执行你的应用程序中的测试套件。在应用程序目录下执行 {{{nosetests}}} 就会运行所有在 tests 目录下创建的测试。如果你还没装 nose,执行以下命令使用 setuptools 来安装: {{{ easy_install -U nose }}} * 注意: {{{paste.fixture}}} 目前和 Windows 不兼容,我们正在解决这个问题。 == 与测试有关的 PyLons 对象 == PyLons 给 {{{paste.fixture}}} response 对象添加了几个属性,你可以通过该对象访问到一些在web请求过程中才创建的对象。 * {{{session}}} Session 对象 * {{{req}}} Request 对象 * {{{c}}} 包含了传递给模板的那些变量的对象 * {{{g}}} Globals 对象 要使用它们,只需要执行 get/post 命令,然后访问 response 的属性即可: {{{ response = app.get('/some/url') assert response.session['var'] == 4 }}} == 示例: 测试一个控制器 == 首先我们创建一个新项目和控制器: {{{ paster create --template=PyLons TestExample cd TestExample paster controller comments }}} 你会发现当你创建一个控制器的时候它创建了两个文件。控制器本身,和它的一个测试,放在 {{{testexample/tests/functional/}}} 目录下。 将 {{{testexample/controllers/comments.py}}} 文件修改如下: {{{#!python from testexample.lib.base import * class CommentsController(BaseController): def index(self): return Response('Basic output') def sess(self): session['name'] = 'Joe Smith' session.save() return Response('Saved a session') }}} 然后编写一系列基本的测试,保证该控制器的 actions 正确地执行了它们的功能,将 {{{testexample/tests/functions/test_comments.py}}} 修改如下: {{{#!python from testexample.tests import * class TestCommentsController(TestController): def test_index(self): response = self.app.get(url_for(controller='/comments')) assert 'Basic output' in response def test_sess(self): response = self.app.get(url_for(controller='/comments', action='sess')) assert response.session['name'] == 'Joe Smith' assert 'Saved a session' in response }}} 在项目主目录下运行 {{{nosetests}}} 然后你应该可以看到它们都通过了: {{{ .. ---------------------------------------------------------------------- Ran 2 tests in 2.999s OK }}} 不幸的是,如果你使用 assertion 进行测试的话,当它失败的时候,nosetests (至少0.8.6) 还不能提供 assertion 结果的详细信息。比如将下面这个测试添加到 {{{test_sess}}} 函数中: {{{#!python assert response.session.has_key('address') == True }}} 当你执行 {{{nosetests}}} 的时候你会得到下面这样的,基本没什么用的响应: {{{ .F ====================================================================== FAIL: test_sess (testexample.tests.functional.test_comments.TestCommentsController) ---------------------------------------------------------------------- Traceback (most recent call last): File "~/TestExample/testexample/tests/functional/test_comments.py", line 12, in test_sess assert response.session.has_key('address') == True AssertionError: ---------------------------------------------------------------------- Ran 2 tests in 1.417s FAILED (failures=1) }}} 既然我们继承的 {{{TestController}}} 是一个标准的 Python 单元测试控制器,那我们可以使用 assertEqual ,它会提供更多信息。新的测试如下: {{{#!python self.assertEqual(response.session.has_key('address'), True) }}} 它会提供以下有用的失败信息: {{{ .F ====================================================================== FAIL: test_sess (testexample.tests.functional.test_comments.TestCommentsController) ---------------------------------------------------------------------- Traceback (most recent call last): File "~/TestExample/testexample/tests/functional/test_comments.py", line 12, in test_sess self.assertEqual(response.session.has_key('address'), True) AssertionError: False != True }}} 关于执行使用了 get/post 的测试,和测试response、headers等的更多细节,请看Paste文档中关于web应用程序测试方面的部分: [[http://pythonpaste.org/testing-applications.html#the-tests-themselves|Testing Application with Paste, the Tests]]