简体   繁体   中英

How to test a Flask (non-route) function that processes a request, using pytest?

Context: I have two Flask routes which process the same request data (one interactively, one as an API). To keep my code DRY, I want to write a function process_post_request() that

  1. accepts the request as in input parameter from each route,
  2. parses the request,
  3. returns results which the routes can use.

For example, in views.py:

@app.route('/interactive', methods=['GET', 'POST'])
def interactive():
    if request.method == 'POST':
        sum, product = process_post_request(request)
        # present the results on a web page

@app.route('/api', methods=['GET', 'POST'])
def api():
    if request.method == 'POST':
        sum, product = process_post_request(request)
        # return the results so that JavaScript can parse them

def process_post_request(request):
    param1 = request.form.get('param1')
    param2 = request.form.get('param2')
    sum = param1 + param2
    product = param1 * param2
    return sum, product

Question: How can I write a pytest for process_post_request() ? The problem is that if I create a "request" and try to pass it to process_post_request() , the request goes to a route, so that route returns a result. For example, in views_test.py:

import pytest

@pytest.fixture
def client():
    """Create a client to make requests from"""
    with app.test_client() as client:
        with app.app_context():
            pass
        yield client

def test_process_post_request():
    request = client.post('/interactive', data={'param1': 5, 'param2': 7})
    sum, product = process_post_request(request)
    assert sum == 12

Because request returns a response, pytest throws this error:

>       request = client.post('/interactive', data={'param1': 5, 'param2': 7})
E       AttributeError: 'function' object has no attribute 'post'

I created an app route to return comma-separated parameters:

@app.route('/pass-through', methods = ['GET', 'POST'])
def pass_through():
    if request.method == 'POST':
        params = process_post_request(request)
        return ','.join(params)

Then tested that app route:

def test_process_post_request():
    with app.test_client() as client:
        response = client.post('/pass-through', data={'param1': 5, 'param2': 7})
        sum, product = response.data.decode().split(',')
        assert sum == 12

where decode() translates from bytes to string.

It's not the most satisfying solution because it really tests the app route, so it depends on the app route function pass_through() using the same parameter names as process_post_request() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM