Skip to content

Lippia-io/lippia-api-sample-project

Repository files navigation

LIPPIA API Example Project

Purpose

The following project has the purpose of demonstrate and let test automation developers to test API requests by using Lippia Automation Framework based on Rest Client library. This sample project includes the required components as binaries, docker containers and configuration files to simply download and run a set of sample tests in your local computer, using the Lippia container stack.

System Requirements:

Getting started

Reports Integrations

We believe that the reports should express the results of our tests in the most legible, detailed and pleasant way possible, so that in this way, our clients have at their disposal a report on the operation and behavior of their product, as well as the performance of the team. This example offers different reporting outoputs:

  • Cucumber Reporting Pretty Console Output: this reporter ius useful to see log execution in console output, in the IDE and in the CI/CD pipeline output.
  • Lippia Test Manager a solution that combines Manual and Automation tests results in a single platform. To know more see Lippia.io
  • ExtentReport a community solution for simple reports. To know more see Extent Reports documentation

Cucumber Reporting Pretty Console Output

By default this project uses Cucumber Reporting plugin with console output. This plugin shows results in plain console that is useful for development environments and CI-CD pipelines.

Pretty console Output

Lippia Test Manager

This integration uses an adaptar that automatically ingests results of Scenarios into Lippia Test Manager. You just simply need to implement LTM-adapter-cucumber4-JVM and you can see the results in Lippia Test Manager as an Automated Run Result.

To configure your automation project to inject results into LTM, you should do the following things:

  • Include property reference ${test-manager.report} in cucumber options (pom.xml)
  • To set following properties, you need obtain an account in LTM (visit the web https://www.lippia.io/ to start free trial account)
  • Properties:
    • TEST_MANAGER_API_HOST: https://example.com
    • TEST_MANAGER_RUN_NAME: id run in project
    • TEST_MANAGER_PROJECT_CODE: id project to inject test execution results
    • TEST_MANAGER_USERNAME: username Account LTM
    • TEST_MANAGER_PASSWORD: password Account LTM

Runs List

Run Automated Result sample

Extent Reports Integration

Reports are generated in the folder called target, which will be generated once the execution of the test suite is finished.
Note that the following structure is part of the report generated with ExtentReport library after running the test project using the Extent plugin. Results report can be found at lippia-api-sample-project/target/reports/index.html

index.hmtl sample

Project structure

A typical Lippia Test Automation project usually looks like this

	.
├── main
│   ├── java
│   │   └── com
│   │       └── crowdar
│   │           └── api
│   │		 └── config
│   │ 	         |    └── EntityConfiguration.java
│   │            └── model
│   │               │   └── Data.java
│   │               │   └── ResponseHeaders.java
│   │		    │	└── User.java
│   │               │   └── UserCreated.java
│   │               │   └── Users.java
│   │               └── services
│   │                   └── ResponseHeadersService.java
│   │                   └── UserService.java
│   └── resources
│       ├── config.properties
│       ├── cucumber.properties
│       └── log4j.properties
└── test
    ├── java
    │   ├── ApiExampleProjectParallelTestRunner.java
    │   ├── ApiExampleProjectTestRunner.java
    │   └──
	└── steps	
	│   └── ResponseHeadersSteps.java
	│   └── UserSteps.java
	└── apiExampleProject
    │           └── Hooks.java
    └── resources
        └── features
            └── ApiExample.feature
		└── jsons
	└── jsons
            └── request
	    	└── createUser.json
		└── errorRequest.json
		└── exampleJson.json
		└── responseHeadersRequest.json
	    └── response
	    	└── responseHeadersResponse.json

Folder's description:

Path Description
main\java\...\examples\model\*.java Folder with all the Mapped Objects matching steps with java code
main\java\...\examples\config\*Steps.java Folder with all the Settings wich match with Gherkin Test Scenarios
test\resources\features\*.feature Folder with all the feature files containing Test Scenarios and Sample Data
test\resources\request\*.json Folder with all the json files containing Request data
test\resources\response\*.json Folder with all the json files containing Response data if necessary
main\resources Folder with all configuration needed to run Lippia

In this example, ApiExample is the first endpoint the framework will interact with. The steps defined in UserSteps.java to execute the Test Scenarios defined in Gherkin language.

File Description
User.java Model: you can declare every attribute expected on the responses that you want to interact with. You need to add one new file for each response you want to model in your tests.
UserSteps.java StepOpject: Code to support the behaviour of each step coded into the feature files for the User endpoint. This code executes the interaction between the Framework and the api endopoint and match the steps with the code who run interactions.
ApiExample.feature Feature file: Definition of the Test Scenarios with all the steps written in Cucumber format (http)

Project type options:

  • The project type option allows the user to say Lippia which library will need to download. For this project is set the API one that only have all library needed for this kind of project. This option can be changed in the pom.xml file
    You can get more information checking the README file from lippia-core project.
├── config.properties
        ├── base.api.url = urlBase
        |   └── This option allows the user to say Lippia which urlBase would need to perform requests
        |
        ├── crowdar.projectType = API
        |
        └── crowdar.api.entityConfiguration = api.config.entityConfiguration
            └── This option allows the user to say Lippia where to look for the defined constants or entities
                (note that java folder is ignored, the path must be specified from the java child folder)

Json Structure for request data

This project use json to manage request data like url parameters, body data, headers and url endpoints. The following picture shows the structure of the json

Lippia Scenarios Example API

Runners


├── lippia-api-sample-project
│   ├── docs
│   │   └── ...
│   ├── src
│   │   ├── main
│   ├── java
│   │     └── ...
│   ├── resources 
│   │     └── ...
│   ├── test
│   │     ├── resources
│   │     │ └── ...
│   │ 
│   ├── pom.xml
│   ├── testngParalell.xml
│   ├── testng.xml
│          
│  

The test cases are executed using TestNG class. This class is the main entry point for running tests in the TestNG framework. By creating their own TestNG object and invoke it on a testng.xml.

Attribute Description
name The name of this suite. It is a mandatory attribute.
verbose Whether TestNG should run different threads to run this suite.
parallel Whether TestNG should run different threads to run this suite.
thread-count The number of threads to use, if parallel mode is enabled (ignored other-wise).
annotations The type of annotations you are using in your tests.
time-out The default timeout that will be used on all the test methods found in this test.

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="BDD Test Suite" verbose="1" parallel="tests" thread-count="1" configfailurepolicy="continue">
    <test name="Login and Update Profile Test" annotations="JDK" preserve-order="true">
        <classes>
            <class name="ApiExampleProjectTestRunner"/>
        </classes>
    </test>
</suite>

testngParalell.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="BDD Test Suite" verbose="1" parallel="methods" data-provider-thread-count="10" thread-count="10" configfailurepolicy="continue">
    <test name="Test 1" annotations="JDK" preserve-order="true">
        <classes>
            <class name="ApiExampleProjectParalellTestRunner"/>
        </classes>
    </test>
</suite>

This file captures your entire testing and makes it easy to describe all your test suites and their parameters in one file, which you can check in your code repository or e-mail to coworkers.

pom.xml

A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project. It contains default values for most projects. Examples for this is the build directory, which is target; the source directory, which is src/main/java; the test source directory, which is src/test/resources; and so on. When executing a task or goal, Maven looks for the POM in the current directory. It reads the POM, gets the needed configuration information, then executes the goal.

How to select Sequential or Paralell Runner:

Sequential Runner:

  • In the pom.xml file, it looks for the POM in the current directory and assign the value of testng.xml.

  • This would be as follows:

        <apiExample.runner>testng.xml</apiExample.runner>

Paralell Runner:

  • In the pom.xml file, it looks for the POM in the current directory and assign the value of testngParalell.xml

  • This would be as follows:

        <apiExample.runner>testngParalell.xml</apiExample.runner>

Key classes explanation

We recommend taking a look at the following classes before you start looking at the usage examples

Summary

If you want to know more about the use of the following classes, click on the link on your left and you will be redirected to a specific section of it.

Class Description
Request It´s used to set and get some attributes of the request
Response It´s used to set and get some attributes of the response
APIManager It´s used to set and get responses of the performed requests
MethodsService It´s where HTTP Methods are declared, It´s used to perform requests, and contains some methods for validations
Headers It´s used to set and get a list of headers
EntityConfiguration It´s where entities should be declared, and each declared constant should return a service

Gherkin examples using Codeless steps

JSON Assertions

Json obtained against json expected

Assertion 1, assertion of json obtained against json expected

Entities explanation

The EntityConfiguration class has located in config folder, and here, is where entities are declared. For example:

EntityConfiguration CLASS: (note that USER entity is declared here, and it returns UserService CLASS)

public enum EntityConfiguration {

    USER {
        @Override
        public Class<?> getEntityService() {
            return UserService.class;
        }
    };
    
    public abstract Class<?> getEntityService();
}

UserService CLASS: (note that it´s extended from MethodsService CLASS and here the HTTP Methods are declared, in UserService are declared some methods who will be called according to operation value defined for Examples in the Scenario. This method, which will receive 2 mandatory parameters: the json name and the model class to deserialize the response)

public class UserService extends MethodsService {

    public static Response get(String jsonName) {
        return get(jsonName, Data.class);
    }

    public static Response post(String jsonName) {
        return post(jsonName, UserCreated.class);
    }

    public static Response delete(String jsonName) {
        return delete(jsonName, null);
    }

}

Data composition

In the model examples you can mapped the expected objects from different api responses. We can show you a little example:

{
    "data": {
        "id": 2,
        "email": "janet.weaver@reqres.in",
        "first_name": "Janet",
        "last_name": "Weaver",
        "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
    }
}

So the model class will be something like this:

public class User {

    @JsonProperty("id")
    private int id;
    @JsonProperty("email")
    private String email;
    @JsonProperty("first_name")
    private String firstName;
    @JsonProperty("last_name")
    private String lastNamelast_name;
    @JsonProperty("avatar")
    private String avatar;

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getFirstName() { return firstName; }
    public void setFirstName(String first_name) { this.firstName = first_name; }
    
    public String getLastName() { return lastName; }
    public void setLastName(String last_name) { this.lastName = last_name; }
    
    public String getAvatar() { return avatar; }
    public void setAvatar(String avatar) { this.avatar = avatar; }
}

The idea is have one attribute per field to map on the response

Json obtained against json expected modified by some parameters

Assertion 5, assertion of json obtained against json expected modified by some parameters

It uses a override method called "validateFields", in this case, it receives 3 parameters: Object actual, Object jsonExpected, and a list of parameters
It works in the following way:

usersWithParams.json (note that first_name field contains a variable enclosed between {{}})
    {
        "data": {
            "id": 2,
            "email": "janet.weaver@reqres.in",
            "first_name": "{{name}}",
            "last_name": "Weaver",
            "avatar": "https://reqres.in/img/faces/2-image.jpg"
        }
    }

It´s sended to service class returned by entity defined, where:
UserService class contains:

    @Override
    public void validateFields(Object expected, Object actual, Map<String, String> parameters) throws Exception {
        Map<String, Object> expectedObjectMapped = MapUtils.convertObjectToMap(expected);
        Map<String, String> expectedData = (Map<String, String>) expectedObjectMapped.get("data");
        expectedData.replace("first_name", parameters.get("name"));

        validateFields(expected, actual);
    }

This code is an example of what we must do to make an assertion modifying values ​​of a json with parameters   
** Note that if you don't overwrite the validateFields function, the existing ones in MethodsService will be called by default **
[This overwrite is necessary, if you want to make assertions by modifying an expected json with parameters]

Json obtained against json mapped in the model class

Assertion 2, assertion of json obtained against json mapped in the model class

Json obtained is null

Assertion 3, validates that json obtained is null

Json obtained is an empty array

Assertion 4, validates that json obtained is an empty array

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published