Sunday, June 18, 2017

Filtering and Querying JSON for Tests

When I'm developing an API, I write unit tests along the way to test smaller portions of my application. In addition to having unit tests, I like to add an integration test (or smoketest). The point of this integration test is to exercise the APIs endpoints as maybe a customer would.

I write a simple shell script that calls the endpoints and verifies responses. My goal is to create a smoketest script that is easy to use and maintain so I can quickly test out endpoints. This kind of script can also be used to test an application when an update has been deployed.

I'm experimenting with using curl and jq in my smoketest script to parse JSON, and I would like to share here a few fun ways to test responses from APIs.

The simplest way to use curl and jq together is to send a request with curl then format the json response with jq. The Cocktail DB has an nice API we can use for simple testing (please be nice and don't bombard their API with requests!). So let's try getting a random cocktail recipe:

curl http://www.thecocktaildb.com/api/json/v1/1/random.php

OK. Notice that it's hard to read the JSON response. Let's now take that same request and pipe the response output to jq like this:

curl http://www.thecocktaildb.com/api/json/v1/1/random.php | jq .

Wow - so much nicer! Using jq to reformat the response makes it easier to visually inspect the JSON.

Now let's check the HTTP response code that is returned. The option -w '%{http_code' will print just the HTTP response code. The rest of the output is redirected to /dev/null, and the result is stored in the shell variable STATUS:

STATUS=$(curl -so /dev/null -w '%{http_code}' ${COCKTAIL_DB_API}/random.php)

Next, let's count the number of Vodka drinks in the database. To do this, we're going to use the jq built-in function length. When you look at the JSON in the response, you see that the field drinks is an array of drinks. Here is the shell code that gets the number of Vodka drinks:

COUNT=$(curl -s ${COCKTAIL_DB_API}/filter.php\?i\=Vodka | jq '.drinks | length')

When I looked at the JSON response, I noticed that a drink has these fields:

  • strDrink
  • strDrinkThumb
  • idDrink
Some of the thumbnails are null. We can count the number of drinks with null thumbnails using jq's select. Select only the drinks where strDrinkThumb is null, create an array of those drinks, and get the length of the array. Here's how I did it in my shell script:

NULL_THUMBNAIL_COUNT=$(curl -s ${COCKTAIL_DB_API}/filter.php\?i\=Vodka | jq '[.drinks[] | select(.strDrinkThumb == null)] | length')

You might use this in a test to verify that no drinks have null thumbnails.

These examples are in the script cocktail-db-tests.sh in my repository https://github.com/annawinkler/api-tests.

While working out these examples,  I found this site helpful for debugging my jq filter https://jqplay.org/ and the jq manual a great reference https://stedolan.github.io/jq/manual/. Sometimes I need to diff json, and I like to use this online tool for that: http://www.jsondiff.com/.