DEV Community

Cover image for Serenity automation framework - Part 1/4 - Automation Test with API
cuongld2
cuongld2

Posted on • Edited on

Serenity automation framework - Part 1/4 - Automation Test with API

When building an automation framework from scratch, the major big thing to consider is how to choose an existing library/framework to support us. (Yes you could create automation framework without the support of any existing library/framework, but it takes a lot of time and resources).

So the framework we choose to use should have the following features:

  • Support different kinds of testing (API, UI, mobile..)
  • Support parallel testing (to reduce the time to execute tests)
  • Integrate with other test management tools (Testrail for example)..

As per my experience, the best match framework for Python is pytest(currently working in this in my current job), for Java is Serenity.

In this tutorial series, I will show you how to get started using with Serenity.

Alt Text

You all can find out about serenity in serenity/thucydides

Its previous name is thucydides, later changed to Serenity ( I heard somewhere they said for better pronunciation).

In short, Serenity is like a wrapper of Selenium, but also support dealing with API. Their philosophy is about BDD, and they introduce new design pattern for screen-play (which I think is better understanding and maintenance if we apply correctly).

Also, their creator(John Fergurson) said that using Serenity can create live documentation for the features we are testing. (I always think that it's hard to document about the features as there will be a lot of changes, updated.. so the philosopy of Serenity looks good to me).

That's it for the short introduction.
In this first blog post for Serenity, I will show quick example how to test API.

I. Create some APIs to test:

For the guideline how to create API, please follow this tutorial Create Gamelist API with Spring and Tomcat

To run the application, simply run : "mvn tomcat7:run"

II. Implement API tests using Serenity:

1.Create new maven project:

I usually doing Java code with IntelliJ ( I'm a big fan of Jetbrains product anyway :)) )

You can code in Eclipse, Netbeans or anything you like

To create new project in IntelliJ: Go to File -> New -> Project -> Maven

Alt Text

After that, you name your groupd-ID, artifact ID with anyname you want.

Alt Text

Finish after you name the project

2.About pom file:

POM file is where you store the information about the library or plugin you might be using.

The POM file will look like this:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>donald</groupId>
    <artifactId>serenity-guideline</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <properties>
        <serenity.maven.version>2.0.71</serenity.maven.version>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/net.serenity-bdd/serenity-rest-assured -->
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-rest-assured</artifactId>
            <version>${serenity.maven.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.13.2</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20190722</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/uk.co.datumedge/hamcrest-json -->
        <dependency>
            <groupId>uk.co.datumedge</groupId>
            <artifactId>hamcrest-json</artifactId>
            <version>0.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>uk.co.datumedge</groupId>
            <artifactId>hamcrest-json</artifactId>
            <version>0.2</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jooq/jool -->
        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>jool</artifactId>
            <version>0.9.14</version>
        </dependency>
    </dependencies>


</project>

```



We need to declare the serenity restassured libs (since we are testing API).

You might checkout more information about restassured in [here](http://rest-assured.io/)

Besides dependency about serenity-restassured, we will use other for setting up the util for assertion, parse model object <-> json.

Tips: In IntelliJ, you can choose enable auto-import for maven project, so that when you add new dependencies, it will apply to the project immediately for better coding experience.

3.Test project structure:

We will have package main and test

In main :
 java: we will implement common utils( write soft assertion, parse object) and call API function

Call the API to create new game



````javascript

import common.CoreConstant;
import io.restassured.response.Response;
import models.features.gamelist.Game;
import common.ApiUtil;
import static net.serenitybdd.rest.SerenityRest.given;

public class CreateNewGameApi {

    public Response createNewGame(Game gameInput) {

        return given().baseUri(CoreConstant.GAMELIST_HOST + CoreConstant.GAMELIST_API)
                .header("Content-Type", "application/json")
                .body(ApiUtil.parseObjectToJSON(gameInput, Game.class))
                .when()
                .post();
    }

}

```
{% endraw %}

All the information about url, api_path will be stored in CoreConstant class

For the body part input of the API, I already create ApiUtil to deal with parsing between object and json.
You only need to create model class for the Game item
{% raw %}


````javascript
public class Game {

    private Integer id;
    private String title;
    private String author;

    public Game() {
    }

    public Integer getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}
```


CoreConstant class we will use typesafe function.
It will read the information in automation.env.conf depends on which env we are using



````javascript

public class CoreConstant {

    private static Config conf;

    static {
        conf = Configs.newBuilder()
                .withResource("automation.conf")
                .withResource("automation." + Env.get().getName() + ".conf")
                .build();
    }

    public static final String GAMELIST_HOST = conf.getString("localhost.url");
    public static final String GAMELIST_API = conf.getString("gamelist.api");


}

```
{% endraw %}



 resources: we will store automation.conf and automation.local.conf for config information about app_url and api_url


We need to separate local vs other env such as dev, sit, uat...
In the future, if you want to implement for other envs,you can create configuration file like automation.dev.conf..

In test:
 java: we will implement the tests using jUnit
{% raw %}


````javascript

public class CreateNewGameTest extends BaseTest {

    private CreateNewGameApi createNewGame = new CreateNewGameApi();
    private Game gameInput = new Game();

    @Test
    public void test_create_game_success(){
        gameInput.setId(10);
        gameInput.setAuthor("Donald");
        gameInput.setTitle("Serenity Demo");

        Response response = createNewGame.createNewGame(gameInput);
        softAssertImpl.assertThat("Response code must be 200", response.statusCode(), 200);
        softAssertImpl.assertThat("Text response must be like : Game created with id",response.getBody().asString().contains("Game created with id"), true);
        softAssertImpl.assertAll();
        response.prettyPrint();

    }

}



```



Serenity also supports using Cucumber and screenplay pattern but since we only test API so I think no need to implement that.

The demo using Cucumber and screenplay will be in section 2 and 3, since I will demo with GUI testing.

4.Run the test

To run the test from IDE, simply click on run button:
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/j81yqsik42hmustetoiz.png)

Or you can run from command line:
mvn test

As usual, you can refer to the source code in github.
Here is the repo [serenity-guidelines](https://github.com/cuongld2/serenityguideline)

5.Practice:
In this tutorial, I did not cover about testing the modify game item API and delete item API.

Take these two as practices if you like.

Next tutorial I will cover about testing GUI using Serenity

Please like or comment if you like. It would mean a lot to me.
Peace!!!

Notes: If you feel this blog help you and want to show the appreciation, feel free to drop by :

[<img src="https://thepracticaldev.s3.amazonaws.com/i/cno42wb8aik6o9ek1f89.png">](https://www.buymeacoffee.com/dOaeSPv
)

This will help me to contributing more valued contents.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)