• 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 (7)

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

24.04.2023

Marathon vs. sprint: two concepts to reach a goal

In our software development process, we are used to doing sprints. Now two of our team members took part in the London and Vienna City Marathons. They share their experiences and draw parallels between sports and software development.

23.03.2023

From Bitpanda to AURENA: Oliver Tulla joins as Frontend Lead

AURENA Tech strengthens its frontend team and is happy to welcome Oliver Tulla, formerly working for Bitpanda, as a Lead Developer.

06.03.2023

AURENA Tech Winter Games 2023

In our latest team activity, we came together for a fun day in the Austrian mountains.

02.03.2023

“QA needs to be part of the software development lifecycle from the start”

Our QA lead Tatjana Statescu explains how we established a comprehensive QA process at AURENA Tech, what our testing strategy looks like, and discusses the key factors for a successful quality assurance team.

19.12.2022

Design and Build Efficient GraphQL

How we make use of Typegraphql, Field Resolver, and Dataloaders.

Open positions

AURENA.tech
text
Junior Quality Assurance Engineer (f/m/x)

In this role, you will conduct regression and exploratory tests for our mobile and desktop web applications.

  • Leoben or fully remote
  • Fulltime, permanent
  • Starts at € 37,800 p.a.
AURENA.tech
text
Senior QA Automation Engineer (f/m/x)

In this role, you will responsible to enhance our automated test coverage, create and execute test plans.

  • Leoben or fully remote
  • Fulltime, permanent
  • Starts at € 51,800 p.a.
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 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 € 60,200 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 € 60,200 p.a.