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