Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test an API Client with Python?

I'm working on a client library for a popular API. Currently, all of my unit tests of said client are making actual API calls against a test account.

Here's an example:

def test_get_foo_settings(self):
    client = MyCustomClient(token, account)
    results = client.get_foo_settings()

    assert_is(type(results), list)

I'd like to stop making actual API calls against my test account.

How should I tackle this? Should I be using Mock to mock the calls to the client and response?

Also, I'm confused on the philosophy of what to test with this client library. I'm not interested in testing the actual API, but when there are different factors involved like the method being invoked, the permutations of possible return results, etc - I'm not sure what I should test and/or when it is safe to make assumptions (such as a mocked response).

Any direction and/or samples of how to use Mock in my type of scenario would be appreciated.

like image 467
doremi Avatar asked Feb 05 '13 21:02

doremi


People also ask

Can we test API using Python?

You can now add your own test cases and assertions to automate your API test cases. Hope this article helps you to get started with API automation testing using Python.

How do you test an API?

API testing flow is quite simple with three main steps: Send the request with necessary input data. Get the response having output data. Verify that the response returned as expected in the requirement.


1 Answers

I would personally do it by first creating a single interface or function call which your library uses to actually contact the service, then write a custom mock for that during tests.

For example, if the service uses HTTP and you're using Requests to contact the service:

class MyClient(…):
    def do_stuff(self):
         result = requests.get(self.service_url + "/stuff")
         return result.json()

I would first write a small wrapper around requests:

class MyClient(…):
    def _do_get(self, suffix):
         return requests.get(self.service_url + "/" + suffix).json()

    def do_stuff(self):
         return self._do_get("stuff")

Then, for tests, I would mock out the relevant functions:

 class MyClientWithMocks(MyClient):
     def _do_get(self, suffix):
          self.request_log.append(suffix)
          return self.send_result

And use it in tests like this:

def test_stuff(self):
    client = MyClientWithMocks(send_result="bar")
    assert_equal(client.do_stuff(), "bar")
    assert_contains(client.request_log, "stuff")

Additionally, it would likely be advantageous to write your tests so that you can run them both against your mock and against the real service, so that if things start failing, you can quickly figure out who's fault it is.

like image 174
David Wolever Avatar answered Sep 18 '22 13:09

David Wolever