2012-11-20 26 views
4

我有一个金字塔应用程序,我仍然试图学习。我应该为它编写单元测试,但我不知道如何构建请求。单元测试时如何获得实际的金字塔请求

我看到金字塔有一个DummyRequest的测试模块,但是这是空白的,很明显,如果我将它传递给它将失败的视图,因为它没有填充请求在运行时的属性。

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

回答

8

无论何时您进行单元测试(这与功能测试都不同),就是您正在测试一个小的“单元”。这个单位(在这种情况下你的看法)不需要“真正”的请求,也不需要一个完整的工作系统。这种观点对于自称为“请求”的对象可能具有某种期望,但这就是关于它的内容,并且它确实不需要真实请求中可用的所有内容。这是模拟或虚拟物体发挥作用的地方。你想测试你的视图,所以你可以传递一些东西到你的视图中,并用它需要的属性来检查它是否在做这件事。比方说,你有以下配置:

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() 

大,所以这是一个真正的观点,你会发现,它只需要请求有两个属性,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来帮助确保您的整个应用程序按预期工作,但这不是单元测试的领域。

+0

什么将是实现''request.db.query''方法最佳做法? ''MagicMock()''?现在回想起来,SQLAlchemy中的查询实际上会返回一个“User”实例,因此可以模拟使DummyDB()。query()方法返回期望的用户号? –

2

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

1

我认为Brian的答案很好,但会补充说“尽可能容易地编写可测试的代码”是一个有用的口头禅。就您可以使功能模块化并编写便于使用您熟悉的非请求相关手段进行单元测试的便携式库而言,您会很高兴。

功能测试比单元测试更难,更混乱,速度更慢,正如Brian所说,Webtest就是金字塔所在的地方。硒又一个数量级更难,更混乱,更慢。小心;如果您的测试依赖于实际数据,那么随着数据更改,它们将随时间而中断。嘲笑和好的虚拟数据可以帮助解决这个问题。在必要时使用更高级别,更难的测试形式,但不仅仅是为了好玩 - 您可以在一定程度上使用您的架构来减少对它的需求。

要回答的实际“你怎么了”的问题:如果你有类似WebTest的,你只是做一些设置,然后像做

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

,那么你必须与所有一个方便的响应对象你可能希望的信息,然后你写你的断言。 tutorial in the docs将会比我更好地解释。

1

你可以建立在设置功能的“假”这样的要求:

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

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

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

希望这有助于