Skip to content

Commit

Permalink
Adds performance tests for supported endpoints (#451)
Browse files Browse the repository at this point in the history
* added a basic performance test for v4 establishments and trusts

* added a basic performance test for v4 establishments and trusts

* Move perf scripts to v4 folder

* Adds basic performance tests for other supported endpoints in v1, 2 and 3

* Set baseUrl as env var, add README for perf tests

* Remove redundant perf scripts

* Move repeated functions to utils, set api key at runtime

---------

Co-authored-by: mikestock-nimble <mike.stock@nimbleapproach.com>
  • Loading branch information
cshnimble and mikestock-nimble authored Jan 24, 2024
1 parent a7bc32f commit a042d30
Show file tree
Hide file tree
Showing 9 changed files with 369 additions and 0 deletions.
28 changes: 28 additions & 0 deletions Dfe.Academies.Performance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Academies API Performance tests

This directory holds the performance test scripts for the Academies API.

Tests are written for the [k6](https://k6.io) performance testing tool.

## Setup

You will need k6 installed to be able to run these tests. Details on how to do so are available in their [documentation](https://grafana.com/docs/k6/latest/get-started/installation/).

## Configuration

The variables you will need to set are defined below:

| Variable | Description | Example |
|---|---|---|
| `API_KEY` | The API key used in headers for requests | `app-key` |
| `BASE_URL` | The url of the service to be tested | `https//localhost:5001` |

## Running the tests

To run an individual script, navigate to the correct directory and run

`k6 run -e API_KEY=<your-value> -e BASE_URL=<your-value> <your-script-name>`

## Results

By default, metrics are output to the console at the end of the tests, including any checks that are run as part of the test scripts.
14 changes: 14 additions & 0 deletions Dfe.Academies.Performance/scripts/utils/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { check } from 'k6'

export function isStatus200(res) {
check(res, {
'status is 200': (r) => r.status === 200,
})
}

export function getHeaders() {
return {
'ApiKey': `${__ENV.API_KEY}`,
'Content-Type': 'application/json'
}
}
25 changes: 25 additions & 0 deletions Dfe.Academies.Performance/scripts/v1/keyStagePerformance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import http from 'k6/http'
import { check, sleep } from 'k6'
import { isStatus200, getHeaders } from '../utils/utils.js'

export const options = {
vus: 20,
duration: '30s'
}

const baseUrl = __ENV.BASE_URL

export default function () {

getEducationPerformanceByUrn('100000')

sleep(1)
}

function getEducationPerformanceByUrn(urn) {
const res = http.get(`${baseUrl}/educationPerformance/${urn}`, {
headers: getHeaders()
})

isStatus200(res)
}
26 changes: 26 additions & 0 deletions Dfe.Academies.Performance/scripts/v2/baselineTracker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import http from 'k6/http'
import { check, sleep } from 'k6'
import { isStatus200, getHeaders } from '../utils/utils.js'

export const options = {
vus: 20,
duration: '30s'
}

const baseUrl = `${__ENV.BASE_URL}/v2`

export default function () {

getBaselineTrackers()

sleep(1)
}

function getBaselineTrackers() {
// TODO change url endpoint when spelling mistake resolved
const res = http.get(`${baseUrl}/basline-tracker?page=1&count=50`, {
headers: getHeaders()
})

isStatus200(res)
}
25 changes: 25 additions & 0 deletions Dfe.Academies.Performance/scripts/v2/fssProjects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import http from 'k6/http'
import { check, sleep } from 'k6'
import { isStatus200, getHeaders } from '../utils/utils.js'

export const options = {
vus: 20,
duration: '30s'
}

const baseUrl = `${__ENV.BASE_URL}/v2`

export default function () {

getFreeSchoolProjects()

sleep(1)
}

function getFreeSchoolProjects() {
const res = http.get(`${baseUrl}/fss/projects`, {
headers: getHeaders()
})

isStatus200(res)
}
45 changes: 45 additions & 0 deletions Dfe.Academies.Performance/scripts/v3/trusts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import http from 'k6/http'
import { check, sleep } from 'k6'
import { isStatus200, getHeaders } from '../utils/utils.js'

export const options = {
vus: 20,
duration: '30s'
}

const baseUrl = `${__ENV.BASE_URL}/v3`

export default function () {

getTrustByUkPrn('10067112')

searchTrustByName('SOUTH YORK MULTI ACADEMY TRUST')

searchTrustByUkPrn('10067112')

sleep(1)
}

function getTrustByUkPrn(ukprn) {
const res = http.get(`${baseUrl}/trust/${ukprn}`, {
headers: getHeaders()
})

isStatus200(res)
}

function searchTrustByName(name) {
const res = http.get(`${baseUrl}/trusts?groupName=${name}&page=1&count=10`, {
headers: getHeaders()
})

isStatus200(res);
}

function searchTrustByUkPrn(ukprn) {
const res = http.get(`${baseUrl}/trusts?ukPrn=${ukprn}&page=1&count=10`, {
headers: getHeaders()
})

isStatus200(res)
}
45 changes: 45 additions & 0 deletions Dfe.Academies.Performance/scripts/v4/establishments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import http from 'k6/http'
import { check, sleep } from 'k6'
import { isStatus200, getHeaders } from '../utils/utils.js'

export const options = {
vus: 20,
duration: '30s'
}

const baseUrl = `${__ENV.BASE_URL}/v4`

export default function () {

getEstablishmentByUkPrn('10079319')

getEstablishmentByUrn('100000')

getEstablishmentsForTrust('10067112')

sleep(1)
}

function getEstablishmentByUkPrn(ukprn) {
const res = http.get(`${baseUrl}/establishment/${ukprn}`, {
headers: getHeaders()
})

isStatus200(res)
}

function getEstablishmentByUrn(urn) {
const res = http.get(`${baseUrl}/establishment/urn/${urn}`, {
headers: getHeaders()
})

isStatus200(res)
}

function getEstablishmentsForTrust(ukprn) {
const res = http.get(`${baseUrl}/establishments/trust?trustUkPrn=${ukprn}`, {
headers: getHeaders()
})

isStatus200(res)
}
66 changes: 66 additions & 0 deletions Dfe.Academies.Performance/scripts/v4/trusts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import http from 'k6/http'
import { check, sleep } from 'k6'
import { isStatus200, getHeaders } from '../utils/utils.js'

export const options = {
vus: 20,
duration: '30s'
}

const baseUrl = `${__ENV.BASE_URL}/v4`

export default function () {

getTrustByUkPrn('10067112')

getTrustByCompaniesHouseNumber('11082297')

getTrustByReferenceNumber('TR03739')

searchTrustByUkPrn('10067112')

searchTrustByName('SOUTH YORK MULTI ACADEMY TRUST')

sleep(1)
}

function getTrustByUkPrn(ukprn) {
const res = http.get(`${baseUrl}/trust/${ukprn}`, {
headers: getHeaders()
})

isStatus200(res)
}

function getTrustByCompaniesHouseNumber(companiesHouseNumber) {
const res = http.get(`${baseUrl}/trust/companiesHouseNumber/${companiesHouseNumber}`, {
headers: getHeaders()
})

isStatus200(res)

}

function getTrustByReferenceNumber(trustReferenceNumber) {
const res = http.get(`${baseUrl}/trust/trustReferenceNumber/${trustReferenceNumber}`, {
headers: getHeaders()
})

isStatus200(res)
}

function searchTrustByName(name) {
const res = http.get(`${baseUrl}/trusts?groupName=${name}&page=1&count=10`, {
headers: getHeaders()
})

isStatus200(res);
}

function searchTrustByUkPrn(ukprn) {
const res = http.get(`${baseUrl}/trusts?ukPrn=${ukprn}&page=1&count=10`, {
headers: getHeaders()
})

isStatus200(res)
}
95 changes: 95 additions & 0 deletions TramsDataApi.Test/Integration/V4/GenerateDataTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Dfe.Academies.Academisation.Data;
using Dfe.Academies.Domain.Establishment;
using Dfe.Academies.Domain.Trust;
using System.Collections.Generic;
using System.Linq;
using TramsDataApi.Test.Fixtures;
using TramsDataApi.Test.Helpers;
using Xunit;

namespace TramsDataApi.Test.Integration.V4
{
[Collection(ApiTestCollection.ApiTestCollectionName)]
public class GenerateDataTests
{
private readonly ApiTestFixture _apiFixture;

public GenerateDataTests(ApiTestFixture fixture)
{
_apiFixture = fixture;
}

[Fact(Skip = "Generate data for performance testing on an adhoc basis")]
public void GenerateTrustData()
{
using var context = _apiFixture.GetMstrContext();
context.ChangeTracker.AutoDetectChangesEnabled = false;

for (var idx = 0; idx < 4000; idx++)
{
CreateDataSet(context);
}
}

private static TrustDataSet CreateDataSet(MstrContext context)
{
var trust = DatabaseModelBuilder.BuildTrust();
context.Add(trust);
context.SaveChanges();

var establishments = new List<EstablishmentDataSet>();

for (var idx = 0; idx < 3; idx++)
{
var establishment = DatabaseModelBuilder.BuildEstablishment();
var ifdPipeline = DatabaseModelBuilder.BuildIfdPipeline();
ifdPipeline.GeneralDetailsUrn = establishment.PK_GIAS_URN;

var establishmentDataSet = new EstablishmentDataSet()
{
Establishment = establishment,
IfdPipeline = ifdPipeline
};

context.Establishments.Add(establishment);
context.IfdPipelines.Add(ifdPipeline);

establishments.Add(establishmentDataSet);
}

context.SaveChanges();

var trustToEstablishmentLinks = LinkTrustToEstablishments(trust, establishments.Select(d => d.Establishment).ToList());

context.EducationEstablishmentTrusts.AddRange(trustToEstablishmentLinks);

context.SaveChanges();

var result = new TrustDataSet()
{
Trust = trust,
Establishments = establishments
};

return result;
}

private static List<EducationEstablishmentTrust> LinkTrustToEstablishments(Trust trust, List<Establishment> establishments)
{
var result = new List<EducationEstablishmentTrust>();

establishments.ForEach(establishment =>
{
var educationEstablishmentTrust = new EducationEstablishmentTrust()
{
TrustId = (int)trust.SK,
EducationEstablishmentId = (int)establishment.SK
};

result.Add(educationEstablishmentTrust);
});

return result;
}
}
}

0 comments on commit a042d30

Please sign in to comment.