Testing Rest API services in Java can be complex if the appropriate tools are not used, even more so if they are automated. Indeed, these tests focus on the requests and responses generated and must test a series of aspects.
Here’s a detailed explanation of testing and verifying a Rest API with Cucumber. Before that, let’s discuss what Cucumber is and other related concepts!
What is API Rest?
An API (Application Programming Interface) is a set of rules and protocols that allow communication between software applications. Now, REST (Representational State Transfer) originated in 2000 and was described in Roy Fielding’s thesis. In effect, API Rest is an application programming interface that conforms to the REST architecture style.
In other words, API REST defines a set of functions to make requests (Request) and receive responses (Responses) through the HTTP protocol under client-server architecture.
Indeed, REST API uses HTTP methods (HTTP verbs) to make requests, and each one has a particular function.
- GET is used only to query information.
- POST is used to request the creation of a new record (supports payload).
- PUT is used to update an existing record (supports payload) completely.
- PATCH, similar to the PUT method, allows updating only a fragment of the record and not its entirety (it supports payload).
- DELETE is used to remove an existing record.
- HEAD is used to obtain information about a given resource without returning the record.
- OPTIONS allow you to describe the communication options for the target resource.
The HTTP status codes (HTTP Status code) briefly describe the response obtained in the requests. These are:
- 1XX Informational responses
- 2XX Correct requests
- 3XX Redirects
- 4XX Client Errors
- 5XX Server Errors
What is Cucumber?
It is a tool that allows you to run functional descriptions in plain text as automated software tests. Cucumber implements the Behavior Driven Development methodology (BDD or Behavior Driven Development), where the tests are written first before the source code.
In this sense, the language used by Cucumber for these functional descriptions is called Gherkin.
What is Gherkins?
It is defined as a Domain Specific Language that humans and computers can understand. To define functional descriptions, we need five reserved words to build our tests:
- Feature indicates the name of the functionality that we are going to test. Include a description in the form of a user story “As [role] I want [ feature ] so [ benefits ].”
- Scenario Describes each scenario we will test; different scenarios must be tested for the same functionality.
- Given provides context for the scenario as the point where the test is run and prerequisites on the data.
- When Specifies the set of actions that launch the test and the user interaction that triggers the functionality we want to test.
- Then Specifies the expected result in the test to make our checks.
Cucumber does not distinguish these keywords, but they make the feature more consistent and readable with the BDD structure.
In order for the above to be better understood, let’s implement an example to test and verify Rest API, using the Cucumber and the BDD methodology.
We will initially download and install Java and Gradle as the dependency manager.
- Java 11
- Gradle 5.6.4
On the other hand, we need a client capable of making requests to the Rest API, such as Postman, to obtain as much information as possible. It is essential to mention that Postman is much more than a rest client; but it can help us do the previous analysis.
Additionally, we can use the IDE of our choice, but Intellij IDEA has enough to carry out the tests in its free version.
IntelliJ IDEA 2020.2.2 Community
We will use Cucumber with Gherkin to perform the tests, so it is very important to install two plugins in IDE, which will help us format Gherkin code and generate java code. These are:
- Cucumber for Java
Likewise, environment variables must be added for Java and Gradle. In the case of Windows, it would look like this.
- JAVA_HOME=C:\Program Files\Java\jdk-11.0.8
- GRADLE_HOME =C:\gradle-5.6.4
After that, we verify by executing the commands in the console.
SIN 54151S Analyst$90.93
SIN 54151S IT Consultant$81.12
SIN 518210C Cloud Senior Microservices Consultant$129.41
Public REST API
To do our tests, we will use restapiexample.com, which provides a public test Rest API. It does not present authentication because it is a test API, but in any other project, it does, so it must be implemented later.
Indeed, it will allow us to register, update, list, and delete employees.
- Get all employees
- Get employee by Id
- Create new employee
- Update employee by Id
- Delete employee by Id
In the first instance, we will explore and test these APIs with Postman. Once this is done, there is more detail on the services mentioned.
Creating the Project
Intellij IDEA Community will be enough to implement and run our automated tests, so we create a new Java Gradle project.
Dependencies and the build.Gradle
The necessary dependencies are specified in the build.Gradle file and the task that will run the tests and generate the report is established.
To be able to execute requests and handle responses to a Rest API, we add.
- rest-assured v4.3.1
- rest-assured-common v4.3.1
- json-path v4.3.1
- json-schema-validator v4.3.1
Likewise, we will write the tests in Gherkin language to be executed by Cucumber.
- JUnit v4.12
- cucumber-java v1.2.5
- cucumber-JUnit v1.2.5
On the other hand, it will be extremely useful to view reports about the execution of our tests, so we added.
- cucumber-reporting v5.3.1
Creating the Clientapi Package
In the clientapi package, we will create classes capable of making requests to any API. To do this, we make use of classes provided by rest-assured.
POST, PUT, DELETE, and GET type requests have similar behavior but somewhat different implementations. In this sense, the Factory design pattern is useful on this occasion where the IRequest.java describes the behavior of the requests.
With the help of RestAssured, the implementation of the requests is greatly simplified, but the interesting thing is to follow a Given – When – Then format. However, for this example, we will not exploit this potential much more than to make requests to an Endpoint with a particular Payload.
The FactoryRequest.java will be in charge of manufacturing our requests in a more organized way without having redundant code.
Creating the util Package
The useful package only contains the JsonUtils.java class. It has useful functions for basic operations on strings in JSON format that we will use in our tests.
By Creating the Test Feature
The resources package houses all of our .feature files representing the Gherkins language tests. In this sense, the EmployeesAPI.feature means the tests that we will do with restapiexample.com.
Next, we make the description in Gherkin language, where a scenario to be tested is described, the HTTP method to be used, and the Endpoint and the necessary Payload. The corresponding verification is carried out in the status code and the expected response at the end of each test.
Note that there are properties in the response that are dynamic, like the ID, that are difficult to be evaluated, so we indicate that they are EXCLUDE and will ignore them thanks to our implementation in JsonUtils.java
- TEST Delete Employee
- TEST Update Employee
- TEST List Employee
- TEST List Employees
Once this is implemented, the Steps Definitions are created that have our tests’ source. The plugins we install in the IDE will help us generate source code.
Creating the Runner Package
The runner package is in charge of running the tests and is where the step definitions are added. In this sense, the StepDefinitions.java is where the executed tests are implemented, closely related to the EmployeesAPI.feature
The idea of StepDefinitions.java is to program each of the Given-When-Then written in the tests and give them functionality. However, many of these repeat or have very similar patterns that you can organize. Thus, we can simplify and optimize the code thanks to regular expressions, avoiding renunciation.
The RunnerCucumber.java is the main class for our tests where you get used to implementing hooks (@Before/@After), but they won’t be necessary.
To run our tests, we run the following command, which has the task of running the automated tests for all scenarios with the @Regression tag.
Likewise, the report.json is also generated when the tests are finished. This can be used as a data source to use report templates and see a better organized and clean presentation. To do this, in the package runner, we add the ReportGenerator.java class with the following instructions.
Finally, we independently execute the last class created to generate a report in HTML format. Now we can view the reports from any web browser.
We can see that applying a BDD methodology using Cucumber to execute functional descriptions with Gherkin is interesting, but it applies a new layer in development. However, it is a good way to implement API tests that can be customized and implemented on average, even though tools such as Postman could do almost the same but are limited to their structure.
Further blogs within this API testing with Cucumber category.