Advanced testing - aivancioglo/RestTest GitHub Wiki

This page will help you to optimize your testing. But before be sure that you have read the basics.

Contents

Intro

Just imagine that you have a test scenario like here:

import com.github.aivancioglo.resttest.http.Response;
import org.junit.Test;

import static com.github.aivancioglo.resttest.http.OAuth1.*;
import static com.github.aivancioglo.resttest.http.RestTest.get;
import static com.github.aivancioglo.resttest.http.RestTest.post;
import static com.github.aivancioglo.resttest.http.StatusCode.OK;
import static com.github.aivancioglo.resttest.setters.Setters.body;
import static com.github.aivancioglo.resttest.setters.Setters.queryParam;
import static com.github.aivancioglo.resttest.verifiers.Verifiers.path;
import static org.hamcrest.Matchers.is;

public class DataTest {
    private Response response;

    @Test
    public void unoptimizedRestTest() {
        response = post("tools.com/data",
              consumerKey("consumerKey"),
              consumerSecret("consumerSecret"),
              token("token"),
              tokenSecret("tokenSecret"),
              body("{" +
                    "\"name\":\"RestTest\"," +
                    "\"language\":\"Kotlin\"" +
                    "}"));

        response.assertThat(OK);

        String id = response.path("id");

        response = get("tools.com/data",
              consumerKey("consumerKey"),
              consumerSecret("consumerSecret"),
              token("token"),
              tokenSecret("tokenSecret"),
              queryParam("id", id));

        response.assertThat(OK, "schemas/dataGetPositiveSchema.json",
              path("name", is("RestTest")),
              path("language", is("Kotlin")));
    }
}

As you can see, we are using the same endpoint few times. Each time we need to set the same main parameters for him, i. e. consumerKey, consumerSecret, etc. Lets optimize this test and make it several time sorter.

Variables

The first step - use less hardcoding. Create the Variables class which will contain all your constants:

public class Variables {
    public static final String HOST = "tools.com";
    public static final String CONSUMER_KEY = "consumerKey";
    public static final String CONSUMER_SECRET = "consumerSecret";
    public static final String TOKEN = "token";
    public static final String TOKEN_SECRET = "tokenSecret";
    public static final String REST_TEST = "RestTest";
    public static final String KOTLIN = "Kotlin";
}

Your own endpoint

Now you can create your own endpoint. It is one of the ways for test optimizing. Your endpoint allows you to send a request with predefined parameters. Use it to make your tests more sorter and readable. Let's create an endpoint Data:

import com.github.aivancioglo.resttest.http.Request;
import com.github.aivancioglo.resttest.http.Response;
import com.github.aivancioglo.resttest.setters.Setter;

import static com.github.aivancioglo.resttest.http.OAuth1.*;
import static com.github.aivancioglo.resttest.setters.Setters.host;
import static com.github.aivancioglo.resttest.setters.Setters.path;
import static io.restassured.http.Method.GET;
import static io.restassured.http.Method.POST;
import static project.Variables.*;

public class Data extends Request {
    public final static String GET_POSITIVE_SCHEMA = "schemas/dataGetPositiveSchema.json";
    public final static String POST_POSITIVE_SCHEMA = "schemas/dataPostPositiveSchema.json";

    private final String PATH = "/data";

    {
        set(
              host(HOST),
              path(PATH),
              consumerKey(CONSUMER_KEY),
              consumerSecret(CONSUMER_SECRET),
              token(TOKEN),
              tokenSecret(TOKEN)
        );
    }

    public Response get(Setter... setters) {
        return send(GET, PATH, setters);
    }

    public Response post(Setter... setters) {
        return send(POST, setters);
    }
}

Nice. You can update your test and compare the results:

public class DataTest {
    private Response response;

    @Test
    public void unoptimizedRestTest() {
        response = new Data().post(
              body("{" +
                    "\"name\":\"RestTest\"," +
                    "\"language\":\"Kotlin\"" +
                    "}"));

        response.assertThat(OK);

        String id = response.path("id");

        response = new Data().get(
              queryParam("id", id));

        response.assertThat(OK, GET_POSITIVE_SCHEMA,
              path("name", is(REST_TEST)),
              path("language", is(KOTLIN)));
    }
}

Payload

As you can see our test is smaller. But we still have a hardcoded body. To optimize it, let's create a payload that will allow us to serialize the java class to JSON. Create your payload:

import com.fasterxml.jackson.annotation.JsonProperty;

import java.io.Serializable;

public class DataPayload implements Serializable {

    @JsonProperty("name")
    private String name;

    @JsonProperty("language")
    private String language;

    public DataPayload(String name, String language) {
        this.name = name;
        this.language = language;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }
}

NOTE: Here we are using Jackson Project for serializing.

Now let's see how can we use it in our test. Create an instance of your payload with required parameters:

private DataPayload dataPayload = new DataPayload(REST_TEST, KOTLIN);

Set it into body setter:

response = new Data().post(
      body(dataPayload));

Now it will be automatically transformed to JSON. Nice!

Model

If you need to extract something from your response body, the best practice is using models. Let's create a model for our endpoint:

import com.github.aivancioglo.resttest.http.Model;

public class DataModel extends Model {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

We can use it to update our endpoint. Now our request methods in Data class will return model instead of a simple response:

public DataModel get(Setter... setters) {
    return send(GET, PATH, setters).as(DataModel.class);
}

public DataModel post(Setter... setters) {
    return send(POST, setters).as(DataModel.class);
}

After updating the endpoint class, we can use it in our test. Use DataModel class instead of a simple Response class:

public class DataTest {
    private DataModel dataModel;
    private DataPayload dataPayload = new DataPayload(REST_TEST, KOTLIN);

    @Test
    public void unoptimizedRestTest() {
        dataModel = new Data().post(
              body(dataPayload));

        dataModel.assertThat(OK);

        String id = dataModel.getId();

        dataModel = new Data().get(
              queryParam("id", id));

        dataModel.assertThat(OK, GET_POSITIVE_SCHEMA,
              path("name", is(REST_TEST)),
              path("language", is(KOTLIN)));
    }
}

Steps

The last best way to optimize our test is the steps. We can divide our test into parts by sense. The first step in our test is making the post request and extracting an id. Let's create the DataSteps class with the method, that making this:

import static com.github.aivancioglo.resttest.http.StatusCode.OK;
import static com.github.aivancioglo.resttest.setters.Setters.body;

public class DataSteps {
    public static String postToolAndGetId(DataPayload payload) {
        DataModel dataModel = new Data().post(
              body(payload));

        dataModel.assertThat(OK);

        return dataModel.getId();
    }
}

Now we can update our test:

@Test
public void unoptimizedRestTest() {
    String id = postToolAndGetId(dataPayload);

    dataModel = new Data().get(
          queryParam("id", id));

    dataModel.assertThat(OK, GET_POSITIVE_SCHEMA,
          path("name", is(REST_TEST)),
          path("language", is(KOTLIN)));
}

Great! Just compare with the beginning. Splendid difference!