Running end to end tests (Rest APIs)

Unit and integration tests are important to verify that isolated and integrated software modules are behaving as expected. Nevertheless, end to end tests (sometimes called system tests) are also important, because they allow to test the system as a whole, as seen for the end user. End to end tests are different from unit and integration tests because the SuT (Software under Test) is deployed in the same environment as in production.

To execute an end to end test in ElasTest, the SuT have to be declared explicitly. Then, any TJob can be associated to that SuT. In this way, the SuT can be managed independently the number of TJob executed against it.

Here we will run our JUnit5 Rest Test provided by default in ElasTest, which makes use of a rest application as a SuT and has a single test that is responsible for making a GET request to that Sut. This test has been developed in Java using JUnit5:

RestAppTest class

public class RestAppTest extends ElasTestBase {

    @Test
    public void rootServiceTest() {
        String appHost = System.getenv("ET_SUT_HOST");

        if (appHost == null) {
            appHost = "localhost";
        }

        RestTemplate client = new RestTemplate();
        String url = "http://" + appHost + ":8080/";
        logger.info("Send GET request to {}", url);
        String result = client.getForObject(url, String.class);

        assertThat(result).isEqualTo("Hello World!");
    }

}


ET_SUT_HOST variable will be the IP of our SuT. ElasTest will automatically inject the right value (Know more about Environment Variables)

In addition, as can be seen in the example, this test class extends a class called ElasTestBase which is responsible for printing logs at the beginning and end of each test. These two logs have a specific structure and are used by ElasTest to filter the logs corresponding to each test. We explain this in more detail here.

ElasTestBase class

public class ElasTestBase {

    protected static final Logger logger = LoggerFactory.getLogger(ElasTestBase.class);

    @BeforeEach
    public void logStart(TestInfo testInfo) {
        logger.info("##### Start test: " + testInfo.getTestMethod().get().getName());
    }

    @AfterEach
    public void logEnd(TestInfo testInfo) {
        logger.info("##### Finish test: " + testInfo.getTestMethod().get().getName());
    }

}


To Run "JUnit5 Rest Test" TJob you only need follow these steps:

1. Access your ElasTest dashboard
2. Get into "Rest API" project
3. Run the 'JUnit5 Rest Test' TJob
4. Execution screen is open automatically

Our TJob will start running: you will see the test information and log.

Once the test is finished you will see the test results and log. Eventually the test should end succesfully.

IMPORTANT: ElasTest make use of xml results file to get all the test results information.

You can click on the Test Suite to display it and see each of the Test Cases. You can also click on one of them to navigate to the information section of this Test Case, where you can see their logs filtered thanks to the two traces of logs that the class ElasTestBase prints at the beginning and end of each test and that we have commented above. There's only one in this TJob, so we'll navigate to this one (rootServiceTest):

You can click too on the View In LogAnalyzer button for navigate to Log Analyzer Tool and view the execution logs:

Or you can click on the View Case In LogAnalyzer button view the specific test execution logs:

If you want to create the TJob yourself, you only need follow these steps:

1. Access your ElasTest dashboard
2. Create a New Project

The Projects serve to organize the TJobs related to each other. You can create a new Project by clicking on the button with the same name. You only need to indicate the name of the project and then click on SAVE button:

Immediately you will be redirected to the project page:

3. Create a SuT

There are several ways to deploy a Sut in ElasTest, but they can be grouped in two ways:

  • Deployed by Elastest: your software is packaged as Docker container/s. It can be a single Docker image or a docker-compose.
    • With Commands Container: Your SuT is packaged as a Docker image. You must write the Commands Container Image and the commands that will run like the docker image CMD.
    • With Docker Image: Your SuT is packaged as a Docker image. ElasTest will pull it from DockerHub and run it as the Dockerfile states.
    • With Docker Compose: Your SuT is declared as a docker-compose. ElasTest will pull all the necessary images from DockerHub and run them as the field Docker Compose.
  • Deployed outside ElasTest: your software is already deployed somewhere.
    • No instrumentation: No monitoring traces sent to ElasTest.
    • Instrumented by ElasTest: Elastest will be responsible for accessing your Sut to send monitoring traces.
    • Manual Instrumentation: If you want to manually send its logs and metrics to ElasTest.
    • Use External Elasticsearch: if you use your own Elasticsearch to save the monitoring traces and you want ElasTest to access it to retrieve them.

You can read Software under Test for more detailed information about Sut.

In our case, we will need to insert the following data for create the SuT of "JUnit5 Rest Test" TJob:

  • SuT Name: can be called as you want, but we will call it Rest App
  • With Commands Container / With Docker Image / With Docker Compose: With Docker Image
  • Docker Image: image of the SuT (elastest/demo-rest-java-test-sut)
  • Wait for http port: which port of the SuT should ElasTest wait to be available before starting the TJob (8080)


4. Create a new TJob

When a TJob is created, the minimum information that you have to provide is the following:

  • TJob Name: name of the TJob
  • Select a SuT: If your TJob make use of a Software under Test. In this case, none.
  • Environment docker image: the docker image that will host your test. This docker images should contain a client to download your code from your repository hosting service. For example, if your tests are hosted in GitHub and implemented in a Maven project with Java, you need to include a git client, Maven and the Java Development Kit (JDK) in the image.
  • Commands: these are the bash commands to be executed to download the code from a repository and to execute the tests. The specific commands depends on the source code repository type and the technology.

In our case, we will need to insert the following data for the TJob "JUnit5 Rest Test":

  • TJob Name: can be called as you want, but we will call it JUnit5 Rest Test
  • Test Results Path: /demo-projects/rest/junit5-rest-test/target/surefire-reports. This is the complete path where the xml reports of the execution in the container will be saved. We explain this in more detail here.

  • Select a SuT: already created SuT to be tested through to the TJob (Rest App)

  • Environment docker image: elastest/test-etm-alpinegitjava (image that contains Git, Maven and Java).

  • Commands:
    git clone https://github.com/elastest/demo-projects;
    cd /demo-projects/rest/junit5-rest-test;
    mvn -B test;
    

By clicking on SAVE the TJob will be saved and you will be redirected to the project page again, where you will be able to execute the TJob.

5. Run the TJob from the Project's page

In this example, when the TJob is executed, the following steps are performed:

  1. SuT is executed starting the docker container elastest/demo-rest-java-test-sut
  2. ElasTest waits until container has a http service available in port 8080
  3. When service is ready, the test container elastest/test-etm-alpinegitjava is started and specified commands are executed on it.
  4. The test implemented in /demo-projects/rest/junit5-rest-test maven project is executed. This test makes a http request to a Rest endpoint in the SuT and verifies that current result is the expected one.
  5. When the test container finishes, ElasTest stops the SuT and TJob containers.

The following examples, also offered by default in ElasTest, are implemented with different technologies:

Java JUnit4 Python JS Jasmine Java Karate
You can view the Source Code in GitHub. This test has been developed in Java using JUnit4.
RestAppTest class

public class RestAppTest extends ElasTestBase {

    @Test
    public void rootServiceTest() {
        String appHost = System.getenv("ET_SUT_HOST");

        if (appHost == null) {
            appHost = "localhost";
        }

        RestTemplate client = new RestTemplate();
        String url = "http://" + appHost + ":8080/";
        logger.info("Send GET request to {}", url);
        String result = client.getForObject(url, String.class);

        assertEquals("Hello World!", result);
    }

}


ElasTestBase class

public class ElasTestBase {

    protected static final Logger logger = LoggerFactory.getLogger(ElasTestBase.class);

    @Rule
    public TestName name = new TestName();

    @Before
    public void logStart() {
        logger.info("##### Start test: " + name.getMethodName());
    }

    @After
    public void logEnd() {
        logger.info("##### Finish test: " + name.getMethodName());
    }

}

TJob Configuration
  • TJob Name: can be called as you want, but we will call it JUnit4 Rest Test
  • Test Results Path: /demo-projects/rest/junit4-rest-test/target/surefire-reports
  • Select a SuT: Rest App
  • Environment docker image: elastest/test-etm-alpinegitjava
  • Commands:
        
        git clone https://github.com/elastest/demo-projects;
        cd /demo-projects/rest/junit4-rest-test;
        mvn -B test;
        
    
You can view the Source Code in GitHub. This test has been developed in Python.
TestRest class


import unittest
import os
import sys
import xmlrunner
import ElasTestBase
import requests


class TestRest(ElasTestBase.ElasTestBase):
    def test_root_service(self):
        sutUrl = ElasTestBase.sutUrl
        print 'Send GET request to ' + sutUrl
        response = requests.get(sutUrl)
        self.assertEqual(response.content, 'Hello World!')


if __name__ == '__main__':
    file_path = './testresults'
    if not os.path.exists(file_path):
        os.makedirs(file_path)
    file_name = file_path + '/results.xml'
    with open(file_name, 'wb') as output:
        unittest.main(
            testRunner=xmlrunner.XMLTestRunner(output=output),
            failfast=False, buffer=False, catchbreak=False)


ElasTestBase class

import unittest
import os

sutUrl = None
class ElasTestBase(unittest.TestCase):
    def setUp(self):
        global sutUrl
        testName = self._testMethodName
        print '##### Start test: ' + testName
        sutIp = '172.17.0.3'
        if('ET_SUT_HOST' in os.environ):
            sutIp = os.environ['ET_SUT_HOST']

        sutUrl = 'http://' + sutIp + ':8080'

    def tearDown(self):
        testName = self._testMethodName
        print '##### Finish test: ' + testName

TJob Configuration
  • TJob Name: can be called as you want, but we will call it Python Rest Test
  • Test Results Path: /demo-projects/rest/python-rest-test/testresults
  • Select a SuT: Rest App
  • Environment docker image: elastest/test-etm-alpinegitpython
  • (Alpine image with Git and Python)
  • Commands:
        
        git clone https://github.com/elastest/demo-projects;
        cd /demo-projects/rest/python-rest-test;
        python RestTest.py;
        
    
You can view the Source Code in GitHub. This test has been developed in Javascript using Jasmine.
rest-test-spec.js

var request = require('request');
config = require('./elastest-conf.js');

describe('Rest Test', function() {
    it('Root Service Test', function(done) {
        console.log('Send GET request to ' + config.sutUrl);

        request.get(config.sutUrl, function(error, response, body) {
            expect(body).toEqual('Hello World!');
            done();
        });
    });
});


elastest-conf.js

var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(
    new jasmineReporters.JUnitXmlReporter({
        consolidateAll: true,
        savePath: 'testresults',
        // this will produce distinct xml files for each capability
        filePrefix: 'xml-report',
    }),
);

var reporterCurrentSpec = {
    specStarted: function(result) {
        console.log('##### Start test: ' + result.description);
    },
    specDone: function(result) {
        console.log('##### Finish test: ' + result.description);
    },
};

jasmine.getEnv().addReporter(reporterCurrentSpec);

module.exports = {
    sutUrl: process.env.ET_SUT_HOST ? 'http://' + process.env.ET_SUT_HOST + ':8080' : 'http://172.17.0.3:8080',
};


TJob Configuration
  • TJob Name: can be called as you want, but we will call it Jasmine Rest Test
  • Test Results Path: /demo-projects/rest/jasmine-rest-test/testresults
  • Select a SuT: Rest App
  • Environment docker image: elastest/test-etm-alpinegitnode
  • (Alpine image with Git, Node, and necessary libraries like jasmine)
  • Commands:
        
        npm install --save request;
        git clone https://github.com/elastest/demo-projects;
        cd /demo-projects/rest/jasmine-rest-test;
        jasmine;
        
    
You can view the Source Code in GitHub. This test has been developed in Java using Karate .
root-service-test.feature

Feature: Test a Sut 

Scenario: Navigate to url and obtain 200 response 
    Given  url appUrl 
    When   method get 
    Then   status 200 
Scenario: Navigate to url and obtain 500 response 
    Given  url appUrl 
    When   method get 
    Then   status 500 


RestAppTest class

@RunWith(Karate.class)
public class RestAppTest {
}


karate-config.js

function() {   

  // Log start and finish every scenario
  karate.log('##### Start test:',karate.info.scenarioName);
  karate.configure("afterScenario",function(){
      karate.log('##### Finish test:',karate.info.scenarioName);
  });

  var host = java.lang.System.getenv('ET_SUT_HOST');
  if(!host) {
      host = "localhost"
  }
  var url = "http://" + host + ":8080";
  var config = {
    appUrl: url
  };

  return config;
}

TJob Configuration
  • TJob Name: can be called as you want, but we will call it Karate Rest Test
  • Test Results Path: /demo-projects/rest/karate-rest-test/target/surefire-reports
  • Select a SuT: Rest App
  • Environment docker image: elastest/test-etm-alpinegitjava
  • Commands:
        
        git clone https://github.com/elastest/demo-projects;
        cd /demo-projects/rest/karate-rest-test;
        mvn -B test;