Skip to content

Commit f2dc208

Browse files
committed
helpers refactored, replacement values introduced, more tests
1 parent b13f9de commit f2dc208

File tree

9 files changed

+153
-113
lines changed

9 files changed

+153
-113
lines changed

src/QAToolKit.Engine.Bombardier.Test/BombardierTestsGeneratorTests.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ public async Task GenerateBombardierTestWithOptionsVariation2Test_Successfull()
6060
options.BombardierTimeout = 30;
6161
options.BombardierUseHttp2 = true;
6262
options.BombardierInsecure = true;
63+
options.AddReplacementValues(new ReplacementValue[] {
64+
new ReplacementValue(){
65+
Key = "id",
66+
Value = 1000
67+
},
68+
new ReplacementValue(){
69+
Key = "name",
70+
Value = "MJ"
71+
}
72+
});
6373
});
6474

6575
var content = File.ReadAllText("Assets/getPetById.json");
@@ -249,5 +259,65 @@ public async Task GenerateBombardierTestDefaultBombardierOptionsTest_Successfull
249259
Assert.Equal(HttpMethod.Get, bombardierTests.FirstOrDefault().Method);
250260
Assert.Equal("/pet/10", bombardierTests.FirstOrDefault().Url.ToString());
251261
}
262+
263+
[Fact]
264+
public async Task GenerateBombardierTestPostTest_Successfull()
265+
{
266+
267+
var bombardierTestsGenerator = new BombardierTestsGenerator(options =>
268+
{
269+
options.AddReplacementValues(new ReplacementValue[] {
270+
new ReplacementValue(){
271+
Key = "id",
272+
Value = 1000
273+
},
274+
new ReplacementValue(){
275+
Key = "name",
276+
Value = "MJ"
277+
}
278+
});
279+
});
280+
281+
var content = File.ReadAllText("Assets/addPet.json");
282+
var httpRequest = JsonConvert.DeserializeObject<IList<HttpRequest>>(content);
283+
284+
var bombardierTests = await bombardierTestsGenerator.Generate(httpRequest);
285+
286+
Assert.NotNull(bombardierTests);
287+
Assert.Single(bombardierTests);
288+
Assert.Contains($@" -m POST https://petstore3.swagger.io/api/v3/pet -c 3 -H ""Content-Type: application/json"" -b ""{{\""id\"":1000,\""name\"":\""MJ\""}}"" --http2 --timeout=30s --duration=5s", bombardierTests.FirstOrDefault().Command);
289+
Assert.Equal(HttpMethod.Post, bombardierTests.FirstOrDefault().Method);
290+
Assert.Equal("/pet", bombardierTests.FirstOrDefault().Url.ToString());
291+
}
292+
293+
[Fact]
294+
public async Task GenerateBombardierTestPostWithExampleValuesTest_Successfull()
295+
{
296+
297+
var bombardierTestsGenerator = new BombardierTestsGenerator(options =>
298+
{
299+
options.AddReplacementValues(new ReplacementValue[] {
300+
new ReplacementValue(){
301+
Key = "companyId",
302+
Value = "1241451"
303+
},
304+
new ReplacementValue(){
305+
Key = "companyName",
306+
Value = "MJ"
307+
}
308+
});
309+
});
310+
311+
var content = File.ReadAllText("Assets/addPet.json");
312+
var httpRequest = JsonConvert.DeserializeObject<IList<HttpRequest>>(content);
313+
314+
var bombardierTests = await bombardierTestsGenerator.Generate(httpRequest);
315+
316+
Assert.NotNull(bombardierTests);
317+
Assert.Single(bombardierTests);
318+
Assert.Contains($@" -m POST https://petstore3.swagger.io/api/v3/pet -c 3 -H ""Content-Type: application/json"" -b ""{{\""id\"":999,\""name\"":\""my pet 999\""}}"" --http2 --timeout=30s --duration=5s", bombardierTests.FirstOrDefault().Command);
319+
Assert.Equal(HttpMethod.Post, bombardierTests.FirstOrDefault().Method);
320+
Assert.Equal("/pet", bombardierTests.FirstOrDefault().Url.ToString());
321+
}
252322
}
253323
}

src/QAToolKit.Engine.Bombardier.Test/BombardierTestsRunnerTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ public async Task BombardierPostTestWithOptionsTest_Successfull()
7676
options.BombardierTimeout = 30;
7777
options.BombardierUseHttp2 = true;
7878
options.BombardierNumberOfTotalRequests = 1;
79+
options.AddReplacementValues(new ReplacementValue[] {
80+
new ReplacementValue(){
81+
Key = "id",
82+
Value = 1241451
83+
},
84+
new ReplacementValue(){
85+
Key = "name",
86+
Value = "MJ"
87+
}
88+
});
7989
});
8090

8191
var content = File.ReadAllText("Assets/addPet.json");

src/QAToolKit.Engine.Bombardier/BombardierGeneratorOptions.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ public class BombardierGeneratorOptions
6262
/// What is the type of the test
6363
/// </summary>
6464
internal TestType TestType { get; } = TestType.LoadTest;
65+
/// <summary>
66+
/// Key/value pairs of replacement values
67+
/// </summary>
68+
internal ReplacementValue[] ReplacementValues { get; private set; }
69+
70+
/// <summary>
71+
/// Use replacement values
72+
/// </summary>
73+
/// <param name="replacementValues"></param>
74+
/// <returns></returns>
75+
public BombardierGeneratorOptions AddReplacementValues(ReplacementValue[] replacementValues)
76+
{
77+
ReplacementValues = replacementValues;
78+
return this;
79+
}
6580

6681
/// <summary>
6782
/// Add Oauth2 token to the bombardier generator

src/QAToolKit.Engine.Bombardier/BombardierTestsGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ public async Task<IEnumerable<BombardierTest>> Generate(IList<HttpRequest> restR
5050
foreach (var request in restRequests)
5151
{
5252
scriptBuilder.AppendLine($"{bombardierFullPath} " +
53-
$"-m {request.Method.ToString().ToUpper()} {HttpUrlHelper.GenerateUrlParameters(request)}" +
53+
$"-m {request.Method.ToString().ToUpper()} {HttpUrlHelper.GenerateUrlParameters(request, _bombardierGeneratorOptions)}" +
5454
$"{BombardierSwitchGeneratorHelper.GenerateConcurrentSwitch(request, _bombardierGeneratorOptions)}" +
5555
$"{AuthorizationHeaderHelper.GenerateAuthHeader(request, _bombardierGeneratorOptions)}" +
5656
$"{ContentTypeHeaderHelper.GenerateContentTypeHeader(request, _bombardierGeneratorOptions.BombardierBodyContentType)}" +
57-
$"{HttpBodyHelper.GenerateJsonBody(request, _bombardierGeneratorOptions.BombardierBodyContentType)}" +
57+
$"{BombardierSwitchGeneratorHelper.GenerateBodySwitch(request, _bombardierGeneratorOptions)}" +
5858
$"{BombardierSwitchGeneratorHelper.GenerateHttpProtocolSwitch(_bombardierGeneratorOptions)}" +
5959
$"{BombardierSwitchGeneratorHelper.GenerateTimeoutSwitch(_bombardierGeneratorOptions)}" +
6060
$"{BombardierSwitchGeneratorHelper.GenerateDurationSwitch(_bombardierGeneratorOptions)}" +

src/QAToolKit.Engine.Bombardier/BombardierTestsRunner.cs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -138,24 +138,13 @@ private decimal GetLatencyMiliseconds(string latency)
138138
CultureInfo cultures = new CultureInfo("en-US");
139139
var digitString = Regex.Match(latency, @"\d+.\d+");
140140
var unitString = Regex.Replace(latency, @"\d+.\d+", "");
141-
decimal digit;
142-
143-
switch (unitString)
141+
var digit = unitString switch
144142
{
145-
case "s":
146-
digit = Convert.ToDecimal(digitString.Value, cultures) * 1000;
147-
break;
148-
case "ms":
149-
digit = Convert.ToDecimal(digitString.Value, cultures);
150-
break;
151-
case "us":
152-
digit = Convert.ToDecimal(digitString.Value, cultures) / 1000;
153-
break;
154-
default:
155-
digit = Convert.ToDecimal(digitString.Value, cultures);
156-
break;
157-
}
158-
143+
"s" => Convert.ToDecimal(digitString.Value, cultures) * 1000,
144+
"ms" => Convert.ToDecimal(digitString.Value, cultures),
145+
"us" => Convert.ToDecimal(digitString.Value, cultures) / 1000,
146+
_ => Convert.ToDecimal(digitString.Value, cultures),
147+
};
159148
return digit;
160149
}
161150

src/QAToolKit.Engine.Bombardier/Helpers/GeneratorHelper.cs renamed to src/QAToolKit.Engine.Bombardier/Helpers/BombardierSwitchGeneratorHelper.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,23 @@ internal static object GenerateConcurrentSwitch(HttpRequest request, BombardierG
9393
{
9494
return $" -c {bombardierGeneratorOptions.BombardierConcurrentUsers}";
9595
}
96+
97+
/// <summary>
98+
/// Generate bombardier payload body switch
99+
/// </summary>
100+
/// <param name="request"></param>
101+
/// <param name="bombardierGeneratorOptions"></param>
102+
/// <returns></returns>
103+
internal static object GenerateBodySwitch(HttpRequest request, BombardierGeneratorOptions bombardierGeneratorOptions)
104+
{
105+
var body = HttpBodyHelper.GenerateHttpRequestBody(request, bombardierGeneratorOptions.BombardierBodyContentType, bombardierGeneratorOptions.ReplacementValues);
106+
107+
if (string.IsNullOrEmpty(body))
108+
{
109+
return String.Empty;
110+
}
111+
112+
return $" -b \"{body.Replace(@"""", @"\""")}\"";
113+
}
96114
}
97115
}
Lines changed: 10 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using Newtonsoft.Json;
22
using Newtonsoft.Json.Linq;
3+
using QAToolKit.Core.HttpRequestTools;
34
using QAToolKit.Core.Models;
45
using System;
6+
using System.Collections;
57
using System.Linq;
68
using System.Net.Http;
79

@@ -18,109 +20,28 @@ public static class HttpBodyHelper
1820
/// </summary>
1921
/// <param name="request"></param>
2022
/// <param name="useContentType"></param>
23+
/// <param name="replacementValues"></param>
2124
/// <returns></returns>
22-
internal static string GenerateJsonBody(HttpRequest request, ContentType.Enumeration useContentType)
25+
internal static string GenerateHttpRequestBody(HttpRequest request, ContentType.Enumeration useContentType, ReplacementValue[] replacementValues)
2326
{
2427
if (request.Method == HttpMethod.Get)
2528
{
2629
return String.Empty;
2730
}
2831
else
2932
{
30-
var useRequest = request.RequestBodies.FirstOrDefault(content => content.ContentType == ContentType.Enumeration.Json);
33+
if (useContentType != ContentType.Enumeration.Json)
34+
useContentType = ContentType.Enumeration.Json;
35+
36+
var useRequest = request.RequestBodies.FirstOrDefault(content => content.ContentType == useContentType);
3137

3238
if (useRequest == null)
33-
{
34-
//throw new Exception($"Request body content type '{useContentType}' not found in the HttpRequest.");
3539
return String.Empty;
36-
}
37-
38-
//generate JSON body from HttpRequest object
39-
var body = GenerateBodyJsonString(useRequest);
40-
41-
return $" -b \"{body.Replace(@"""", @"\""")}\"";
42-
}
43-
}
44-
45-
//TODO: extend to support arrays, enums, object arrays
46-
private static string GenerateBodyJsonString(RequestBody requestBody)
47-
{
48-
JObject obj = new JObject();
49-
foreach (var property in requestBody.Properties)
50-
{
51-
var propertyType = GetSimplePropertyType(property);
52-
var propertyName = GetPropertyName(property);
53-
if (propertyType == null)
54-
{
55-
//not supported yet
56-
var complextType = GetComplexPropertyType(property);
5740

41+
var replacer = new HttpRequestDataReplacer(request, replacementValues);
5842

59-
// obj.Add(new JProperty(propertyName, Convert.ChangeType(property.Value, propertyType)));
60-
}
61-
else
62-
{
63-
obj.Add(new JProperty(propertyName, Convert.ChangeType(property.Value, propertyType)));
64-
}
43+
return replacer.ReplaceRequestBodyModel(useContentType).ToString();
6544
}
66-
67-
return obj.ToString(Formatting.None);
68-
}
69-
70-
private static string GetPropertyName(Property property)
71-
{
72-
return property.Name;
73-
}
74-
75-
private static Type GetSimplePropertyType(Property property)
76-
{
77-
switch (property.Type)
78-
{
79-
case "integer":
80-
if (property.Format == "int64")
81-
{
82-
return typeof(long);
83-
}
84-
else
85-
{
86-
return typeof(int);
87-
}
88-
case "string":
89-
return typeof(string);
90-
default:
91-
return null;
92-
}
93-
}
94-
95-
private static Type GetComplexPropertyType(Property property)
96-
{
97-
switch (property.Type)
98-
{
99-
case "object":
100-
/*if (type.Equals(typeof(string)))
101-
{
102-
// if (property.Value != null)
103-
// property.Value = Faker.Lorem.Sentence(1);
104-
}
105-
*/
106-
break;
107-
case "array":
108-
foreach (var prop in property.Properties)
109-
{
110-
// prop.Value = Faker.Lorem.Sentence(1);
111-
}
112-
break;
113-
case "enum":
114-
foreach (var prop in property.Properties)
115-
{
116-
// prop.Value = Faker.Lorem.Sentence(1);
117-
}
118-
break;
119-
default:
120-
throw new Exception($"{property.Type} not valid type.");
121-
}
122-
123-
return null;
12445
}
12546
}
12647
}

src/QAToolKit.Engine.Bombardier/Helpers/HttpUrlHelper.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using QAToolKit.Core.Models;
1+
using QAToolKit.Core.HttpRequestTools;
2+
using QAToolKit.Core.Models;
23
using System;
34
using System.Collections.Generic;
45
using System.Linq;
@@ -16,22 +17,38 @@ public static class HttpUrlHelper
1617
/// Generate and replace URL parameters with replacement values
1718
/// </summary>
1819
/// <param name="request"></param>
20+
/// <param name="bombardierGeneratorOptions"></param>
1921
/// <returns></returns>
20-
internal static string GenerateUrlParameters(HttpRequest request)
22+
internal static string GenerateUrlParameters(HttpRequest request, BombardierGeneratorOptions bombardierGeneratorOptions)
2123
{
2224
var queryParameters = new Dictionary<string, string>();
2325

2426
//add query parameters
25-
foreach (var parameter in request.Parameters.Where(p => p.Value != null))
27+
foreach (var parameter in request.Parameters.Where(p => p.Value != null).Where(l => l.Location == Location.Query))
2628
{
2729
queryParameters.Add(parameter.Name, parameter.Value);
2830
}
2931

3032
var baseUrl = new Uri($"{request.BasePath}{request.Path}").ToString();
3133

34+
var url = AddQueryString(baseUrl, queryParameters).ToString();
3235

36+
// var replacer = new HttpRequestDataReplacer(request, bombardierGeneratorOptions.ReplacementValues);
3337

34-
var url = AddQueryString(baseUrl, queryParameters).ToString();
38+
//url = replacer.ReplaceUrlParameters();
39+
40+
if (bombardierGeneratorOptions.ReplacementValues != null)
41+
{
42+
foreach (var replacementValue in bombardierGeneratorOptions.ReplacementValues)
43+
{
44+
var type = replacementValue.Value.GetType();
45+
46+
if (url.Contains("{" + replacementValue.Key + "}") && type.Equals(typeof(string)))
47+
{
48+
url = url.Replace("{" + replacementValue.Key + "}", (string)replacementValue.Value);
49+
}
50+
}
51+
}
3552

3653
return url;
3754
}

src/QAToolKit.Engine.Bombardier/QAToolKit.Engine.Bombardier.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
<ItemGroup>
3535
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
36-
<PackageReference Include="QAToolKit.Core" Version="0.1.5" />
36+
<PackageReference Include="QAToolKit.Core" Version="0.1.6" />
3737
<PackageReference Include="System.Text.Encodings.Web" Version="4.7.1" />
3838
</ItemGroup>
3939

0 commit comments

Comments
 (0)