From c3114c5407cce9a1b1c91da042d4773a1f35f5d8 Mon Sep 17 00:00:00 2001 From: Anaig Date: Mon, 27 Jul 2020 15:31:56 +0200 Subject: [PATCH 1/2] update AKS version --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index bdd641c..f0d18ad 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -37,7 +37,7 @@ variables: - name: APP_SP_OBJECT_ID value: ddf63018-48fb-4738-a3f5-0062fb16dbb0 - name: AKS_VERSION - value: 1.18.1 + value: 1.18.2 - name: HELM_RELEASE_NAME value: contoso - name: RESOURCE_GROUP From 5c98e7b6d14c617dc9630fc03ba859d1cc8320d8 Mon Sep 17 00:00:00 2001 From: Anaig Date: Wed, 29 Jul 2020 09:42:47 +0200 Subject: [PATCH 2/2] add load test file --- Dockerfile | 14 +++- .../Contoso.LoadTests.csproj | 16 +++++ Src/Contoso.LoadTests/LoadTest.cs | 71 +++++++++++++++++++ Src/Contoso.sln | 12 ++++ 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 Src/Contoso.LoadTests/Contoso.LoadTests.csproj create mode 100644 Src/Contoso.LoadTests/LoadTest.cs diff --git a/Dockerfile b/Dockerfile index e37dc0a..213734b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ WORKDIR /app COPY Src/*.sln . COPY Src/Contoso/*.csproj ./Contoso/ COPY Src/Contoso.UnitTests/*.csproj ./Contoso.UnitTests/ +COPY Src/Contoso.LoadTests/*.csproj ./Contoso.LoadTests/ RUN dotnet restore # copy everything else and build app @@ -20,15 +21,22 @@ WORKDIR /app/Contoso RUN dotnet build -c Release /p:VersionPrefix=${VersionPrefix} /p:TreatWarningsAsErrors=true -warnaserror -FROM build AS testrunner +FROM build AS unittestrunner WORKDIR /app/Contoso.UnitTests ENTRYPOINT ["dotnet", "test", "--logger:trx", "--collect:XPlat Code Coverage"] - -FROM build AS test +FROM build AS unittest WORKDIR /app/Contoso.UnitTests RUN dotnet test --collect:"XPlat Code Coverage" +FROM build AS loadtestrunner +WORKDIR /app/Contoso.LoadTests +ENTRYPOINT ["dotnet", "test", "--logger:trx", "--results-directory", "/loadTestResults"] + +FROM build AS loadtest +WORKDIR /app/Contoso.LoadTests +RUN dotnet test + FROM build AS publish WORKDIR /app/Contoso RUN dotnet publish -c Release -o /out diff --git a/Src/Contoso.LoadTests/Contoso.LoadTests.csproj b/Src/Contoso.LoadTests/Contoso.LoadTests.csproj new file mode 100644 index 0000000..5b1791f --- /dev/null +++ b/Src/Contoso.LoadTests/Contoso.LoadTests.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + diff --git a/Src/Contoso.LoadTests/LoadTest.cs b/Src/Contoso.LoadTests/LoadTest.cs new file mode 100644 index 0000000..4a383cb --- /dev/null +++ b/Src/Contoso.LoadTests/LoadTest.cs @@ -0,0 +1,71 @@ +using NBomber.Contracts; +using NBomber.CSharp; +using RestSharp; +using System; +using System.Net.Http; +using System.Runtime.Versioning; +using Xunit; +using Xunit.Abstractions; + +namespace Contoso.LoadTests +{ + public class LoadTest + { + + static HttpClient client = new HttpClient(); + static string _stepName = "CheckIfOK"; + private readonly Uri _path; + private readonly int _concurrency; + private readonly int _duration; + private readonly int _warmuUp; + private readonly ITestOutputHelper _output; + + public LoadTest(ITestOutputHelper output) + { + static Uri getUriFromEnvironment(string name) + { + var env = Environment.GetEnvironmentVariable(name); + if (string.IsNullOrWhiteSpace(env)) + { + throw new NotSupportedException($"Missing environment variable {name}"); + } + return new Uri(env); + }; + + _path = getUriFromEnvironment("SERVICE_URL"); + _concurrency = 10; + _duration = 10; + _warmuUp = 5; + } + + /// + /// Executes a basic load test using NBomber + /// + [Fact] + public void RunLoadTest() + { + // Load test settings + var warmUpPhase = TimeSpan.FromSeconds(_warmuUp); // execution time of warm-up before start bombing + var testDuration = TimeSpan.FromSeconds(_duration); // execution time of Scenario + var concurrentCopies = _concurrency; // specify how many copies of current Scenario to run in parallel + + // Assertions parameters + var acceptedFailNumber = 0; + var minRPS = 5; + + // Execution step for the load scenario + var step = Step.Create(_stepName, async context => + { + var response = await client.GetAsync(_path + "/sample/sumNumbersUpTo?value=100"); + var success = response.IsSuccessStatusCode; + return success ? Response.Ok() : Response.Fail(); + }); + + // List of assertions to be respected by the scenario for each step + var successAssertion = Assertion.ForStep(stepName: _stepName, + assertion: statistics => statistics.FailCount == acceptedFailNumber); + var rpsAssertion = Assertion.ForStep(stepName: _stepName, + assertion: statistics => statistics.RPS >= minRPS); + } + } +} diff --git a/Src/Contoso.sln b/Src/Contoso.sln index 663ad28..a1434d4 100644 --- a/Src/Contoso.sln +++ b/Src/Contoso.sln @@ -8,6 +8,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Contoso.UnitTests", "Contoso.UnitTests\Contoso.UnitTests.csproj", "{B219CDAD-7641-4ECB-8B96-EB47E25DE5AC}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AAA7F28-054C-45C6-83A2-8FB787A7DF50}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contoso.LoadTests", "Contoso.LoadTests\Contoso.LoadTests.csproj", "{55737DD5-84C3-4CFB-AC6A-14FB8E14FA37}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -22,10 +26,18 @@ Global {B219CDAD-7641-4ECB-8B96-EB47E25DE5AC}.Debug|Any CPU.Build.0 = Debug|Any CPU {B219CDAD-7641-4ECB-8B96-EB47E25DE5AC}.Release|Any CPU.ActiveCfg = Release|Any CPU {B219CDAD-7641-4ECB-8B96-EB47E25DE5AC}.Release|Any CPU.Build.0 = Release|Any CPU + {55737DD5-84C3-4CFB-AC6A-14FB8E14FA37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55737DD5-84C3-4CFB-AC6A-14FB8E14FA37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55737DD5-84C3-4CFB-AC6A-14FB8E14FA37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55737DD5-84C3-4CFB-AC6A-14FB8E14FA37}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B219CDAD-7641-4ECB-8B96-EB47E25DE5AC} = {0AAA7F28-054C-45C6-83A2-8FB787A7DF50} + {55737DD5-84C3-4CFB-AC6A-14FB8E14FA37} = {0AAA7F28-054C-45C6-83A2-8FB787A7DF50} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E55E11EA-AB0F-4280-943D-F6F1EC519DFB} EndGlobalSection