• 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

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.

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

12.04.2021

Our approach to Gitlab runners

Until recently our engineering team was exclusively using Gitlab shared runners for our CI/CD pipelines. While they did (and partly still do) get the job done, recent outages have made us aware of how critical functioning CI/CD is to us in our day-to-day work.

23.09.2020

Welcome aboard: Meet QA lead Tatjana Statescu

QA is a cornerstone to ship reliably working products that exceed user expectations. Tatjana is going to build up our competence center to bring quality assurance at AURENA Tech to the next level.

27.04.2020

IaC: AWS CDK vs. Terraform

If you are interested in the difference between IaC tools, check out our comparison of AWS CDK and HashiCorp Terraform.

12.03.2020

Meetup: Confident Angular testing and insights into Ivy

#AngularGraz goes Leoben: Great talks and helpful insights in Angular Ivy and Testing in Angular, hosted at the AURENA Tech office.

03.03.2020

From Apple to AURENA: Matt Pearce joins digital unit

To accelerate the expansion course, AURENA is bringing the recruiting and IT specialist Matt Pearce from Great Britain into the team.