使用 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

与测试有关的 PyLons 对象

PyLonspaste.fixture response 对象添加了几个属性,你可以通过该对象访问到一些在web请求过程中才创建的对象。

要使用它们,只需要执行 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 文件修改如下:

   1     from testexample.lib.base import *
   2 
   3     class CommentsController(BaseController):
   4         def index(self):
   5             return Response('Basic output')
   6 
   7         def sess(self):
   8             session['name'] = 'Joe Smith'
   9             session.save()
  10             return Response('Saved a session')

然后编写一系列基本的测试,保证该控制器的 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应用程序测试方面的部分:

Testing Application with Paste, the Tests

PyLons/UnitTest (last edited 2009-12-25 07:10:23 by localhost)

Loading