Writing tests

Tests are performed using nose2. The documentation is here

Naming tests

Add a file with a name starting with test_ under the test folder. In the new file each test function must start with test_. By adding a number in the test function, it is possible to order the execution of the tests. For instance:

def test_01_get_oauthlogin(self):

will executed before:

def test_02_get_authorize(self):

Following this naming convention the new test file will be automatically discovered by nose2. See (http://nose2.readthedocs.io/en/latest/usage.html#naming-tests) for more details.

Fixtures

A test fixture represents the preparation needed to perform one or more tests, and any associate cleanup actions. This may involve, for example, creating temporary or proxy databases, directories, or starting a server process. Since we are testing services which run on a Flask server, we have to start a Flask instance before performing the tests. To do so, we can use fixtures to automatically start and stop the Flask server (see https://docs.python.org/3/library/unittest.html#class-and-module-fixtures for details).

Flask provides a way to test your application by exposing the Werkzeug test Client and handling the context locals for you (see http://flask.pocoo.org/docs/0.10/testing/)

In the setUpClass add the following code to create a new Flask test client:

app = create_app()
app.config['TESTING'] = True
self.app = app.test_client()

Assert

Make use of the several assert methods offered by unittest to check for and report failures: these methods produce a much more descriptive error in case of failure.

Method assertChecks that
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)

An example

Here is an example of test file that you can use as a reference

"""
Test  dataobjects endpoints
"""

import io
import os
import json
import unittest
from restapi.server import create_app


__author__ = 'Roberto Mucci (r.mucci@cineca.it)'


class TestDataObjects(unittest.TestCase):

    @classmethod
    def setUpClass(self):
        "set up test fixtures"
        print('### Setting up flask server ###')
        app = create_app()
        app.config['TESTING'] = True
        self.app = app.test_client()

    @classmethod
    def tearDownClass(self):
        "tear down test fixtures"
        print('### Tearing down the flask server ###')

    def test_01_get_verify(self):
        """ Test that the flask server is running and reachable"""

        r = self.app.get('http://localhost:8080/api/verify')
        self.assertEqual(r.status_code, 200)

    def test_02_post_dataobjects(self):
        """ Test file upload: POST """
        # I need to understand who to reapeat the upload test, since
        # overwrite is not allowed
        r = self.app.post('http://localhost:8080/api/dataobjects', data=dict(
                         file=(io.BytesIO(b"this is a test"),
                          'test.pdf')))
        self.assertEqual(r.status_code, 200)  # maybe 201 is more appropriate