• bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
  • bids: 0 +10
  • bidders: 0 +10
  • completed auctions: 0 +10
  • next fall of the hammer: 0 ending now
  • sold lots: 0 +10
Job openings (4)

03.05.2021

Smoke Testing with Jest and GraphQL

One important capability in our QA strategy is to run smoke tests against remote service endpoints, to check that they are healthy. In this article, we share our approach, walking you through some examples.

written by Tatjana Statescu

When it comes to implementing our QA strategy, one important capability is our ability to run smoke tests against remote service endpoints, to check that they are healthy. This provides us quick feedback after each deployment.

We implement our health checks as GraphQL endpoints, and we use Jest to test them from a CI/CD pipeline. In this article, we share our approach, walking you through some examples.

Why Jest?

Jest is a JavaScript testing framework that focuses on simplicity. Our Unit tests are also written in Jest, so it is easy to write and maintain API tests in the same format.

Setting up Jest

First of all, let’s install Jest:

                npm install --save-dev jest
            

To run tests easily and control the configuration, we create a jest.config.js file. It is possible to use the Jest command line runner and pass options as flags, but for convenience reasons Jest allows to use configuration file in JSON, TypeScript, and JavaScript format.

Here is our Jest config:

jest.config.js
                module.exports = {
  testEnvironment: "node",
  runner: "groups",
  reporters:  ["default", "jest-junit"],
  extraGlobals: [],
  testTimeout: 10000,
};
            

We use “groups” test runner. it allows us to use tags in the tests and execute specific groups of tests with Jest.

Since we want to have a possibility to see individual test results, which can be also interpreted by our CI/CD pipeline we use jest-junit which produces a JUnit format result file.

We add a shortcut script to execute smoke tests to the package.json file:

package.json
                {
.
.
.
"scripts": {
    "test": "jest",
    "test-smoke": "jest --group=smoke",
  },
.
.
.
}
            

The health check test

First to make it clearer what we are talking about here’s an approximate architecture that we are testing:

Here, we have two API Gateway services that are in front of two business services. The API Gateways provide a specific API for a particular use case, and the business services give general functionality. We need to ensure that the entire API a Facade service gives is available.

Let’s create a test folder and the test case:

                mkdir tests
cd tests
            

We also need to install Axios HTTP client to allow performing HTTP requests:

                npm install axios
            

And to make requests to the GraphQL server we need a GraphQL client, for that let’s install apollo-boost:

                npm install apollo-boost graphql cross-fetch
            

And finally the test case. The example given illustrates a microservice architecture with API Gateways in front of the various services:

tests/healthcheck.test.js
                import axios from 'axios'
import 'cross-fetch/polyfill';
import { getGraphQLClient } from './utils/getGQLClient';
import { getBaseUrl, getAPIGatewayDNSUrl } from './utils/environment'
import { SERVICE2_HEALTHCHECK } from './fixtures-healthcheck'
 
axios.defaults.adapter = require('axios/lib/adapters/http')
 
let url
 
beforeAll( async () => {
    url = {
        base: {},
        APIGatewayDNS: {}
    }  
    url["base"]["postcode-lookup"] = await getBaseUrl('postcode-lookup')
    url["base"]["vat-validator"] = await getBaseUrl('vat-validator')
    url["APIGatewayDNS"]["postcode-lookup"] = url["base"]["postcode-lookup"]
    url["APIGatewayDNS"]["vat-validator"] = await getAPIGatewayDNSUrl('vat-validator')
});
 
/**
 * System smoke tests
 * @group smoke
 */
describe('Tests health check endpoints', () => {
    it.each(['postcode-lookup', 'vat-validator'])('should receive OK from service 1 through %s API Gateway', async (module) => {  
        const response = await axios.get( url.base[module] + '/api/v1/healthcheck')
          .catch(function (error) {
            console.log(error);
          });
          expect(response.status).toBe(200);
          expect(response.data.healthy).toBeTruthy;
        });
    it.each(['postcode-lookup', 'vat-validator'])('should receive OK from %s API Gateway', async (module) => {  
        const response = await axios.get( url.APIGatewayDNS[module] + '/healthcheck')
            .catch(function (error) {
            console.log(error);
            });
            expect(response.status).toBe(200);
            expect(response.data.healthy).toBeTruthy;
        });
    it.each(['postcode-lookup', 'vat-validator'])('should should receive OK from service 2 through %s API Gateway', async (module) => {  
        const client = getGraphQLClient(url.APIGatewayDNS[module] + '/'); 
        const response = await client.query({
            query: SERVICE2_HEALTHCHECK }
            );
            expect(response.data.healthcheck.healthy).toBeTruthy;
        });   
});
            

Some explanations on the code:

                it.each
            

is a great solution for data-driven tests, it allows us to write the test once and pass data in.

In the first test, we make simple GET calls to the /healthcheck endpoints of ‘service 1’. The request goes through both API Gateways to make sure the connection between the API Gateways and the service is also working. We use Axios HTTP client that allows us to make an HTTP request with node.js.

In the second test, we make GET calls to the /healthcheck endpoints of ‘postcode-lookup’ API Gateway and ‘vat-validator’ API Gateway endpoints.

In the third test, we make a GraphQL request using ApolloClient to test both API Gateway connection to ‘service 2’ and the health of ‘service 2’.

Here is how we set it up ApolloClient:

getGQLClient.js
                import ApolloClient from 'apollo-boost';
 
export const getGraphQLClient = (baseUrl) => {
  return new ApolloClient({
    uri: baseUrl + 'graphql',
    request: (operation) => {
      operation.setContext({
        timeout: 20000
      })
    },
    onError: (e) => { console.log(e) },
  });
}
            

Running smoke tests

To run tests just execute

                npm run test-smoke
            

And here is the result:

Article by
Tatjana Statescu

Tatjana is QA lead at AURENA Tech. “The only thing better than finding a bug early is preventing it entirely”: With this in mind, Tatjana makes sure that quality is built into all development stages.

More articles

20.04.2022

Let's break the Vegas rule

Our Scrum Master GO shares her insights and main take-aways from the Atlassian Team ´22.

28.02.2022

AURENA Tech strengthens its DevOps team

We welcome Junior DevOps Engineer Danijel Maraz as the newest member to the AURENA Tech team.

05.01.2022

Replay Your Event Streams for Fun and Profit

Event Sourcing, Stream Processing and CQRS.

20.12.2021

My conference experience: Agile Testing Days 2021

Our QA lead Tatjana shares her highlights and main takeaways when attending the Agile Testing Days 2021.

17.12.2021

Welcome onboard: The AURENA Tech team is growing

We are happy to welcome a new Scrum Master, Junior QA Engineer and UI Design Lead to the AURENA Tech team.

Open positions

AURENA.tech
text
Node.js Developer (f/m/x)

In this role, you will work on feature development and continuous improvement of our leading real-time auction platform.

  • Leoben or fully remote
  • Fulltime, permanent
  • Starts at € 48,500 p.a.
AURENA.tech
text
Senior React Developer (f/m/x)

Build new high-performance apps from scratch and develop new features for our leading real-time auction platform

  • Leoben or fully remote
  • Fulltime, permanent
  • Starts at € 58,800 p.a.
AURENA.tech
text
Senior Node.js Developer (f/m/x)

This role offers you the opportunity to lead middleware and microservice development at AURENA Tech.

  • Leoben or fully remote
  • Fulltime, permanent
  • Starts at € 58,800 p.a.
AURENA.tech
text
Senior Mobile App Developer (f/m/x)

Develop cross-platform native apps and progressive web apps from scratch.

  • Leoben or fully remote
  • Fulltime, permanent
  • Starts at € 58,800 p.a.