使用 paste.fixture 进行单元测试
PyLons 使用 paste.fixture 来模拟向应用程序发起请求,为你的应用程序提供了强大的单元测试的能力。这样你就可以保证响应是被正确的处理了,(You can then ensure that the response was handled appropriately and that the controller set things up properly.)
PyLons 利用 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 文件修改如下:
然后编写一系列基本的测试,保证该控制器的 actions 正确地执行了它们的功能,将 testexample/tests/functions/test_comments.py 修改如下:
1 from testexample.tests import *
2
3 class TestCommentsController(TestController):
4 def test_index(self):
5 response = self.app.get(url_for(controller='/comments'))
6 assert 'Basic output' in response
7
8 def test_sess(self):
9 response = self.app.get(url_for(controller='/comments', action='sess'))
10 assert response.session['name'] == 'Joe Smith'
11 assert 'Saved a session' in response
在项目主目录下运行 nosetests 然后你应该可以看到它们都通过了:
.. ---------------------------------------------------------------------- Ran 2 tests in 2.999s OK
不幸的是,如果你使用 assertion 进行测试的话,当它失败的时候,nosetests (至少0.8.6) 还不能提供 assertion 结果的详细信息。比如将下面这个测试添加到 test_sess 函数中:
1 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 ,它会提供更多信息。新的测试如下:
1 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应用程序测试方面的部分: