Testing a WoT REST Device API with Postman

With THNG:STRUCTION, you can easily model and create REST APIs for embedded devices that follow the Web Of Things (WoT) way of communicating with each other, with interactions such as getting and setting properties, triggering actions and querying events. Now the first batch of modules support HTTP+JSON, to form REST APIs that are easy to comprehend, use and test. READMEs show test cases using curl, the well-known command line utility for running HTTP calls, such as so:

# querying a property
$ curl http://${DEVICE}/wot/properties/temp

# setting a property with a PUT call, input data and correct content-type
$ echo -n '{ "led": true }' | curl -X PUT -H 'Content-Type: application/json' -d @- http://${DEVICE}/wot/properties/led

# triggering an action with a POST call
$ echo -n '{ "name": "flashLed" }' | curl -X POST -H 'Content-Type: application/json' -d @- http://${DEVICE}/wot/actions

# querying the events
$ curl http://${DEVICE}/wot/events

Now, command line fu is not everybody's favorite, let's look at some other tools.

Tools around APIs

Web developers are likely to know and use some of the existing tools that are around already, such as these:

  • Swagger let's you model, generate and test REST APIs based on the OpenAPI specification,
  • RAML, the RESTful API Modeling Language, based on the RAML specification,
  • Postman, an API Development Environment, which supports from Swagger and RAML description formats,
  • ... and many more tools that exist in this context.

Regarding devices, network reachability is important when running tests against it. Unfortunately, device development and communication is kind of a "local" one with regard to the network you're. My device - if connected via Ethernet or WiFi for example - has a local IP and thus isn't on the internet. So web based services around API testing will not be able to communicate with it unless you start to tweak your network configuration with VPNs and dynamic DNS magic - or just use a local app for that.

Starting some tests using Postman

Postman is such as Application, installed locally on your desktop, cross-platform. It actually does not need a user registration, but some use cases are only available for registered user, because information is stored under one's account at Postman's service platform. For the more simple tests that follow, no registration is required.

Download Postman, install according to your platform's installation process and start the app. It kicks off with a window asking what to do. Besides Templates and predefined API integration, which require a registration, the "Create New" Tab has some basic building blocks. Hit "Request/Create a basic request":

New Tab

I'd like to test one of the examples i built before, using the THNG:STRUCTION generator. If you haven't already, try to follow along the MKR1000 sample or build your own model (takes only a minute :). Now back to Postman.

Within the option dialog, give the request a name, like "WoT test", and create a new collection. I created a new collection going by the same name, and hit "save". It should present you with a structured yet empty dashboard going by the name of "WoT Test":

Dashboard

Next i have to find the IP of my device. The sample device sketch prints out the IP address on Serial during setup, in my case 192.168.0.101. I'd like to declare this as a parameter. In the top right part is the Environment section there's a settings-like button, "Manage Environments". This is a good way to specify environment variables, such as my DEVICEIP:

Declare Device IP as environment variable

I need to select that environment as well (one can have multiple of these, which is good):

Select environments

Now it's time for the first request. I select GET as method, http://{{DEVICEIP}}/wot as the URL. Nice thing: Entering '{' as the marker for inline variables, a popup opens where i can select the variables i defined for the current environment. Ok, clicking on "Send" fires off the request, and my device answers. It gives back application/json as Content type, so Postman is able to pretty-print/format it in the box below, and i see the Thing API with properties, actions and events, great!

First request

The pane in the middle shows "Authorization" by default, which i don't need, so i switch it to "Headers", which uses less space. Next request :) I click "+" within the tab section at the top to start with a new request, because i want to know about the current temperature, using GET to http://{{DEVICEIP}}/wot. Easy:

Current Temperature

Now, the API offers a property "threshold", which is writable. This is done using a PUT request, sending JSON to the right URL. I copy the URL, create a new tab, select "PUT" and paste in the identical URL, changing "temp" to "threshold" at the end. Now, some json is needed. I switch to the "Headers" pane and add a "Content-Type" being "application/json", which is nicely selectable after a few keystrokes. A body is needed, so i switch the middle pane to "Body", entering:

{ "threshold": 22.0 }

after selecting "raw" as the type. Hit "Send" and not much happens? The body is empty, but the status code on the right side says it: "201 created". This means that the device understood it, otherwise it would have returned an HTTP error code such as "500". A new GET request to the same URL shows the threshold i just set:

PUT to threshold

GET to threshold

Testing APIs made easy

So Postman makes it really easy to communicate with a WoT device for testing purposes, debugging etc. But still a very manual task. The middle pane has a tab called "Tests". I go back to the first Request tab where i queried the Thing Description. Clicking on the "Tests" tab allows me to enter Javascript code which is executed after the request. To the right, a number of snippets are shown. I want to ensure that the Thing Description really is of type "thing", so i choose:

pm.test("WoT Thing is of Type Thing", function () {
    var td = pm.response.json();
    pm.expect(td.type).to.eql("thing");
});

Clicking on "Send" again executes the request and the Javascript snippet and shows the result in the lower pane under "Test Results":

JS-based Tests

Now that is really neat! It will allow us to have full test cases for devices based on a WoT API. Ok, somewhen in the future :)

So much for today!

I only scratched the surface here of what Postman can actually do with APIs, but it's a good starting point. IoT devices are likely going to have APIs in the future, if they're open and documented, one can do a lot with it. And this is a good tool to get into the testing mood :)