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

Enhance console output with Spectre Console #8

Merged
merged 4 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .idea/.idea.Rucksack/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions Rucksack.ConsoleExample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

using Rucksack;
using Rucksack.LoadStrategies;

int completedTasks = 0;

await LoadTestRunner.Run(() =>
{
var index = Interlocked.Increment(ref completedTasks);

return index switch
{
_ when index % 3 == 0 => Task.FromException(new ArgumentOutOfRangeException("arg", "Bad argument!")),
_ when index % 5 == 0 => Task.FromException(new InvalidOperationException("Invalid operation!")),
_ => Task.Delay(TimeSpan.FromSeconds(1.1))
};
}, new LoadTestOptions
{
LoadStrategy = new SequentialLoadStrategy(TimeSpan.FromSeconds(1))
{
new OneShotLoadStrategy(10),
new OneShotLoadStrategy(20),
new OneShotLoadStrategy(15),
new OneShotLoadStrategy(25),
new OneShotLoadStrategy(30)
}
});
14 changes: 14 additions & 0 deletions Rucksack.ConsoleExample/Rucksack.ConsoleExample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Rucksack\Rucksack.csproj" />
</ItemGroup>

</Project>
142 changes: 46 additions & 96 deletions Rucksack.Tests/BasicIntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Rucksack.LoadStrategies;
using Rucksack.Tests.Util;
using Xunit.Abstractions;
using static System.TimeSpan;

Expand All @@ -18,14 +19,7 @@ await LoadTestRunner.Run(() =>
{
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
}, new LoadTestOptions
{
LoadStrategy = new OneShotLoadStrategy(count),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
}, LoadTestOptionsFactory.Create(new OneShotLoadStrategy(count), testOutputHelper));

executionCount.Should().Be(count);
}
Expand All @@ -45,14 +39,7 @@ await LoadTestRunner.Run(() =>
{
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
}, new LoadTestOptions
{
LoadStrategy = new RepeatBurstLoadStrategy(count, interval, duration),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
}, LoadTestOptionsFactory.Create(new RepeatBurstLoadStrategy(count, interval, duration), testOutputHelper));

executionCount.Should().Be(count * durationSeconds / intervalSeconds);
}
Expand All @@ -67,17 +54,12 @@ public async Task BasicSteppedBurstIntegrationTest()
const int expected = 75; // 5 + 10 + 15 + 20 + 25

await LoadTestRunner.Run(() =>
{
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
}, new LoadTestOptions
{
LoadStrategy = new SteppedBurstLoadStrategy(step, from, to, FromSeconds(1)),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
},
LoadTestOptionsFactory.Create(new SteppedBurstLoadStrategy(step, from, to, FromSeconds(1)),
testOutputHelper));

executionCount.Should().Be(expected);
}
Expand All @@ -93,17 +75,12 @@ public async Task BasicConstantUserLoadIntegrationTest()
const int expected = 25;

await LoadTestRunner.Run(() =>
{
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
}, new LoadTestOptions
{
LoadStrategy = new ConstantUserLoadStrategy(count, FromSeconds(1), FromSeconds(5)),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
},
LoadTestOptionsFactory.Create(new ConstantUserLoadStrategy(count, FromSeconds(1), FromSeconds(5)),
testOutputHelper));

executionCount.Should().Be(expected);
}
Expand All @@ -119,21 +96,16 @@ public async Task BasicConstantUserLoadIntegrationTest_WithLongRunningTask()
const int expected = 21;

await LoadTestRunner.Run(async () =>
{
int value = Interlocked.Increment(ref executionCount);

if (value == 1)
{
await Task.Delay(5000);
}
}, new LoadTestOptions
{
LoadStrategy = new ConstantUserLoadStrategy(count, FromSeconds(1), FromSeconds(5)),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
int value = Interlocked.Increment(ref executionCount);

if (value == 1)
{
await Task.Delay(5000);
}
},
LoadTestOptionsFactory.Create(new ConstantUserLoadStrategy(count, FromSeconds(1), FromSeconds(5)),
testOutputHelper));

executionCount.Should().Be(expected);
}
Expand All @@ -151,17 +123,13 @@ public async Task BasicSteppedUserLoadIntegrationTest()
const int expected = 75;

await LoadTestRunner.Run(() =>
{
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
}, new LoadTestOptions
{
LoadStrategy = new SteppedUserLoadStrategy(step, from, to, FromSeconds(1), FromSeconds(1), FromSeconds(5)),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
},
LoadTestOptionsFactory.Create(
new SteppedUserLoadStrategy(step, from, to, FromSeconds(1), FromSeconds(1), FromSeconds(5)),
testOutputHelper));

executionCount.Should().Be(expected);
}
Expand All @@ -179,21 +147,17 @@ public async Task BasicSteppedUserLoadIntegrationTest_WithLongRunningTask()
const int expected = 71;

await LoadTestRunner.Run(async () =>
{
int value = Interlocked.Increment(ref executionCount);

if (value == 1)
{
await Task.Delay(5000);
}
}, new LoadTestOptions
{
LoadStrategy = new SteppedUserLoadStrategy(step, from, to, FromSeconds(1), FromSeconds(1), FromSeconds(5)),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
int value = Interlocked.Increment(ref executionCount);

if (value == 1)
{
await Task.Delay(5000);
}
},
LoadTestOptionsFactory.Create(
new SteppedUserLoadStrategy(step, from, to, FromSeconds(1), FromSeconds(1), FromSeconds(5)),
testOutputHelper));

executionCount.Should().Be(expected);
}
Expand All @@ -209,21 +173,14 @@ await LoadTestRunner.Run(() =>
{
Interlocked.Increment(ref executionCount);
return Task.CompletedTask;
}, new LoadTestOptions
}, LoadTestOptionsFactory.Create(new SequentialLoadStrategy(FromSeconds(1))
{
LoadStrategy = new SequentialLoadStrategy(FromSeconds(1))
{
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
},
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
new OneShotLoadStrategy(count),
}, testOutputHelper));

executionCount.Should().Be(expected);
}
Expand All @@ -245,14 +202,7 @@ await LoadTestRunner.Run(async () =>
var delay = random.Next(1000, 5000);
await Task.Delay(delay);
Interlocked.Increment(ref executionCount);
}, new LoadTestOptions
{
LoadStrategy = new RepeatBurstLoadStrategy(count, interval, duration),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
}, LoadTestOptionsFactory.Create(new RepeatBurstLoadStrategy(count, interval, duration), testOutputHelper));

executionCount.Should().Be(count * durationSeconds / intervalSeconds);
}
Expand Down
20 changes: 4 additions & 16 deletions Rucksack.Tests/EmptyIntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Rucksack.LoadStrategies;
using Rucksack.Tests.Util;
using Spectre.Console;
using Xunit.Abstractions;

namespace Rucksack.Tests;
Expand All @@ -15,14 +17,7 @@ public void EmptyIntegrationTest()
LoadTestRunner.Run(() =>
{
executed = true;
}, new LoadTestOptions
{
LoadStrategy = new OneShotLoadStrategy(1),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
}, LoadTestOptionsFactory.Create(new OneShotLoadStrategy(1), testOutputHelper));

executed.Should().BeTrue();
}
Expand All @@ -36,14 +31,7 @@ await LoadTestRunner.Run(async () =>
{
await Task.Delay(100);
executed = true;
}, new LoadTestOptions
{
LoadStrategy = new OneShotLoadStrategy(1),
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
});
}, LoadTestOptionsFactory.Create(new OneShotLoadStrategy(1), testOutputHelper));

executed.Should().BeTrue();
}
Expand Down
1 change: 1 addition & 0 deletions Rucksack.Tests/Rucksack.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="MartinCostello.Logging.XUnit" Version="0.4.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Spectre.Console.Testing" Version="0.49.1" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
Expand Down
24 changes: 24 additions & 0 deletions Rucksack.Tests/Util/LoadTestOptionsFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.Extensions.Logging;
using Spectre.Console;
using Xunit.Abstractions;

namespace Rucksack.Tests.Util;

public static class LoadTestOptionsFactory
{
public static LoadTestOptions Create(ILoadStrategy strategy, ITestOutputHelper testOutputHelper)
=> new()
{
LoadStrategy = strategy,
LoggerFactory = LoggerFactory.Create(builder =>
{
builder.AddXUnit(testOutputHelper);
}),
Console = AnsiConsole.Create(new AnsiConsoleSettings
{
Ansi = AnsiSupport.No,
ColorSystem = ColorSystemSupport.NoColors,
Out = new AnsiConsoleOutput(new TestOutputHelperTextWriterAdapter(testOutputHelper)),
})
};
}
40 changes: 40 additions & 0 deletions Rucksack.Tests/Util/TestOutputHelperTextWriterAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Text;
using Xunit.Abstractions;

namespace Rucksack.Tests.Util;

public class TestOutputHelperTextWriterAdapter(ITestOutputHelper output)
: TextWriter
{
private string currentLine = "";

public override void Write(char value)
{
if (value == '\n')
{
WriteCurrentLine();
}
else
{
currentLine += value;
}
}

public override Encoding Encoding => Encoding.Default;

private void WriteCurrentLine()
{
output.WriteLine(currentLine);
currentLine = "";
}

protected override void Dispose(bool disposing)
{
if (currentLine != "")
{
WriteCurrentLine();
}

base.Dispose(disposing);
}
}
6 changes: 6 additions & 0 deletions Rucksack.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rucksack", "Rucksack\Rucksa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rucksack.Tests", "Rucksack.Tests\Rucksack.Tests.csproj", "{DAFD1A96-C7A4-44AD-ACFA-BAF42A02035E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rucksack.ConsoleExample", "Rucksack.ConsoleExample\Rucksack.ConsoleExample.csproj", "{662F7ACE-7319-42FA-A737-9004F331337E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -18,5 +20,9 @@ Global
{DAFD1A96-C7A4-44AD-ACFA-BAF42A02035E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAFD1A96-C7A4-44AD-ACFA-BAF42A02035E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAFD1A96-C7A4-44AD-ACFA-BAF42A02035E}.Release|Any CPU.Build.0 = Release|Any CPU
{662F7ACE-7319-42FA-A737-9004F331337E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{662F7ACE-7319-42FA-A737-9004F331337E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{662F7ACE-7319-42FA-A737-9004F331337E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{662F7ACE-7319-42FA-A737-9004F331337E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Loading