Python Web Framework Series – Pylons: Part 2 Controllers, Views and Testing


We last left off with Getting Started and having created our “pylonsforum” project and generated our first controller.

Source for home.py

``

import logging </p>

from pylons import request, response, session, tmpl_context as c 
from pylons.controllers.util import abort, redirect_to 

from pylonsforum.lib.base import BaseController, render 

log = logging.getLogger(__name__) 

class HomeController(BaseController): 

    def index(self): 
        # Return a rendered template 
        #return render(‘/home.mako’) 
        # or, return a response 
        return ‘Hello World </div> </div>

Source for test_home.py

 

from pylonsforum.tests import * </p>

class TestHomeController(TestController): 

    def test_index(self): 
        response = self.app.get(url(controller=‘home’, action=‘index’)) 
        # Test response… </div> </div>

 

 

Some Testing Setup

Now this is optional but these are some things I got out of the Pylons Book with test setup, mainly I wanted to refresh the test database on every go.

first open up test.ini in the top level of your project and change the [app:main] section to the following:


 

[app:main]
#use = config:development.ini
use = egg:pylonsforum
full_stack = true
cache_dir = % (here)s/data
beaker.session.key = pylonsforum
beaker.session.secret = somesecret</p>

sqlalchemy.url = sqlite:///%(here)s/test.db </div> </div>

 

 


Then open up websetup.py in the pylonsforum directory and change it to so:

“””Setup the pylonsforum application”””
import logging
from pylonsforum import model
import os.path</p>

from pylonsforum.config.environment import load_environment

log = logging.getLogger(__name__)

def setup_app(command, conf, vars):
    load_environment(conf.global_conf, conf.local_conf)
    # Load the models
    from pylonsforum.model import meta
    meta.metadata.bind = meta.engine
    filename = os.path.split(conf.filename)[-1]
    if filename == ‘test.ini’:
        # Permanently drop any existing tables
        log.info(“Dropping existing tables…”)
        meta.metadata.drop_all(checkfirst=True)
    # Continue as before
    # Create the tables if they aren’t there already
    meta.metadata.create_all(checkfirst=True)
    log.info(“Successfully set up.”)

 

 

this will ensure a proper refresh of the database each time you run a test.

 

Testing

Now that we’re setup lets get onto testing (test first).

So far my study has found pylons to emphasize functional tests over unit tests. Hopefully, those with more experience will correct me. On the plus side nothing is stopping you from unit tests, and the functional test support is really nice giving you access to the response object including your view.

The response object there will let you examine the html returned based on the conditions you’ve set. lets not get to advanced yet and just change test_index to look for a specific page title so change the test_index test to the following

  def test_index_title(self):
      response = self.app.get(url(controller=‘home’, action=‘index’))
      assert Pylons Forum in response
      # Test response…

so what we have here is a test asserting that our web response is able to find “Pylons Forum” in the page somewhere. running the following command from the top level directory where test.ini is located:

nosetests --with-pylons=test.ini

will results in the following failed test result:

 Picture 2

Controller and view review

Pylons has a return based controller/action behavior. So it can return a number of objects for now we can focus on raw text and rendering a view.

As you can see from the comments rendering a view is as simple as placing one in the template directory

edit home.py index action to look like so:

 

  def index(self):
    return render(‘index.mako’)

 

 

then create a file in the templates directory called index.mako that looks like so

 

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
</span>
</span>Pylons Forum<span style="color: #007000"></title></span><br /> <span style="color: #007000"></head></span><br /> <span style="color: #007000"><body></span><br /> <span style="color: #007000"><div</span> <span style="color: #0000c0">id=</span>“recentposts” <span style="color: #0000c0">style=</span>“float: right” <span style="color: #007000">></span><br /> <span style="color: #007000"><table></span><br /> <span style="color: #007000"><thead><tr><th></span>subject<span style="color: #007000"></th><th></span>author<span style="color: #007000"></th><th></span>date submitted<span style="color: #007000"></th></tr></thead></span><br /> <span style="color: #007000"><tbody></span><br /> <span style="color: #007000"><tr><td></span>jkruse<span style="color: #007000"></td><td></span>Re: Whats Up<span style="color: #007000"></td><td></span>06/01/2009<span style="color: #007000"></td></tr></span><br /> <span style="color: #007000"><tr><td></span>rsvihla<span style="color: #007000"></td><td></span>Whats Up<span style="color: #007000"></td><td></span>06/01/2009<span style="color: #007000"></td></tr></span><br /> <span style="color: #007000"><tr><td></span>thondo<span style="color: #007000"></td><td></span>Re: Looking for new work<span style="color: #007000"></td><td></span>05/25/2009<span style="color: #007000"></td></tr></span><br /> <span style="color: #007000"><tr><td></span>jkruse<span style="color: #007000"></td><td></span>Re: Looking for new work<span style="color: #007000"></td><td></span>5/20/2009<span style="color: #007000"></td></tr></span><br /> <span style="color: #007000"><tr><td></span>usmith<span style="color: #007000"></td><td></span>Looking for new work<span style="color: #007000"></td><td></span>05/01/2009<span style="color: #007000"></td></tr></span><br /> <span style="color: #007000"></tbody></span><br /> <span style="color: #007000"></table></span><br /> <span style="color: #007000"></div></span><br /> <span style="color: #007000"></body></span> </div> </div> <p>   </p> <h3> </h3> <p>   </p> <p> Now that we’ve created our view and our action rendering said view, lets run our test again and see what we get: </p> <p> <a href="//lostechies.com/ryansvihla/files/2011/03/Picture4_52B6D823.png"><img height="169" width="810" border="0" src="//lostechies.com/ryansvihla/files/2011/03/Picture4_thumb_0993BD1B.png" alt="Picture 4" style="border-right-width: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px" /></a> </p> <p>   </p> <h3> In Closing </h3> <p> This whirlwind tour of testing, views and controllers is at an end. Stay tuned for more in depth coverage of controllers and views in the next post. </p> </td></span></td></span></td></tr></span></td></span></td></span></td></tr></span></td></span></td></span></td></tr></span></td></span></td></span></td></tr></span></td></span></td></span></td></tr></span></tbody></span></th></span></th></span></th></tr></thead></span></table></span></body></span>

Python Web Framework Series – Pylons: Part 1 Getting Started