如何在单元测试时获得实际的金字塔请求

时间:2012-11-20 23:36:35

标签: python unit-testing pyramid

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

我看到Pyramid有一个带有DummyRequest的测试模块,但这是空白的,很明显,如果我将其传递给视图,它将会失败,因为它没有填充请求所具有的属性跑步时。

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

4 个答案:

答案 0 :(得分: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个属性,matchdictdb。我们可以做到这一点:

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帮助确保整个应用程序按预期工作,但这不是单元测试的领域。

答案 1 :(得分:2)

如果您还没有,请查看Pyramid unit vs integration vs functional testingPyramid testing guidelines。恕我直言,从功能测试开始,与使用DummyRequest的单元测试相反,在许多情况下往往会提供更好的结果(即更容易实现和维护)。我建议使用Webtest (examples in pyramid docs)Selenium库(或两者的组合)。使用webtest将允许您测试基本功能,测试通常比Selenium运行得更快。 Selenium实际上可以启动浏览器并允许更精细的控件。因为它启动了浏览器,所以selenium测试往往需要更长的时间才能运行。我认为一个好的经验法则是,如果您只需要基本测试(例如,查看特定页面是否加载),那么请坚持使用Webtest。如果您的测试需要对浏览器进行更多控制(例如调试javascript),请尝试使用Selenium。查看上面链接的文档,以获取有关如何使用这些库进行测试的示例。

答案 2 :(得分: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)

希望这有帮助

答案 3 :(得分:1)

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

功能测试比单元测试更难,更混乱,更不简单;正如布莱恩所提到的,Webtest就是金字塔的用武之地。硒是另一个数量级更难,更混乱和更慢。小心;如果您的测试依赖于实际数据,它们将随着数据的变化而中断。模拟和良好的虚拟数据可以帮助解决这个问题。在必要时使用更高级别,更困难的测试形式,但不仅仅是为了好玩 - 您可以在某种程度上使用您的架构来减少对它的需求。

回答实际的“你好吗”问题:如果你有像Webtest这样的东西,你只需做一些设置,然后做一些像

这样的事情。
response = app.get('/form.html')

然后你有一个方便的响应对象,包含你想要的所有信息,然后你写下你的断言。 tutorial in the docs将比我更好地解释。