Integration Testing Flask Apps

Pytest fixtures are pretty amazing, and I end up writing quick and dirty fixtures all the time for my tests. I just wrote a quickie pytest fixture for integration testing flask apps. Here's how you use it:

import requests

def test_request_tasks(server):  
    assert requests.get(server + '/tasks').status_code == 200

Pytest will fork and run your app in another process, and you can request urls using your http library of choice (hahaha, there is only one correct choice).

OK, I warned you that this is quick-and-dirty, so here it is:

@pytest.yield_fixture()
def server():  
    PORT = 12345
    pid = os.fork()
    if pid == 0:
        app.run(port=PORT)
    else:
        while True:
            try:
                requests.get('http://localhost:{0}'.format(PORT))
                break
            except requests.ConnectionError:
                continue
    yield 'http://localhost:{0}'.format(PORT)
    os.kill(pid, signal.SIGTERM)

A couple things to note:

The port is just hardcoded to 12345, if you got motivated you could have the forked process bind to port 0, which will return a handy random free port, then use a pipe to communicate back to the main process and let it know the port number. That's WORK though.

Also I'm using SIGTERM to kill the process, which can actually be ignored by the process if it is feeling frisky. So you can swap that out for SIGKILL if you run into problems. Here's a little more on SIGKILL vs SIGTERM

This method is adapted from Matt O'Donnel's unittest method here