5

我有一个 Pyramid 应用程序,我仍在努力学习。我应该为它编写单元测试,但我不知道如何构建请求。

我看到 Pyramid 有一个带有 a 的测试模块,DummyRequest但这是空白的,显然如果我将它传递到视图中,它将失败,因为它没有填充请求在运行时将具有的属性。

所以问题是,如何在测试时传递一个看起来像运行时请求的请求?

4

4 回答 4

9

每当您进行单元测试(与功能测试不同)时要意识到的是,您正在测试一个小“单元”。该单元(在这种情况下是您的视图)不需要“真正的”请求,也不需要完整的工作系统。该视图对自称为“请求”的对象可能具有的某些期望,但仅此而已,它当然不需要真实请求中可用的所有内容。这就是模拟或虚拟对象发挥作用的地方。你想测试你的视图,所以你可以将一些东西传递到你的视图中,它需要检查它是否在做这项工作。假设您有以下配置:

def main():
    config = Configurator()
    config.add_route('user', '/users/{uid}')
    return config.make_wsgi_app()

@view_config(route_name='user', renderer='user_template.mako')
def user_view(request):
    uid = request.matchdict['uid']
    user = find_user(request, uid)
    if user is None:
        raise HTTPNotFound
    return {'user': user}

def find_user(request, uid):
    return request.db.query(User).filter_by(id=uid).first()

太好了,所以这是一个真实的视图,您会注意到它只要求请求具有 2 个属性,matchdict并且db. 好吧,我们可以这样做:

class Test_user_view(unittest.TestCase):
    def test_it(self):
        req = DummyRequest()
        req.db = DummyDB()
        req.matchdict = {'uid': '3'}
        result = user_view(req)
        self.assertEqual(result['user'].id, 3)

现在我们在这里没有解决的一件事是实现,DummyDB但更好的方法可能是模拟find_user返回一个虚拟值。这使测试保持简单并专注于视图本身,而不会陷入与数据库的对话。那是一个单独的测试。

这里的其他答案更彻底地涵盖了功能测试,您应该确定使用 WebTest 来帮助确保您的整个应用程序按预期工作,但这不是单元测试的领域。

于 2012-11-21T06:27:21.220 回答
2

如果您还没有这样做,请查看Pyramid 单元与集成与功能测试Pyramid 测试指南。恕我直言,从功能测试开始,而不是使用 DummyRequest 进行单元测试,在许多情况下往往会给出更好的结果(即更容易实现和维护)。我建议使用Webtest(金字塔文档中的示例)Selenium库(或两者的组合)。使用 webtest 将允许您测试基本功能,并且测试通常会比 Selenium 运行得更快。Selenium 实际上可以启动浏览器并允许更精细的控制。因为它会启动浏览器,所以 selenium 测试往往需要更长的时间才能运行。我认为一个好的经验法则是,如果您只需要基本测试(例如,查看特定页面是否加载),那么坚持使用 Webtest。如果您的测试需要对浏览器进行更多控制(例如调试 javascript),请尝试 Selenium。查看上面链接的文档,了解如何使用这些库进行测试的示例。

于 2012-11-21T02:57:34.803 回答
2

您可以在 setUp 函数中构建这样的“假”请求:

request = testing.DummyRequest()
request.errors = errors.Errors([])
request.validated = {}

然后在你的一个测试中设置你想要测试的参数。像这样:

request.GET['app_id'] = 'xxxxxxxxx'
valid_register(request)
self.assertTrue('app_id' in request.validated)

希望这可以帮助

于 2012-11-21T07:12:35.180 回答
1

我认为布赖恩的回答很好,但会补充说“尽可能多地编写易于测试的代码”是一个有用的口头禅。在某种程度上,您可以使功能模块化并编写易于使用您熟悉的非请求依赖方式进行单元测试的可移植库,您会很高兴。

功能测试比单元测试更难、更慢、更差一个数量级;正如 Brian 提到的,Webtest 是 Pyramid 的所在。硒是另一个数量级的更难、更混乱、更慢。当心; 如果您的测试依赖于实际数据,那么随着数据的变化,它们会随着时间的推移而中断。模拟和良好的虚拟数据可以帮助解决这个问题。在必要时使用更高级别、更困难的测试形式,但不仅仅是为了好玩——您可以在某种程度上使用您的架构来减少对它的需求。

要回答实际的“你好吗”问题:如果你有类似 Webtest 的东西,你只需做一些设置,然后做类似的事情

response = app.get('/form.html')

然后你有一个方便的响应对象,其中包含你想要的所有信息,然后你写你的断言。文档中的教程将比我解释得更好。

于 2012-11-21T03:59:42.440 回答