Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #32

Merged
merged 9 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Bombardier test asserter, readme update
  • Loading branch information
mihaj committed Nov 19, 2020
commit 54bfaa5a067e01ebc9e03f79af8123b07b2d3cd4
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<Version>0.3.2</Version>
<Version>0.3.5</Version>
</PropertyGroup>
</Project>
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,45 @@ Results sample `bombardierResults`:
]
```

As you can see you get a lot of metrics from the tests.
As you can see you get a lot of metrics from the tests. You can use xUnit to assert the numbers, or you can use `BombardierTestAsserter` like this:

```csharp
var asserter = new BombardierTestAsserter(bombardierResults.FirstOrDefault());
var assertResults = asserter
.NumberOf1xxResponses((x) => x == 0)
.NumberOf2xxResponses((x) => x >= 0)
.NumberOf3xxResponses((x) => x == 0)
.NumberOf4xxResponses((x) => x == 0)
.NumberOf5xxResponses((x) => x == 0)
.AverageLatency((x) => x >= 0)
.AverageRequestsPerSecond((x) => x >= 0)
.MaximumLatency((x) => x >= 0)
.MaximumRequestsPerSecond((x) => x >= 0)
.AssertAll();
```

Asserter produces a list of `AssertResult`:

```csharp
/// <summary>
/// Assert result object
/// </summary>
public class AssertResult
{
/// <summary>
/// Assert name
/// </summary>
public string Name { get; set; }
/// <summary>
/// Is assert true
/// </summary>
public bool IsTrue { get; set; }
/// <summary>
/// Assert message
/// </summary>
public string Message { get; set; }
}
```

## Description

Expand Down
196 changes: 196 additions & 0 deletions src/QAToolKit.Engine.Bombardier.Test/BombardierTestAsserterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using QAToolKit.Core.Models;
using QAToolKit.Engine.Bombardier.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace QAToolKit.Engine.Bombardier.Test
{
public class BombardierTestAsserterTests
{
private readonly ILogger<BombardierTestAsserterTests> _logger;

public BombardierTestAsserterTests(ITestOutputHelper testOutputHelper)
{
var loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
_logger = loggerFactory.CreateLogger<BombardierTestAsserterTests>();
}

[IgnoreOnGithubFact]
public async Task BombardierGetTestWithOptionsTest_Successfull()
{
var content = File.ReadAllText("Assets/getPetById.json");
var httpRequest = JsonConvert.DeserializeObject<IEnumerable<HttpRequest>>(content);

var bombardierTestsGenerator = new BombardierTestsGenerator(httpRequest, options =>
{
options.BombardierConcurrentUsers = 1;
options.BombardierDuration = 1;
options.BombardierTimeout = 30;
options.BombardierUseHttp2 = true;
});

var bombardierTests = await bombardierTestsGenerator.Generate();

//Run Bombardier Tests
var bombardierTestsRunner = new BombardierTestsRunner(bombardierTests.ToList(), options =>
{
options.ObfuscateAuthenticationHeader = true;
});
var bombardierResults = await bombardierTestsRunner.Run();

_logger.LogInformation(JsonConvert.SerializeObject(bombardierResults, Formatting.Indented));

var asserter = new BombardierTestAsserter(bombardierResults.FirstOrDefault());
var assertResults = asserter
.NumberOf1xxResponses((x) => x == 0)
.NumberOf2xxResponses((x) => x >= 0)
.NumberOf3xxResponses((x) => x == 0)
.NumberOf4xxResponses((x) => x == 0)
.NumberOf5xxResponses((x) => x == 0)
.AverageLatency((x) => x >= 0)
.AverageRequestsPerSecond((x) => x >= 0)
.MaximumLatency((x) => x >= 0)
.MaximumRequestsPerSecond((x) => x >= 0)
.AssertAll();

foreach (var result in assertResults)
{
Assert.True(result.IsTrue, result.Message);
}
}

[IgnoreOnGithubFact]
public async Task BombardierPostTestWithOptionsTest_Successfull()
{
var content = File.ReadAllText("Assets/addPet.json");
var httpRequest = JsonConvert.DeserializeObject<IList<HttpRequest>>(content);

var bombardierTestsGenerator = new BombardierTestsGenerator(httpRequest, options =>
{
options.BombardierConcurrentUsers = 1;
options.BombardierDuration = 1;
options.BombardierTimeout = 30;
options.BombardierUseHttp2 = true;
options.BombardierNumberOfTotalRequests = 1;
options.AddReplacementValues(new Dictionary<string, object> {
{"id",1241451},
{ "name","MJ"}
});
});

var bombardierTests = await bombardierTestsGenerator.Generate();

//Run Bombardier Tests
var bombardierTestsRunner = new BombardierTestsRunner(bombardierTests.ToList(), options =>
{
options.ObfuscateAuthenticationHeader = true;
});
var bombardierResults = await bombardierTestsRunner.Run();

var asserter = new BombardierTestAsserter(bombardierResults.FirstOrDefault());
var assertResults = asserter
.NumberOf1xxResponses((x) => x == 0)
.NumberOf2xxResponses((x) => x >= 0)
.NumberOf3xxResponses((x) => x == 0)
.NumberOf4xxResponses((x) => x == 0)
.NumberOf5xxResponses((x) => x == 0)
.AverageLatency((x) => x >= 0)
.AverageRequestsPerSecond((x) => x >= 0)
.MaximumLatency((x) => x >= 0)
.MaximumRequestsPerSecond((x) => x >= 0)
.AssertAll();

foreach (var result in assertResults)
{
Assert.True(result.IsTrue, result.Message);
}
}

[IgnoreOnGithubFact]
public async Task BombardierPostTestWithBodyAndOptionsTest_Successfull()
{
var content = File.ReadAllText("Assets/AddBike.json");
var httpRequest = JsonConvert.DeserializeObject<IList<HttpRequest>>(content);

var bombardierTestsGenerator = new BombardierTestsGenerator(httpRequest, options =>
{
options.BombardierConcurrentUsers = 1;
options.BombardierDuration = 1;
options.BombardierTimeout = 30;
options.BombardierUseHttp2 = true;
options.AddReplacementValues(new Dictionary<string, object> {
{"Bicycle",@"{""id"":66,""name"":""my bike"",""brand"":""cannondale"",""BicycleType"":1}"}
});
});

var bombardierTests = await bombardierTestsGenerator.Generate();

//Run Bombardier Tests
var bombardierTestsRunner = new BombardierTestsRunner(bombardierTests.ToList(), options =>
{
options.ObfuscateAuthenticationHeader = true;
});
var bombardierResults = await bombardierTestsRunner.Run();

_logger.LogInformation(JsonConvert.SerializeObject(bombardierResults, Formatting.Indented));

Assert.NotNull(bombardierResults);
Assert.Single(bombardierResults);
Assert.Equal(@"-m POST https://qatoolkitapi.azurewebsites.net/api/bicycles?api-version=1 -c 1 -H ""Content-Type: application/json"" -b ""{""id"":66,""name"":""my bike"",""brand"":""cannondale"",""BicycleType"":1}"" --http2 --timeout=30s --duration=1s", bombardierResults.FirstOrDefault().Command);

var asserter = new BombardierTestAsserter(bombardierResults.FirstOrDefault());
var assertResults = asserter
.NumberOf1xxResponses((x) => x == 0)
.NumberOf2xxResponses((x) => x >= 0)
.NumberOf3xxResponses((x) => x == 0)
.NumberOf4xxResponses((x) => x == 0)
.NumberOf5xxResponses((x) => x == 0)
.AverageLatency((x) => x >= 0)
.AverageRequestsPerSecond((x) => x >= 0)
.MaximumLatency((x) => x >= 0)
.MaximumRequestsPerSecond((x) => x >= 0)
.AssertAll();

foreach (var result in assertResults)
{
Assert.True(result.IsTrue, result.Message);
}
}

[Fact]
public void BombardierAsserterNullObject_Successfull()
{
Assert.Throws<ArgumentNullException>(() => new BombardierTestAsserter(null));
}

[Fact]
public void BombardierAsserterNullResults_Successfull()
{
var asserter = new BombardierTestAsserter(new BombardierResult());
var assertResults = asserter
.NumberOf1xxResponses((x) => x == 0)
.NumberOf2xxResponses((x) => x >= 0)
.NumberOf3xxResponses((x) => x == 0)
.NumberOf4xxResponses((x) => x == 0)
.NumberOf5xxResponses((x) => x == 0)
.AverageLatency((x) => x >= 0)
.AverageRequestsPerSecond((x) => x >= 0)
.MaximumLatency((x) => x >= 0)
.MaximumRequestsPerSecond((x) => x >= 0)
.AssertAll();

foreach (var result in assertResults)
{
Assert.True(result.IsTrue, result.Message);
}
}
}
}
12 changes: 6 additions & 6 deletions src/QAToolKit.Engine.Bombardier/BombardierGeneratorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class BombardierGeneratorOptions
/// <returns></returns>
public BombardierGeneratorOptions AddReplacementValues(Dictionary<string, object> replacementValues)
{
ReplacementValues = replacementValues ?? throw new ArgumentException(nameof(replacementValues));
ReplacementValues = replacementValues ?? throw new ArgumentException($"{nameof(replacementValues)} is null.");
return this;
}

Expand All @@ -88,9 +88,9 @@ public BombardierGeneratorOptions AddReplacementValues(Dictionary<string, object
public BombardierGeneratorOptions AddOAuth2Token(string token, AuthenticationType authenticationType)
{
if (string.IsNullOrEmpty(token))
throw new ArgumentException(nameof(token));
throw new ArgumentException($"{nameof(token)} is null.");
if (authenticationType == null)
throw new ArgumentException(nameof(authenticationType));
throw new ArgumentException($"{nameof(authenticationType)} is null.");

AccessTokens.Add(authenticationType, token);
return this;
Expand All @@ -104,7 +104,7 @@ public BombardierGeneratorOptions AddOAuth2Token(string token, AuthenticationTyp
public BombardierGeneratorOptions AddApiKey(string apiKey)
{
if (string.IsNullOrEmpty(apiKey))
throw new ArgumentException(nameof(apiKey));
throw new ArgumentException($"{nameof(apiKey)} is null.");

ApiKey = apiKey;
return this;
Expand All @@ -119,9 +119,9 @@ public BombardierGeneratorOptions AddApiKey(string apiKey)
public BombardierGeneratorOptions AddBasicAuthentication(string userName, string password)
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentException(nameof(userName));
throw new ArgumentException($"{nameof(userName)} is null.");
if (string.IsNullOrEmpty(password))
throw new ArgumentException(nameof(password));
throw new ArgumentException($"{nameof(password)} is null.");

UserName = userName;
Password = password;
Expand Down
Loading