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
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