Nowadays, no developer would dare to release an API without tests. But writing API tests is time consuming and painful. We will see in this article how we can do so without pain.
Source code for examples of this article are available in this Github project.
If you Google golang api testing, you will find articles to unit test your API with Go. Let’s consider following API:
We could test it with a unit test as follows:
In this code we perform following tasks:
- Instantiate server
- Build a recorder to record request response
- Execute request
- Make following assertions:
1) Response status code must be 200
2) Response body contents must be valid JSON with expected message
This is quite a tedious code to write, uncreative and error prone.
It would be much simpler and faster to describe request and response, in YAML format for instance, as follows:
- Far simpler to write
- Less error prone
- More explicit
To test what happens when calling an unknown URL we could write:
Once more, this could be replaced to your benefit, with:
These request and response descriptions in YAML format are, pretty much, integration test files in Venom test format for Tavern executor.
Source for these tests are:
We can run these tests with following command line:
These are integration tests as we test the whole application, as opposed to unit tests that test an isolated piece of code. One could think that we could thus do without unit tests. This is plain wrong, unit and integration tests are complementary.
Achieving tests this way allows you to cover far more error cases. Time you save testing this way may be invested in covering all expected status codes. Furthermore, these tests are a way to document your API in a legible way.
Downside of integration tests is that it is often quite difficult to measure code coverage. This is easy to measure code coverage for Go unit tests, but nothing is provided for integration tests.
Fortunately, it is possible to use tools that measure unit tests coverage for integration tests. The trick is to run server and Venom tests in a unit test. When tests are finished, Go has measured code coverage and it is possible to generate a report.
This is what we do in following test:
Function WaitServer() waits for server to start without calling any specific route. Another trick in this code is to add integration compilation tag in source header. This way, this source will be compiled only if indicating compiler to process this tag, with -tag integration option.
We can run this test and generate coverage report with following command lines:
This will produce an HTML report as follows:
Of course, this sample report is not so impressive, but it is very useful for large projects to track code that is not covered with integration tests and thus tells tests you must write to check uncovered error cases.