From 99a944b7cfb7e38f69d93f32223bef336b08f25e Mon Sep 17 00:00:00 2001 From: antyadev Date: Wed, 9 Oct 2024 18:43:39 +0300 Subject: [PATCH] Added Thresholds examples --- .../xUnitExample/Configs/nbomber-config.json | 31 +++++++++ examples/xUnitExample/LoadTestExample.cs | 13 +++- examples/xUnitExample/Thresholds.cs | 63 +++++++++++++++++++ examples/xUnitExample/ThresholdsFromConfig.cs | 44 +++++++++++++ examples/xUnitExample/xUnitExample.csproj | 10 ++- 5 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 examples/xUnitExample/Configs/nbomber-config.json create mode 100644 examples/xUnitExample/Thresholds.cs create mode 100644 examples/xUnitExample/ThresholdsFromConfig.cs diff --git a/examples/xUnitExample/Configs/nbomber-config.json b/examples/xUnitExample/Configs/nbomber-config.json new file mode 100644 index 00000000..ebedfdcd --- /dev/null +++ b/examples/xUnitExample/Configs/nbomber-config.json @@ -0,0 +1,31 @@ +{ + "GlobalSettings": { + "ScenariosSettings": [ + { + "ScenarioName": "http_scenario", + + "LoadSimulationsSettings": [ + { "Inject": [1, "00:00:01", "00:00:30"] } + ], + + "ThresholdSettings": [ + + { "OkRequest": "RPS <= 30" }, + { "OkRequest": "Percent > 90" }, + + { "FailRequest": "Percent < 20" }, + + { "OkLatency": "max < 100" }, + { "OkLatency": "p75 < 80" }, + + { "OkDataTransfer": "p75 < 80" }, + + { "StatusCode": ["500", "Percent < 5"] }, + { "StatusCode": ["400", "Percent < 10"], "AbortWhenErrorCount": 5 }, + { "StatusCode": ["200", "Percent >= 50"], "AbortWhenErrorCount": 5, "StartCheckAfter": "00:00:10" } + + ] + } + ] + } +} diff --git a/examples/xUnitExample/LoadTestExample.cs b/examples/xUnitExample/LoadTestExample.cs index 60ae4af8..3034da58 100644 --- a/examples/xUnitExample/LoadTestExample.cs +++ b/examples/xUnitExample/LoadTestExample.cs @@ -19,7 +19,7 @@ public void SimpleHttpExample() { var request = Http.CreateRequest("GET", "https://nbomber.com") - .WithHeader("Accept", "text/html") + .WithHeader("Content-Type", "application/json") .WithBody(new StringContent("{ some JSON }")); var response = await Http.Send(httpClient, request); @@ -31,7 +31,7 @@ public void SimpleHttpExample() { var request = Http.CreateRequest("GET", "https://nbomber.com") - .WithHeader("Accept", "text/html") + .WithHeader("Content-Type", "application/json") .WithBody(new StringContent("{ some JSON }")); var response = await Http.Send(httpClient, request); @@ -48,7 +48,16 @@ public void SimpleHttpExample() .RegisterScenarios(scenario) .Run(); + // StatsHelper API extensions provides: Get, Find, Exist methods to work with ScenarioStats, StepStats, StatusCodes, etc. + + // gets scenario stats: + // it throws exception if "http_scenario" is not found var scnStats = result.ScenarioStats.Get("http_scenario"); + + // finds scenario stats: + // it returns null if "http_scenario" is not found + scnStats = result.ScenarioStats.Find("http_scenario"); + var step1Stats = scnStats.StepStats.Get("step_1"); var isStep2Exist = scnStats.StepStats.Exists("step_2"); diff --git a/examples/xUnitExample/Thresholds.cs b/examples/xUnitExample/Thresholds.cs new file mode 100644 index 00000000..14603a0e --- /dev/null +++ b/examples/xUnitExample/Thresholds.cs @@ -0,0 +1,63 @@ +using NBomber.Contracts; +using NBomber.CSharp; +using NBomber.Http.CSharp; +using Xunit; + +namespace xUnitExample; + +public class Thresholds +{ + [Fact] + public void Runtime_Thresholds_Example() + { + using var httpClient = new HttpClient(); + + var scenario = Scenario.Create("http_scenario", async context => + { + var step1 = await Step.Run("step_1", context, async () => + { + var request = + Http.CreateRequest("GET", "https://nbomber.com") + .WithHeader("Content-Type", "application/json"); + + var response = await Http.Send(httpClient, request); + + return response; + }); + + return Response.Ok(); + }) + .WithoutWarmUp() + .WithLoadSimulations(Simulation.Inject(rate: 1, interval: TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30))) + .WithThresholds( + // Scenario's threshold that checks: error rate > 10% + Threshold.Create(scenarioStats => scenarioStats.Fail.Request.Percent > 10), + + // Step's threshold that checks: error rate > 10% + Threshold.Create("step_1", stepStats => stepStats.Fail.Request.Percent > 10), + + // Scenario's threshold that checks if any response contains status code 404 + Threshold.Create( + scenarioStats => scenarioStats.Fail.StatusCodes.Exists("404"), + + abortWhenErrorCount: 5, // Threshold checks are executed based on the ReportingInterval (by default each 5 sec), + // so when the threshold ErrorCount = 5, the load test will be aborted. + // By default, 'abortWhenErrorCount' is null meaning Thresholds errors will not abort the test execution. + + + startCheckAfter: TimeSpan.FromSeconds(10) // Threshold check will be delayed on 10 sec + ), + + Threshold.Create(scenarioStats => scenarioStats.Ok.StatusCodes.Find("200")?.Percent <= 30) + ); + + var result = NBomberRunner + .RegisterScenarios(scenario) + .Run(); + + // Here, we attempt to find a failed threshold, and if one is found (i.e., it is not null), we throw an exception. + var failedThreshold = result.Thresholds.FirstOrDefault(x => x.IsFailed); + + Assert.True(failedThreshold == null); + } +} diff --git a/examples/xUnitExample/ThresholdsFromConfig.cs b/examples/xUnitExample/ThresholdsFromConfig.cs new file mode 100644 index 00000000..854f861a --- /dev/null +++ b/examples/xUnitExample/ThresholdsFromConfig.cs @@ -0,0 +1,44 @@ +using NBomber.CSharp; +using NBomber.Http.CSharp; +using Xunit; + +namespace xUnitExample; + +public class ThresholdsFromConfig +{ + [Fact] + public void Runtime_Thresholds_Example() + { + using var httpClient = new HttpClient(); + + var scenario = Scenario.Create("http_scenario", async context => + { + var step1 = await Step.Run("step_1", context, async () => + { + var request = + Http.CreateRequest("GET", "https://nbomber.com") + .WithHeader("Content-Type", "application/json"); + + var response = await Http.Send(httpClient, request); + + return response; + }); + + return Response.Ok(); + }) + .WithoutWarmUp() + .WithLoadSimulations( + Simulation.Inject(rate: 1, interval: TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30)) + ); + + var result = NBomberRunner + .RegisterScenarios(scenario) + .LoadConfig("Configs/nbomber-config.json") + .Run(); + + // Here, we attempt to find a failed threshold, and if one is found (i.e., it is not null), we throw an exception. + var failedThreshold = result.Thresholds.FirstOrDefault(x => x.IsFailed); + + Assert.True(failedThreshold != null); + } +} diff --git a/examples/xUnitExample/xUnitExample.csproj b/examples/xUnitExample/xUnitExample.csproj index 22fc3112..65fa7e2e 100644 --- a/examples/xUnitExample/xUnitExample.csproj +++ b/examples/xUnitExample/xUnitExample.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -21,4 +21,10 @@ + + + PreserveNewest + + +