diff --git a/Dfe.Academies.Performance/README.md b/Dfe.Academies.Performance/README.md new file mode 100644 index 000000000..4615c3789 --- /dev/null +++ b/Dfe.Academies.Performance/README.md @@ -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= -e BASE_URL= ` + +## 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. \ No newline at end of file diff --git a/Dfe.Academies.Performance/scripts/utils/utils.js b/Dfe.Academies.Performance/scripts/utils/utils.js new file mode 100644 index 000000000..1cfd9331a --- /dev/null +++ b/Dfe.Academies.Performance/scripts/utils/utils.js @@ -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' + } +} diff --git a/Dfe.Academies.Performance/scripts/v1/keyStagePerformance.js b/Dfe.Academies.Performance/scripts/v1/keyStagePerformance.js new file mode 100644 index 000000000..fd5ac6bc3 --- /dev/null +++ b/Dfe.Academies.Performance/scripts/v1/keyStagePerformance.js @@ -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) +} diff --git a/Dfe.Academies.Performance/scripts/v2/baselineTracker.js b/Dfe.Academies.Performance/scripts/v2/baselineTracker.js new file mode 100644 index 000000000..e0ec4d9ef --- /dev/null +++ b/Dfe.Academies.Performance/scripts/v2/baselineTracker.js @@ -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) +} diff --git a/Dfe.Academies.Performance/scripts/v2/fssProjects.js b/Dfe.Academies.Performance/scripts/v2/fssProjects.js new file mode 100644 index 000000000..636ef6ca2 --- /dev/null +++ b/Dfe.Academies.Performance/scripts/v2/fssProjects.js @@ -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) +} diff --git a/Dfe.Academies.Performance/scripts/v3/trusts.js b/Dfe.Academies.Performance/scripts/v3/trusts.js new file mode 100644 index 000000000..da8b5e256 --- /dev/null +++ b/Dfe.Academies.Performance/scripts/v3/trusts.js @@ -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) +} diff --git a/Dfe.Academies.Performance/scripts/v4/establishments.js b/Dfe.Academies.Performance/scripts/v4/establishments.js new file mode 100644 index 000000000..24b8106dd --- /dev/null +++ b/Dfe.Academies.Performance/scripts/v4/establishments.js @@ -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) +} diff --git a/Dfe.Academies.Performance/scripts/v4/trusts.js b/Dfe.Academies.Performance/scripts/v4/trusts.js new file mode 100644 index 000000000..a3e398467 --- /dev/null +++ b/Dfe.Academies.Performance/scripts/v4/trusts.js @@ -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) +} diff --git a/TramsDataApi.Test/Integration/V4/GenerateDataTests.cs b/TramsDataApi.Test/Integration/V4/GenerateDataTests.cs new file mode 100644 index 000000000..669f1886e --- /dev/null +++ b/TramsDataApi.Test/Integration/V4/GenerateDataTests.cs @@ -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(); + + 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 LinkTrustToEstablishments(Trust trust, List establishments) + { + var result = new List(); + + establishments.ForEach(establishment => + { + var educationEstablishmentTrust = new EducationEstablishmentTrust() + { + TrustId = (int)trust.SK, + EducationEstablishmentId = (int)establishment.SK + }; + + result.Add(educationEstablishmentTrust); + }); + + return result; + } + } +}