<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Joys and rants of a Python programmer &#187; testing</title>
	<atom:link href="http://blog.pow.lt/tag/testing/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.pow.lt</link>
	<description>Pow! Wham, bam, kapow!</description>
	<lastBuildDate>Wed, 02 Dec 2009 16:04:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Running browser in the middle of a Pylons test</title>
		<link>http://blog.pow.lt/2009/12/01/running-browser-in-the-middle-of-a-pylons-test/</link>
		<comments>http://blog.pow.lt/2009/12/01/running-browser-in-the-middle-of-a-pylons-test/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 14:49:15 +0000</pubDate>
		<dc:creator>Ignas Mikalajūnas</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Pylons]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.pow.lt/?p=83</guid>
		<description><![CDATA[
  Tests are good! writing tests is good! Sometimes they break and you
  can&#8217;t understand what&#8217;s wrong. Pylons is using webtest.TestApp for functional test and
  TestResponse has a showbrowser method, a method that
  displays the response in your browser, but most of the time it&#8217;s
  just not enough.



  When [...]]]></description>
			<content:encoded><![CDATA[<p>
  Tests are good! writing tests is good! Sometimes they break and you
  can&#8217;t understand what&#8217;s wrong. Pylons is using <code>webtest.TestApp</code> for functional test and
  <code>TestResponse</code> has a <code>showbrowser</code> method, a method that
  displays the response in your browser, but most of the time it&#8217;s
  just not enough.
</p>

<p>
  When I started using Pylons, I missed the ability to start a server
  in the middle of the test so much (I had implemented this
  functionality for Zope3 functional tests before) that I just had to
  add it to my Pylons testing environment. As Pylons is a WSGI
  application, it was even easier than I expected:
</p>

<pre class="brush: python;">
import pylons
import webbrowser
import sys
import urllib2

from webtest import TestApp
from wsgiref.simple_server import make_server


def addPortToURL(url, port):
    &quot;&quot;&quot;Add a port number to the url.

        &gt;&gt;&gt; addPortToURL('http://localhost/foo/bar/baz.html', 3000)
        'http://localhost:3000/foo/bar/baz.html'
        &gt;&gt;&gt; addPortToURL('http://foo.bar.com/index.html?param=some-value', 555)
        'http://foo.bar.com:555/index.html?param=some-value'

        &gt;&gt;&gt; addPortToURL('http://localhost:666/index.html', 555)
        'http://localhost:555/index.html'

    &quot;&quot;&quot;
    (scheme, netloc, url, query, fragment) = urllib2.urlparse.urlsplit(url)
    netloc = netloc.split(':')[0]
    netloc = &quot;%s:%s&quot; % (netloc, port)
    url = urllib2.urlparse.urlunsplit((scheme, netloc, url, query, fragment))
    return url


class ServingTestApp(TestApp):

    request = None

    def do_request(self, req, status, expect_errors):
        self.request = req
        return super(ServingTestApp, self).do_request(req, status, expect_errors)

    def serve(self, page_url=None):
        try:
            if page_url is None:
                page_url = getattr(self.request, 'url', 'http://localhost/')
            # XXX we rely on browser being slower than our server
            webbrowser.open(addPortToURL(page_url, 5001))
            print &gt;&gt; sys.stderr, 'Starting HTTP server...'
            srv = make_server('localhost', 5001, pylons.test.pylonsapp)
            srv.serve_forever()
        except KeyboardInterrupt:
            print &gt;&gt; sys.stderr, 'Stopped HTTP server.'
</pre>

<p>
Now instead of the usual <code>TestApp</code> you just
use <code>ServingTestApp</code>
</p>

<pre class="brush: python;">
class TestController(TestCase):

    def __init__(self, *args, **kwargs):
        if pylons.test.pylonsapp:
            wsgiapp = pylons.test.pylonsapp
        else:
            wsgiapp = loadapp('config:%s' % config['__file__'])
        # Replace:
        # self.app = TestApp(wsgiapp)
        # With
        self.app = ServingTestApp(wsgiapp)
        url._push_object(URLGenerator(config['routes.map'], environ))
        TestCase.__init__(self, *args, **kwargs)
</pre>

<p>
And in your code you can do this:
</p>

<pre class="brush: python;">
from sample.tests import *

class TestHelloController(TestController):

    def test_index(self):
        response = self.app.get(url(controller='hello', action='index'))
        # Test response...
        self.app.serve()
</pre>

<p>
  This is immensely useful when you want to find out what to click
  next, while writing a test for a part of the application that you
  haven&#8217;t worked with for a while. Or browser stress-testing, because
  now you can just use your testing framework to generate thousands of
  throw away objects in a database that will be gone when a test is
  over, and will be there again when you run the test for the second
  time.
</p>

<p>
  I use it a lot when I want to test the UI of deleting objects, or
  when I work on things that have a uni-directional workflow. Testing
  the step number 7 in your browser requires you completing the first
  6 steps, doing that every time you want to look at the transition
  from step 7 to step 8 is just too much work.
</p>
<a href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.pow.lt%2F2009%2F12%2F01%2Frunning-browser-in-the-middle-of-a-pylons-test%2F&amp;linkname=Running%20browser%20in%20the%20middle%20of%20a%20Pylons%20test" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.pow.lt/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a> <a href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.pow.lt%2F2009%2F12%2F01%2Frunning-browser-in-the-middle-of-a-pylons-test%2F&amp;linkname=Running%20browser%20in%20the%20middle%20of%20a%20Pylons%20test" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.pow.lt/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a> <a href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.pow.lt%2F2009%2F12%2F01%2Frunning-browser-in-the-middle-of-a-pylons-test%2F&amp;linkname=Running%20browser%20in%20the%20middle%20of%20a%20Pylons%20test" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.pow.lt/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a> <a href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.pow.lt%2F2009%2F12%2F01%2Frunning-browser-in-the-middle-of-a-pylons-test%2F&amp;linkname=Running%20browser%20in%20the%20middle%20of%20a%20Pylons%20test" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.pow.lt/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a> <a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.pow.lt%2F2009%2F12%2F01%2Frunning-browser-in-the-middle-of-a-pylons-test%2F&amp;linkname=Running%20browser%20in%20the%20middle%20of%20a%20Pylons%20test"><img src="http://blog.pow.lt/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.pow.lt/2009/12/01/running-browser-in-the-middle-of-a-pylons-test/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
