Introduction to concise and expressive REST API testing framework — WebTau
Tags: restapi, java, groovy, testing
Published: 2019-05-28 20:57:00

---
title: Introduction to concise and expressive REST API testing framework — WebTau
published: true
description: 

series: webtau
cover_image: https://thepracticaldev.s3.amazonaws.com/i/l4lgznn8kqip0urv2k11.png
tags: rest api, java, groovy, testing
---

# Introduction


[Webtau](https://github.com/twosigma/webtau) (short for **web** **t**est **au**tomation) is a tool and API to write expressive and concise REST API tests.

Let’s start with a simple get-weather example. You have a server that returns a current temperature every time you hit `/weather` end point.

```json
{
  "temperature": 88
}
```

I want to write a simple test to validate that a temperature I receive is lower than 100 Fahrenheit. Here is a webtau test script.

```groovy
scenario("simple get") {
    http.get("/weather") {
        temperature.shouldBe < 100
    }
}
```

`temperature.should` expression gets automatically mapped to the server response and triggers validation against `temperature` value.

To run the test, execute `webtau webtau-simple-get.groovy` command line.

If a command line and standalone scripts is not your cup of tea, you can use JUnit and similar runners.

```groovy
package com.example.tests.junit4

import com.twosigma.webtau.junit4.WebTauRunner
import org.junit.Test
import org.junit.runner.RunWith

import static com.twosigma.webtau.WebTauGroovyDsl.*

@RunWith(WebTauRunner.class) // required for html report generation only
class WeatherGroovyTest {
    @Test
    void checkWeather() {
        http.get("/weather") {
            temperature.shouldBe < 100
        }
    }
}
```

I am using Groovy for testing for the last decade and I think it is perfect for the job. But if you are not a Groovy fan, you can use Java or other JVM languages.

```java
package com.example.tests.junit4;

import com.twosigma.webtau.junit4.WebTauRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

import static com.twosigma.webtau.WebTauGroovyDsl.*;

@RunWith(WebTauRunner.class)
public class WeatherJavaTest {
    @Test
    public void checkWeather() {
        http.get("/weather", (header, body) -> {
            body.get("temperature").shouldBe(lessThan(100));
        });
    }
}
```

# CRUD example

Let’s complicate the example and test the full Create, Read, Update, Delete cycle.

```groovy
scenario("CRUD operations for customer") {
    def customerPayload = [firstName: "FN", lastName: "LN"]

    def id = http.post("/customers", customerPayload) {
        return id // return id value from response body
    }

    http.get("/customers/${id}") {
        body.should == customerPayload // only specified properties will be asserted against
    }

    def changedLastName = "NLN"
    http.put("/customers/${id}", [*:customerPayload, lastName: changedLastName]) {
        lastName.should == changedLastName // specifying body is optional
    }

    http.get("/customers/${id}") {
        lastName.should == changedLastName
    }

    http.delete("/customers/${id}") {
        statusCode.should == 204
    }

    http.get("/customers/${id}") {
        statusCode.should == 404
    }
}
```

Note how test is very data focused and tries to minimize the data management boilerplate by re-using the initial payload as response expectation.

It the test above all CRUD operations are part of the same test. Below is the example of the separating CRUD operations into their own tests.

```groovy
def customerPayload = [firstName: "FN", lastName: "LN"]

def customer = createLazyResource("customer") { // lazy resource to be created on the first access
    def id = http.post("/customers", customerPayload) {
        return id
    }

    return new Customer(id: id, url: "/customers/${id}") // definition is below
}

scenario("customer create") {
    customer.id.should != null // accessing resource for the first time will trigger POST (in this example)
}

scenario("customer read") {
    http.get(customer.url) { // convenient re-use of url defined above
        body.should == customerPayload
    }
}

scenario("customer update") {
    def changedLastName = "NLN"
    http.put(customer.url, [*:customerPayload, lastName: changedLastName]) {
        lastName.should == changedLastName
    }

    http.get(customer.url) {
        lastName.should == changedLastName
    }
}

scenario("customer delete") {
    http.delete(customer.url) {
        statusCode.should == 204
    }

    http.get(customer.url) {
        statusCode.should == 404
    }
}
```

```groovy
class Customer {
    Number id
    String url // store url of the created entity
}
```

Example above is using a `lazyResource` concept to make each test to be self contained. I.e. if I just want to run `delete` test, a resource will still be created. On the other hand if I run all CRUD tests, there will be only one `post`.

# Reporting

One of the time consuming tasks maintaining tests is figuring out what when wrong when a test fails. Webtau provides comprehensive console output as well as a rich, self contained html report.

![](https://thepracticaldev.s3.amazonaws.com/i/upde7rinfewv4n6pv9dt.png)

Note that asserted values are highlighted inside the console output. Failures are highlighted in a similar manner

![](https://thepracticaldev.s3.amazonaws.com/i/1s9jy0861nomzzum2adh.png)

At the end of the tests run you will be given a location of html report

![](https://thepracticaldev.s3.amazonaws.com/i/wadca4ijbdelbg9ydf1j.png)

# Open API, UI Testing, matchers and more

There are a lot more features I want to cover. There is Open API integration for tracking coverage, there is web UI testing parts of webtau that let you create comprehensive tests of your app. There are powerful matchers and data management techniques. Integration with JUnit5.

While I am tempted to cover them now I think dedicated posts may help to focus on one feature at a time.

If you have questions or suggestions, please leave a comment here or create an issue on [github](https://github.com/twosigma/webtau).

# Getting Started

[To get started follow the official docs.](https://twosigma.github.io/webtau/guide/)