Posted on by & filed under Content - Highlights and Reviews, Programming & Development.

A guest post by Aaron Kavlie, a developer at Stremor working on a mobile voice platform called Plexi.

The Flask documentation gives you some basic guidance on testing Flask apps. It might leave you feeling a little unprepared, however, to handle real-world testing in more complicated applications. In this post I’ll cover some good tools and techniques to make testing your app easier. These techniques are framework agnostic too–so even if you’re using another framework, you should find the content useful.

Be sure to also read my Flask Internationalization and Localization post.

Introducing our Scraper

Let’s start with a basic Hacker News scraper. It gets the stories from the front page, and outputs them as JSON:

The Python standard library includes the unittest unit testing framework. Its inclusion in the standard library makes it a safe default when testing Python code. Using unittest, we can start with a basic test of our scraper:

And if we run it, we get confirmation that our test passes:

It looks like we’re on the right path. And given the simplicity of this scraper, we already have most of the code covered.

Stubbing Remote Services

Unfortunately the test has a pretty big problem, which will become evident if we wait just a few minutes and run the test again:

Why did the test just fail? Because Hacker News data changes all of the time! Even though the story we’re targeting, I Am Not Satoshi, stayed in the same place, a few things still changed: points, comments, and relative time submitted. Obviously we need some way to get a fixed version of the front page to test this code.

Enter Mock. Mock allows us to replace code under test, like that call to requests.get, with a stub that gives the same answer every time. In this case, that would be reading a copy of the front page from a file that makes sense.

After saving the page as hn_front_page.html, we can add a stub for requests.get like so:

And after updating the expected output, we have a passing test again–and it will stay that way!

There are some additional factors that make stubbing an essential practice when testing code that hits remote web services: tests will run much faster, especially if your tests make multiple HTTP requests (as opposed to the single request in our example). This is also friendlier to the site or service you’re hitting, and it could save money if you’re working with an API that isn’t free.

Better Testing with Nose

There’s another issue with our test failure: It’s not as helpful as it could be. unittest truncates long values by default, making it difficult to tell where the wrong values were. Furthermore, if any value is incorrect in the dictionary, the whole test fails. More granular testing would be helpful.

Nose is a popular test runner with a lot of useful features. Its support for test generators is a perfect solution to the all-or-nothing test case we received with unittest. Test generators allow us to iterate through the dictionary and execute one test for each key/value pair in the dictionary.

Here’s our test, rewritten using a test generator:

While Nose works perfectly fine with a unittest class, it also accepts plain functions as shown here, as long as they’re prefixed with test. I tend to prefer the simplicity of writing functions to the class-based approach of unittest.

Here’s what you get when running this test:

This is much more helpful than the test method we used earlier. We now know that 3 of our 7 values were incorrect, and it’s clear what the expected values should be.

Correct those 3 values, and all is well:

Conclusion

While this scraper is pretty simple, the testing techniques demonstrated here really shine when you use them on more complex code bases. The requests stub becomes really helpful when you’re testing against tens or hundreds of URLs, and test generators are handy anywhere you need to test a variety of input/output pairs against a function.

All of the code for this example is available on GitHub. Happy testing!

See below for Flask resources from Safari Books Online.

Not a subscriber? Sign up for a free trial.

Safari Books Online has the content you need

Instant Flask Web Development takes you beyond the quick start in the Flask documentation and shows you a bottom-up approach to organizing your Flask application. It shows you how to build a small deployable scheduling application with pointers to the various design decisions you can make when developing with Flask.
Instant Data Intensive Apps with pandas How-to starts with Pandas’ functionalities such as joining datasets, cleaning data, and other data munging tasks. It quickly moves onto building a data reporting tool, which consists of analysis in Pandas to determine what’s relevant and present that relevant data in an easy-to-consume manner, and also provides a section on Flask.

About the author

aaron Aaron Kavlie started doing web development a few years ago and is currently a developer at Stremor working on a mobile voice platform called Plexi. He mainly does backend work with Python these days, but has been known to do frontend web development in the past. He can be reached at @akavlie.

Tags: Flask, Hacker News, JSON, Mock, Nose, Python, requests stub, scraper, testing, unittest,

Comments are closed.