Python Falcon - Testing



Falcon's testing module is a Functional testing framework for Falcon apps. It contains various test classes and utility functions to support functional testing. The testing framework supports both unittest and pytest.

We shall use following the script (myapp.py) to demonstrate testing functionality. It contains a HelloResource class with an on_get() responder that renders a JSON response of Hello World. The create() function returns Falcon's Application object added with a route registered with '/' URL.

from waitress import serve
import falcon
import json
class HelloResource:
   def on_get(self, req, resp):
      """Handles GET requests"""
      resp.text=json.dumps({"message":"Hello World"})

   # This is the default status
   resp.status = falcon.HTTP_200

   # Default is JSON, so override
   resp.content_type = falcon.MEDIA_JSON 
def create():
   app = falcon.App()
   hello = HelloResource()
   app.add_route('/', hello)
   return app
app=create()
if __name__ == '__main__':
   serve(app, host='0.0.0.0', port=8000)

Using unittest

The testing.TestCase extends unittest to facilitate functional testing of WSGI/ASGI applications written with Falcon. We need to inherit from this base class and write the tests.

The test functions in the TestCase subclass are of the name simulate_*() where '*' stands for HTTP methods like GET, POST etc. It means, we have to fetch the result of simulate_get() function and compare it with the expected result by assertion functions.

The simulate_*() functions receive two arguments.

simulate_*(app, route)

Following is the code for test-myapp.py. It executes simulate_get() function and asserts its result with the anticipated result and indicates whether the test has failed or passed.

from falcon import testing
import myapp
class MyTestCase(testing.TestCase):
   def setUp(self):
      super(MyTestCase, self).setUp()
      self.app = myapp.create()
class TestMyApp(MyTestCase):
   def test_get_message(self):
      doc = {'message': 'Hello world!'}
      result = self.simulate_get('/')
      self.assertEqual(result.json, doc)
if '__name__'=='__main__':
   unittest.main()

Run the above test with the help of the following command −

python -m unittest test-myapp.py
F
==============================================================
FAIL: test_get_message (test-myapp.TestMyApp)
--------------------------------------------------------------
Traceback (most recent call last):
   File "E:\falconenv\test-myapp.py", line 17, in test_get_message
   self.assertEqual(result.json, doc)
AssertionError: {'message': 'Hello World'} != {'message':
'Hello world!'}
- {'message': 'Hello World'}
? ^
+ {'message': 'Hello world!'}
? ^ +
--------------------------------------------------------------
Ran 1 test in 0.019s
FAILED (failures=1)

Using Pytest

To perform testing using PyTest framework, you need to install it using PIP utility.

pip3 install pytest

To run a test function, we need an object of testing.TestClient class. It simulates the requests for WSGI and ASGI applications. This object is first obtained by giving Falcon application object as the argument.

We run the simulate_*() functions and assert its result with the anticipated output to decide whether the test has failed or passed. In both the examples, the test fails because of difference in case of 'W' in Hello World message. The responder returns it with uppercase 'W' whereas the test function has it in lowercase.

from falcon import testing
import pytest
import myapp
@pytest.fixture()
def client():
   return testing.TestClient(myapp.create())
def test_get_message(client):
   doc = {'message': 'Hello world!'}
   result = client.simulate_get('/')
   assert result.json == doc

Run the above test using the following command −

pytest test-myapp.py –v
=========== test session starts ==========================
platform win32 -- Python 3.8.6, pytest-7.1.2, pluggy-1.0.0 --
e:\falconenv\scripts\python.exe
cachedir: .pytest_cache
rootdir: E:\falconenv
plugins: anyio-3.5.0
collected 1 item
test-myapp.py::test_get_message FAILED
[100%]
==================== FAILURES =======================
_____________________________________________________
test_get_message
_____________________________________________________
client = <falcon.testing.client.TestClient object at 0x0000000003EAA6A0>
def test_get_message(client):
   doc = {'message': 'Hello world!'}
   result = client.simulate_get('/')
> assert result.json == doc
E AssertionError: assert {'message': 'Hello World'} ==
{'message': 'Hello world!'}
E Differing items:
E {'message': 'Hello World'} != {'message': 'Hello world!'}
E Full diff:
E - {'message': 'Hello world!'}
E ? ^ -
E + {'message': 'Hello World'}
E ? ^
test-myapp.py:42: AssertionError
============ short test summary info ==================
FAILED test-myapp.py::test_get_message - AssertionError:
assert {'message': 'Hello World'} == {'message': 'Hello
world!'}
============ 1 failed in 4.11s ========================
Advertisements