Services are usually acessed using APIs. REST APIs are common both in internal services and in public facing services.
Whenever testing REST APIs, we can either be targetting the client/consumer or the server/producer.
In this tutorial we'll show how a REST API can be tested using Java and the REST Assured library, together with JUnit and WireMock.
REST Assured is a Java library that implements a DSL for easily validating REST API based services by abstracting low-level details of HTTP requests and of parsing responses.
It provides a syntax based on Gherkin (i.e. given, when, then) for better readibility.
From REST Assured documentation, imagine that you have a REST based service accessibile in the
endpoint, and returning a JSON content. }
A JUnit test to check that the HTTP response code is OK (i.e. 200) and that the "lotto" object returned is correct, could be something as follows.
This takes advantage of the JsonPath, a simple JSON parser (there's also an equivalent for XML: XmlPath).
If required, it's also possible to perform JSON Schema validation.
REST Assured concepts
In REST Assured it's all about being able to quickly perform HTTP REST requests and to verify the response easily, no matter if it's JSON or XML based.
Main concepts include:
- request specification - the definition of the request (e.g. URL, authentication, etc); the object RequestSpecification is usually specified using given() and when().
- response specification - the definition of the response (e.g. body, status code); the object ResponseSpecification is usually specified using then()
- parser - an entity responsible for processing and abstract the body content of the response, so that data can easily be referred in the matchers/assertions
- matchers - used to match either built-in ones (io.restassured.matcher.RestAssuredMatchers.*) or from Hamcrest (org.hamcrest.Matchers.*).
Note: it's possible to reuse request specifications or response specifications between multiple requests/responses for different tests (more info here). This can be extremely useful if you need to perform a set of common assertions (e.g. status code being OK) for a bunch of tests.
We aim to test a service that provides an API (i.e. http://api.zippopotam.us/) to obtain location data based on postal/zip codes on several countries.
The workshop provides some exercises, stored under src/test/java/exercises; it also provides the answers.
As an example, lets implement a test for checking that the API returns the correct state, in the correct order, for a given zip code of US.
Another variant of it could be performing data-driven testing to check the returned "state" for a set of input data (e.g. country+zip code).
We'll see ahead how this specific data-driven test will be mapped to Jira.
Tests can be run using Maven; in this case, we'll be only executing the ones inside the "answers" package.
Since the previous command generates multiple JUnit XML files, we may need to merge them into a single XML file so it can be submitted into a Test Execution more easily. That can be achieved by using the junit-merge utility.
After successfully running the tests and generating the aggregated JUnit XML report (e.g., merged-test-results.xml), it can be imported to Xray (either by the REST API or through the Import Execution Results action within the Test Execution, or even by using a CI tool of your choice).
In case you need to interact with Xray REST API at low-level using scripts (e.g. Bash/shell scripts), this tutorial uses an auxiliary file with the credentials (more info in Global Settings: API Keys).
Each JUnit's test is mapped to a Generic Test in Jira, and the Generic Test Definition field contains the name of the package, the class and the method name that implements the Test Case. The summary of each Test issue is filled out with the name of the method corresponding to the JUnit Test.
The Execution Details page also shows information about the Test Suite, which in this case corresponds to the Test class, including its namespace.
In the case of data-driven tests, as the JUnit XML report treats each row of the data provider as a different "test case", then you'll end up with several Tests in Xray.
- Multiple runs of your tests can be grouped and consolidate in a Test Plan, so you can have an updated overview of their current state
- After importing the results, you can link the corresponding Test issues with an existing requirement or user story and thus truck coverage directly on the respective issue
- REST Assured Usage Guide
- Bas Dijkstra open-source workshop on REST Assured
- Bas Dijkstra blog entry about WireMock