{"id":13776,"date":"2020-10-05T10:52:07","date_gmt":"2020-10-05T14:52:07","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=13776"},"modified":"2021-04-27T09:31:13","modified_gmt":"2021-04-27T13:31:13","slug":"testing-fastapi-endpoints-using-fastapi-testclient","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/testing-fastapi-endpoints-using-fastapi-testclient\/","title":{"rendered":"Testing FastAPI endpoints using fastapi.testclient"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">This post shows you an example of how to use <code>fastapi.testclient<\/code> provided by <a href=\"https:\/\/github.com\/tiangolo\/fastapi\">FastAPI<\/a>. This testclient will help anyone to write code level tests quickly.<br \/>\n<\/span><\/p>\n<hr>\n<h3>Background<\/h3>\n<p>Recently, we have developed an internal application using FastAPI. I thought to document a quick testing approach which may help software engineers to write test cases quickly. Here I have used <code>fastapi.testclient<\/code> instead of the <code>requests<\/code> module as I wanted to explore it.<\/p>\n<hr>\n<h3>The application under test<\/h3>\n<p>Our application under test is developed using FastAPI and exposes certain API endpoints which will be used to send skype messages to the predefined channels. I will be taking only one sample method the purpose of this blog.<\/p>\n<pre lang=\"python\">\r\nCULTURE_FILE = 'blah blah blah'\r\n\r\ndef get_messages_from_file(filename):\r\n    \"Return a list of culture related messages\"\r\n    lines = []\r\n    with open(filename, 'r') as fp:\r\n        lines = fp.readlines()\r\n\r\n    return lines\r\n\r\n@app.get(\"\/message\")\r\ndef get_message():\r\n    \"Return a random message\"\r\n    lines = get_messages_from_file(CULTURE_FILE)\r\n    message = random.choice(lines)\r\n\r\n    return {'msg':message.strip()}\r\n<\/pre>\n<p>Let us assume this code exists in a file called <code>main.py<\/code>. <\/p>\n<hr>\n<h3>Using fastapi.testclient<\/h3>\n<p>The testclient is a wrapper written using the requests module in Python, You will need to install the requests module to use test client. Our way of writing this test will involve the following steps:<\/p>\n<p>1. Create a Test client.<br \/>\n2. Get the response from the client using the exposed endpoint.<br \/>\n3. Assert the status code for the response as 200.<br \/>\n4. Assert the response for non-empty messages.<br \/>\n5. Assert the response for the correct message taken from the file.<\/p>\n<hr>\n<h5>1. Create Test client<\/h5>\n<p>Create a new file called <code>test_main.py<\/code> and add the following lines:<\/p>\n<pre lang=\"python\">\r\n\"\"\"\r\nTest for the main page using fastapi.testclient.\r\n\"\"\"\r\nimport os\r\nimport sys\r\nfrom fastapi.testclient import TestClient\r\nimport main\r\nfrom main import app\r\nsys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\r\n\r\n# Declaring test client\r\nclient = TestClient(app)\r\n<\/pre>\n<p>At this stage, we have imported the necessary modules and created test client. Note that we have imported <code>app<\/code>from the <code>main<\/code> and parsing that while creating test client.<\/p>\n<hr>\n<h5>2. Get the response from the client using the exposed endpoint<\/h5>\n<p>Now, within the <code>test_get_message()<\/code> method, create a response using exposed endpoint<\/p>\n<pre lang=\"python\">\r\n# Test for status code for get message\r\ndef test_get_message():\r\n    \"asserting status code\"\r\n    response = client.get(\"\/message\")\r\n<\/pre>\n<hr>\n<h5>3. Assert the status code for the response as 200<\/h5>\n<p>You can assert the response is showing status code as 200<\/p>\n<pre lang=\"python\">\r\nassert response.status_code == 200\r\n<\/pre>\n<hr>\n<h5>4. Assert the response for non-empty messages<\/h5>\n<p>This step will ensure that we don&#8217;t get an empty message before validating the actual message from the file. We will create new method <code>test_get_message_text()<\/code>.<\/p>\n<pre lang=\"python\">\r\n# Test for asserting random message is in the file\r\ndef test_get_message_text():\r\n    \"asserting random message is in the file\"\r\n    response = client.get(\"\/message\")\r\n    message = response.json()\r\n    assert message['msg'] != ''\r\n<\/pre>\n<hr>\n<h5>5. Assert the response for the correct message taken from the file<\/h5>\n<p>We will now check that message we got is really from the intended file. In this case <code>CULTURE_FILE<\/code><\/p>\n<pre lang=\"python\">\r\n# Test for asserting random message is in the file\r\ndef test_get_message_text():\r\n    \"asserting random message is in the file\"\r\n    response = client.get(\"\/message\")\r\n    message = response.json()\r\n    assert message['msg'] != ''\r\n    with open(main.CULTURE_FILE, 'r') as file_handler:\r\n        lines = [line.strip() for line in file_handler]\r\n    assert message['msg'] in lines\r\n<\/pre>\n<hr>\n<h3>Putting it all together<\/h3>\n<p>Here is how our test looks:<\/p>\n<pre lang=\"python\">\r\n\"\"\"\r\nTest for the main page using fastapi.testclient.\r\n\"\"\"\r\nimport os\r\nimport sys\r\nfrom fastapi.testclient import TestClient\r\nimport main\r\nfrom main import app\r\nsys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\r\n\r\n# Declaring test client\r\nclient = TestClient(app)\r\n\r\n# Test for status code for get message\r\ndef test_get_message():\r\n    \"asserting status code\"\r\n    response = client.get(\"\/message\")\r\n    assert response.status_code == 200\r\n\r\n# Test for asserting random message is in the file\r\ndef test_get_message_text():\r\n    \"asserting random message is in the file\"\r\n    response = client.get(\"\/message\")\r\n    message = response.json()\r\n    assert response.json()[\"msg\"] != ''\r\n    with open(main.CULTURE_FILE, 'r') as file_handler:\r\n        lines = [line.strip() for line in file_handler]\r\n    assert message['msg'] in lines\r\n<\/pre>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2020\/10\/fastapi_test_client_test_result.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2020\/10\/fastapi_test_client_test_result.png\" alt=\"\"><\/a><\/p>\n<hr>\n<p>If you are working on testing applications using FastAPI, do consider using fastapi.testclient for your tests. I hope this article would help you to build quick tests around test client.<\/p>\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>This post shows you an example of how to use fastapi.testclient provided by FastAPI. This testclient will help anyone to write code level tests quickly. Background Recently, we have developed an internal application using FastAPI. I thought to document a quick testing approach which may help software engineers to write test cases quickly. Here I have used fastapi.testclient instead of [&hellip;]<\/p>\n","protected":false},"author":28,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[43,253],"tags":[254,255],"class_list":["post-13776","post","type-post","status-publish","format-standard","hentry","category-api-testing","category-fastapi-testclient","tag-fastapi","tag-testclient"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/13776","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=13776"}],"version-history":[{"count":12,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/13776\/revisions"}],"predecessor-version":[{"id":14809,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/13776\/revisions\/14809"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=13776"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=13776"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=13776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}