Testing United Conference: Unleashing the Power of AI in QA
QA Engineer Iana and her colleague Sara report their insights from the latest Testing United Conference with the main topic “AI Augmented QA".
03.05.2021
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.
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.
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:
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:
{
.
.
.
"scripts": {
"test": "jest",
"test-smoke": "jest --group=smoke",
},
.
.
.
}
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:
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:
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) },
});
}
To run tests just execute
npm run test-smoke
And here is the result: