Python Falcon 简明教程

Python Falcon - Testing

Falcon 的测试模块是 Falcon 应用程序的功能测试框架。它包含各种测试类和实用程序函数,以支持功能测试。测试框架同时支持 unittestpytest

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.

我们将使用以下脚本 ( myapp.py ) 来演示测试功能。它包含一个 HelloResource 类,其中包含一个 on_get() 应答者,该应答者呈现一个 Hello World 的 JSON 响应。 create() 函数返回 Falcon 的 Application 对象,其中添加了一个使用 '/' URL 注册的路由。

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

testing.TestCase 扩展了 unittest ,以方便对使用 Falcon 编写的 WSGI/ASGI 应用程序进行功能测试。我们需要从这个基类继承并编写测试。

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.

TestCase 子类中的测试函数的名称为 simulate_ (),其中 *' '* 表示 HTTP 方法,例如 GET、POST 等。这意味着我们必须获取 simulate_get() 函数的结果,并通过断言函数将其与预期结果进行比较。

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.

simulate_ ()* 函数接收两个参数。

The simulate_()* functions receive two arguments.

simulate_*(app, route)

以下是 test-myapp.py 的代码。它执行 simulate_get() 函数并将其结果与预期结果进行断言,并指示测试是否失败或通过。

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

要使用 PyTest 框架进行测试,你需要使用 PIP 实用程序安装它。

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

pip3 install pytest

要运行 test 函数,我们需要一个 testing.TestClient 类的对象。它模拟 WSGI 和 ASGI 应用程序的请求。这个对象首先通过将 Falcon 应用程序对象作为参数来获取。

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.

我们运行 simulate_ ()* 函数并断言其结果是否与预期输出一致,以确定测试是否失败或通过。在这两个示例中,测试都失败了,因为 Hello World 消息中的“W”不同。应答者返回大写“W”,而测试函数中有小写“W”。

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 ========================