I am writing a Pyramid web application that uses URL dispatch for mapping routes to views.
I would like to write a set of unit tests that provide Pyramid's "route matcher" with a variety of paths, and then assert that:
request.matchdict
contains the expected contentsHow can I do this at a proper unit test level (as opposed to at a functional level, by submitting actual HTTP requests)? Which "unit" in Pyramid actually does the route matching, and how can I access it to test my app's configured routing?
NOTE: I know I can do this using functional testing, but I am asking this question because I want to know how to test it much more narrowly--just the route matching portion. I suppose what I'm looking for might be considered an integration test and not a unit test, because it touches multiple components...
I have Googled and read relevant Pyramid documentation, including Dispatching URLs To Views With Routing and Unit, Integration, and Functional Testing. Nothing I have seen shows me how to test my application's configured routes without doing functional tests.
There is not a public api to do this in Pyramid. However, there is a private and pretty stable API for it.. you've been warned.
Route matching doesn't occur on just patterns but also predicates so it requires a full request object to do matching, not just a url.
registry = config.registry or request.registry
mapper = registry.getUtility(pyramid.interfaces.IRoutesMapper)
result = mapper(request)
route, matchdict = result['route'], result['match']
if route is not None:
route # pyramid.interfaces.IRoute object
matchdict # request.matchdict
The raw IRoute
objects themselves are available on a public api via the introspector. You can look these up and match against them on a per-route basis, but this will ignore the route ordering inherent to Pyramid.
introspector = config.registry or request.registry.introspector
intr = introspector.get('routes', route_name)
route = intr['route']
match = route.match(path)
if match is not None:
route # pyramid.interfaces.IRoute object
match # request.matchdict
The route also has the predicates on it which you can pass the request
to in order to determine if the predicates pass.