Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

Integration Tests with CherryPy and requests

$
0
0

CherryPy is a great way to write simple http backends, but there is a part of it that I do not like very much. While there is a documented way of setting up integration tests, it did not work well for me for a couple of reasons. Mostly, I found it hard to integrate with the rest of the test suite, which was using unittest and not py.test. Failing tests would apparently “hang” when launched from the PyCharm test explorer. It turned out the tests were getting stuck in interactive mode for failing assertions, a setting which can be turned off by an environment variable. Also, the “requests” looked kind of cumbersome. So I figured out how to do the tests with the fantastic requests library instead, which also allowed me to keep using unittest and have them run beautifully from within my test explorer.

The key is to start the CherryPy server for the tests in the background and gracefully shut it down once a test is finished. This can be done quite beautifully with the contextmanager decorator:

from contextlib import contextmanager
@contextmanager
def run_server():
cherrypy.engine.start()
cherrypy.engine.wait(cherrypy.engine.states.STARTED)
yield
cherrypy.engine.exit()
cherrypy.engine.block()

This allows us to conviniently wrap the code that does requests to the server. The first part initiates the CherryPy start-up and then waits until that has completed. The yield is where the requests happen later. After that, we initiate a shut-down and block until that has completed.

Similar to the “official way”, let’s suppose we want to test a simple “echo” Application that simply feeds a request back at the user:

class Echo(object):
@cherrypy.expose
def echo(self, message):
return message

Now we can write a test with whatever framework we want to use:

class TestEcho(unittest.TestCase):
def test_echo(self):
cherrypy.tree.mount(Echo())
with run_server():
url = "http://127.0.0.1:8080/echo"
params = {'message': 'secret'}
r = requests.get(url, params=params)
self.assertEqual(r.status_code, 200)
self.assertEqual(r.content, "secret")

Now that feels a lot nicer than the official test API!


Viewing all articles
Browse latest Browse all 9596

Latest Images

Trending Articles