简体   繁体   中英

How to test an endpoint exception using flask and pytest?

I have an endpoint that returns a list from my database. If something goes wrong along the way, I return an internal_server_error, which has 500 status_code and a message as a parameter.

def get_general_ranking():
    try:
        ranking_list = GamificationService.get_general_ranking()
        return basic_response(ranking_list, 200)
    except Exception as e:
        logging.error(str(e))
        cache.delete()
        return internal_server_error_response('Could not get ranking. Check log for reasons.')

I am implementing an unit test to this endpoint. So, right now, I have this implementation:

class TestGamificationController(unittest.TestCase):

    def setUp(self):
        """
        Function called when the class is initialized.
        """
        test_app = app.test_client()
        self.general_ranking = test_app.get('/v1/gamification/general_ranking')

    def test_endpoint_general_ranking(self):
        """
        Testing the endpoint '/v1/gamification/general_ranking'.
        """
        assert self.general_ranking.status_code == 200, "Wrong status code."
        assert len(self.general_ranking.json) > 0, "/v1/gamification/general_ranking is returning an empty list."
        assert self.general_ranking.content_type == 'application/json', "Wrong content_type"

But, as you can see below, when I run the test with coverage to check if I am covering 100% of my code, I get 75%. The missing lines are the exception ones.

---------- coverage: platform darwin, python 3.8.0-final-0 -----------
Name                                       Stmts   Miss  Cover   Missing
------------------------------------------------------------------------
api/controller/GamificationController.py      16      4    75%   18-21

Missing lines:

    except Exception as e:
        logging.error(str(e))
        cache.delete()
        return internal_server_error_response('Could not get ranking. Check log for reasons.')

How can I cover this exception too using pytest? Or should I use something else?

I see three possible fixes for this:

  1. Create a custom route in your app that just raises said exception.
  2. Programmatically add this custom route in your app when you start your tests.
  3. Move your global error handler function to its own file and ignore it from your coverage.

Now personally 1 is the easiest with just applying a debug/dev environment check that just throws a route not found error if it's off.

2 is doable if you use your Flask app factory to generate an app and generate the custom route all on the test execution although I'm not sure if this is enough to pass the AssertionError that Flask throws if you make any modification to its app routes after the first request is received. Which is usually the case when you instantiate your app on your conftest.py .

3 is kind of cheating I suppose.

Hope you got this sorted out. Would like to know how you solved this.

Update: The best way I've found in doing this is by using the sessionstart hook of pytest that runs before any tests. I use this to initialize the custom error endpoints. This approach works best since you won't have to pollute the codebase with test-specific logic.

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