Search code examples
tddpyramiddjango-testing

Pyramid-Ptah for TDD enthusiasts coming from Django


Pyramid-Ptah does not suck, as web frameworks go. It carefully throws away the worst of all the old-school libraries that it imports, and it solves model-view-controller as elegantly as RoR or Django.

Now let's TDD that the homepage.pt contains the correct HTML, per any recent vandalism by us. We will add "Rumble Monkey" to homepage.pt, and assert we can see it in some generated HTML.

To run the Home page, for example, app.py need merely issue these lines:

config.add_route('home', '/')

And where is 'home' going? and how to test it?

Here's HomepageView:

@view_config(route_name='home',
             renderer=player.layout('shelf_ptah:homepage.lt', 'content'))
class HomepageView(object):

    def __init__(self, request):

        self.request = request

    def __call__(self):
        return {}

The route names are both home, so HomepageView tests it.

Next, how to test HomepageView? How to render it the same way the server would.

In Django, we'd use the Client() mock-server object:

def test_index(self):
    resp = self.client.get('/')
    self.assertEqual(resp.status_code, 200)

So, how to render a input URI and get a response.content, as a string, under test, in Ptah-land?


Solution

  • The documentation of Pyramid suggests using webtest for functional tests.

    http://docs.pylonsproject.org/docs/pyramid/en/latest/narr/testing.html#creating-functional-tests

    The example from the docs:

    import unittest
    
    class FunctionalTests(unittest.TestCase):
        def setUp(self):
            from myapp import main
            app = main({})
            from webtest import TestApp
            self.testapp = TestApp(app)
    
        def test_root(self):
            res = self.testapp.get('/', status=200)
            self.assertTrue('Pyramid' in res.body)
    
            assert 'Rumble Monkey' == res.lxml.xpath('head/title')[0].text
    

    I (the OP) got that working with this tweak:

    def setUp(self):
        from app import main
        global_config = {
            '__file__': '...blah/blah/blah/settings.ini',
            'here': '..blah/blah/myapp'}
        settings = {
            'pyramid.includes': '\npyramid_debugtoolbar', 
            'sqlalchemy.url': 'sqlite:///db.sqlite', 
            'pyramid.debug_authorization': 'false', 
            'pyramid.default_locale_name': 'en', 
            'pyramid.reload_templates': 'true', 
            'pyramid.debug_notfound': 'false', 
            'pyramid.debug_templates': 'true', 
            'pyramid.debug_routematch': 'false', 
            'ptah.site_title': 'Rumble Monkey'}
        zapp = main(global_config, **settings)
        from webtest import TestApp
        self.testapp = TestApp(zapp)
    

    I naturally don't know how many of those settings I can take out (or why I had to read the settings.ini file for the app). And I will naturally replace the blah/blah/blah with some os.path.dirname(__file__) wizardry.