Skip to content

[Flask] Running unit tests with Flask Testing and coverage

Radu Raicea edited this page Jan 26, 2018 · 2 revisions

Flask-Testing is used to facilitate unit testing by using its setUp and tearDown methods, among others. Coverage is used to show the percentage of the code that is being covered by the tests. A coverage report is generated only when all the tests pass.

The official documentations can be found here:

https://pythonhosted.org/Flask-Testing/
https://coverage.readthedocs.io/en/coverage-4.4.1/

Creating tests

Multiple test files are used to group the unit tests together (authentication tests, database manipulation tests, etc.)

The tests are written in files starting with test_. An example of a test file is test_website.py:

import logging
import os
import unittest

from flask_testing import TestCase

from project import create_app, logger

# Creates a new instance of the Flask application. The reason for this
# is that we can't interrupt the application instance that is currently
# running and serving requests.
app = create_app()


class TestWebsite(TestCase):

    def create_app(self):
        """
        Instructs Flask to run these commands when we request this group of tests to be run.
        """
        
        # Sets the configuration of the application to 'TestingConfig' in order
        # that the tests use db_test, not db_dev or db_prod.
        app.config.from_object('config.TestingConfig')

        # Sets the logger to only show ERROR level logs and worse. We don't want
        # to print a million things when running tests.
        logger.setLevel(logging.ERROR)

        return app

    def setUp(self):
        """Defines what should be done before every single test in this test group."""
        pass

    def tearDown(self):
        """Defines what should be done after every single test in this test group."""
        pass

    def test_index_page_successful(self):
        """
        Every single test in this test group should be defined as a method of this class.

        The methods should be named as follows: test_<name_of_test>
        """
        
        with self.client:
            response = self.client.get('/')
            self.assertEqual(response.status_code, 200)

# Runs the tests.
if __name__ == '__main__':
    unittest.main()

Running the tests with coverage

Write all the unit tests inside /flask/tests/, start the application and run the tests using the following command in another shell

docker-compose run --rm flask python manage.py cov

Running just one of the test groups

Start the application and run the test group using the following command in another shell (running test_website.py in this example)

docker-compose run --rm flask python manage.py test_one test_website

Note that the coverage report is not generated when only running one test group