17

I have noticed during integration testing that I actually work on recurring use cases with restful APIs (or in general HTTP interfaces) I check here and there with bash+cURL.

It starts looking quite messy and gets harder to maintain. Why deliver mess?

Typical use cases are:

  • Check that an URL returns http response code e.g. 200
  • Check that content type matches some MIME you need in that case
  • Check that returned content matches some pattern, or passes an abstract validation procedure

What I have found so far and consider a workable option without reinventing the wheel, is:

  • have a go with PyCurl - in a hope it fully implements all cURL options esp. proxying but also other switches I might need
  • use Python's built in unit testng

Then I could have, for example, one unit test per service I'd like to check:

import unittest, pycurl

class TestService (unittest.TestCase):

    def test_1(self):
        self.assertEqual(pycurl.returncode("some_url"), 200)

    def test_2(self):
        self.assertTrue(pycurl.response("some_url").matches ("xxx") )

    def test_3(self):
        self.assertTrue (pycurl.ContentType("some_url").equal("xxx"))

if __name__ == '__main__':
    unittest.main()

Does this make sense or is there a more high-level (but not too complex to pick up and integrate) tooling?

Dan Cornilescu
  • 6,780
  • 2
  • 21
  • 45
Ta Mu
  • 6,792
  • 5
  • 43
  • 83

1 Answers1

9

You could look at tools such as Postman which focuses on testing REST APIs with JavaScript - it has some nice features but you lose the use of Python.

Instead, I'd suggest looking at REST-related plugins for pytest, a Python test framework that simplifies your test code, while still running tests written using unittest.

Pytest has a huge set of plugins that simplify various tasks, including:

  • Tavern, which specialises in testing REST APIs and seems highly relevant here - sort of "Postman for Python unit tests".

  • pytest-curl-report - when testing with the requests library, will print a curl command you can use to reproduce the error from shell.

  • Testinfra - focuses on server testing (e.g. state of OS packages, files, processes, etc, usually tested on remote servers) - strongly recommended if you also need this type e.g. to test Ansible code.

    • For those who use Puppet or Chef, Testinfra is similar to Beaker (with RSpec), ServerSpec or InSpec.

If you don't like Tavern, you can of course use pycurl with pytest, which makes it easier to diagnose exactly what failed. This example from the pytest-curl-report site uses only generic pytest features:

$ py.test test.py
============================= test session starts ==============================
platform darwin -- Python 2.7.9 -- py-1.4.27 -- pytest-2.6.4
plugins: curl-report, httpbin, cache, capturelog, cov, flakes, pep8
collected 1 items

test.py F

=================================== FAILURES ===================================
______________________________ test_requests_get _______________________________

    def test_requests_get():
        r = requests.get('http://httpbin.org/get')
>       assert False
E       assert False

test.py:7: AssertionError

Pytest lets you write all tests with a plain assert, and optionally include a helpful message as part of the output. For example, one of your tests could be written:

def test_2():
    assert pycurl.response("some_url").matches ("xxx"), "xxx not found in response"
RichVel
  • 902
  • 6
  • 16