diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index a15f7417..466c2a9b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -282,6 +282,29 @@ jobs:
cd Tests
../../tools/dotnet-stryker -f ../.github/stryker/Stryker.Config.Compression.json -v "${GITHUB_REF#refs/heads/}" -r "Dashboard" -r "cleartext"
+ benchmark:
+ name: Benchmarks
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 8.0.x
+ - name: Run benchmark tests
+ run: cd Tests/Benchmarks/Testably.Abstractions.Benchmarks && dotnet run -c Release --framework net8.0 --exporters json --filter '*'
+ - name: Store benchmark results
+ uses: rhysd/github-action-benchmark@v1
+ with:
+ name: Benchmarks
+ tool: 'benchmarkdotnet'
+ output-file-path: Tests/Benchmarks/Testably.Abstractions.Benchmarks/BenchmarkDotNet.Artifacts/results/Testably.Abstractions.Benchmarks.Benchmarks-report-full-compressed.json
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ benchmark-data-dir-path: '/docs/benchmarks'
+ auto-push: true
+ alert-threshold: '150%'
+ comment-on-alert: false
+ fail-on-alert: false
+
deploy:
name: Deploy
if: startsWith(github.ref, 'refs/heads/release/')
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 97c5fb95..f02ae397 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -295,3 +295,26 @@ jobs:
-H "Authorization: token $GITHUB_TOKEN" \
-d "$body"
fi
+
+ benchmark:
+ name: Benchmarks
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 8.0.x
+ - name: Run benchmark tests
+ run: cd Tests/Benchmarks/Testably.Abstractions.Benchmarks && dotnet run -c Release --framework net8.0 --exporters json --filter '*'
+ - name: Store benchmark results
+ uses: rhysd/github-action-benchmark@v1
+ with:
+ name: Benchmarks
+ tool: 'benchmarkdotnet'
+ output-file-path: Tests/Benchmarks/Testably.Abstractions.Benchmarks/BenchmarkDotNet.Artifacts/results/Testably.Abstractions.Benchmarks.Benchmarks-report-full-compressed.json
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ auto-push: false
+ alert-threshold: '150%'
+ summary-always: true
+ comment-on-alert: true
+ fail-on-alert: true
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 9fe602fc..b8b1aecd 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -7,6 +7,7 @@
+
@@ -32,6 +33,7 @@
+
diff --git a/Testably.Abstractions.sln b/Testably.Abstractions.sln
index 6a4d696e..019ad34a 100644
--- a/Testably.Abstractions.sln
+++ b/Testably.Abstractions.sln
@@ -100,6 +100,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Testably.Abstractions.TestS
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Settings", "Settings", "{D32170F4-1455-4839-8EF4-9530F3AA642A}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{500E38FD-F587-4CC7-A7CE-10DA4AC76CE1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Testably.Abstractions.Benchmarks", "Tests\Benchmarks\Testably.Abstractions.Benchmarks\Testably.Abstractions.Benchmarks.csproj", "{459BB7E6-67C5-4C7B-99A8-09AD7D4CAE0C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -162,6 +166,10 @@ Global
{241E6413-819C-4B06-A739-4D10C2A81365}.Debug|Any CPU.Build.0 = Debug|Any CPU
{241E6413-819C-4B06-A739-4D10C2A81365}.Release|Any CPU.ActiveCfg = Release|Any CPU
{241E6413-819C-4B06-A739-4D10C2A81365}.Release|Any CPU.Build.0 = Release|Any CPU
+ {459BB7E6-67C5-4C7B-99A8-09AD7D4CAE0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {459BB7E6-67C5-4C7B-99A8-09AD7D4CAE0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {459BB7E6-67C5-4C7B-99A8-09AD7D4CAE0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {459BB7E6-67C5-4C7B-99A8-09AD7D4CAE0C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -186,6 +194,8 @@ Global
{0AEBB1A6-07D6-46DC-BC78-9771D380EBC0} = {2FDB2AAE-E5CE-483E-A1A6-EC0B0A4AD67B}
{241E6413-819C-4B06-A739-4D10C2A81365} = {D32170F4-1455-4839-8EF4-9530F3AA642A}
{D32170F4-1455-4839-8EF4-9530F3AA642A} = {61F335A6-9CE0-4040-A34F-E70B1A55077D}
+ {500E38FD-F587-4CC7-A7CE-10DA4AC76CE1} = {61F335A6-9CE0-4040-A34F-E70B1A55077D}
+ {459BB7E6-67C5-4C7B-99A8-09AD7D4CAE0C} = {500E38FD-F587-4CC7-A7CE-10DA4AC76CE1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EC4D8481-B9FD-41B5-832A-369210993DF4}
diff --git a/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.Constructor.cs b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.Constructor.cs
new file mode 100644
index 00000000..181cd6ec
--- /dev/null
+++ b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.Constructor.cs
@@ -0,0 +1,33 @@
+using BenchmarkDotNet.Attributes;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO.Abstractions;
+using System.Linq;
+using Testably.Abstractions.Testing;
+using Testably.Abstractions.Testing.Initializer;
+using MockFileSystem = Testably.Abstractions.Testing.MockFileSystem;
+
+namespace Testably.Abstractions.Benchmarks;
+
+public partial class Benchmarks
+{
+ private readonly Dictionary _testData = CreateTestData();
+
+ [Benchmark]
+ public IFileSystem ConstructorEmpty_Testably() => new MockFileSystem();
+
+ [Benchmark]
+ public IFileSystem ConstructorWithInitialization_1000_Testably() => new MockFileSystem()
+ .Initialize()
+ .With(_testData.Select(x => new FileDescription(x.Key, x.Value)).ToArray()).FileSystem;
+
+ private static Dictionary CreateTestData()
+ {
+ int filesCount = 1000;
+ int maxDirectoryDepth = 8;
+ return Enumerable.Range(0, filesCount)
+ .ToDictionary(
+ i => @$"C:\{string.Join(@"\", Enumerable.Range(0, (i % maxDirectoryDepth) + 1).Select(j => j.ToString(CultureInfo.InvariantCulture)))}\{i}.bin",
+ i => i.ToString(CultureInfo.InvariantCulture));
+ }
+}
diff --git a/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.Usage.cs b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.Usage.cs
new file mode 100644
index 00000000..18210509
--- /dev/null
+++ b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.Usage.cs
@@ -0,0 +1,22 @@
+using BenchmarkDotNet.Attributes;
+using System.IO.Abstractions;
+using MockFileSystem = Testably.Abstractions.Testing.MockFileSystem;
+
+namespace Testably.Abstractions.Benchmarks;
+
+public partial class Benchmarks
+{
+ private readonly string _directoryPath = @"C:\l1\l2\l3\l4\l5\l6\l7\l8\l9\l10";
+ private readonly string _fileContent = "some file content";
+ private readonly string _fileName = "filename.txt";
+
+ private readonly IFileSystem _fileSystem = new MockFileSystem();
+
+ [Benchmark]
+ public void CreateDirectory_Testably()
+ => _fileSystem.Directory.CreateDirectory(_directoryPath);
+
+ [Benchmark]
+ public void WriteFile_Testably()
+ => _fileSystem.File.WriteAllText(_fileName, _fileContent);
+}
diff --git a/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.cs b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.cs
new file mode 100644
index 00000000..7c63df51
--- /dev/null
+++ b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Benchmarks.cs
@@ -0,0 +1,9 @@
+using BenchmarkDotNet.Attributes;
+
+namespace Testably.Abstractions.Benchmarks;
+
+[RPlotExporter]
+[MemoryDiagnoser]
+public partial class Benchmarks
+{
+}
diff --git a/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Program.cs b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Program.cs
new file mode 100644
index 00000000..94780f0c
--- /dev/null
+++ b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Program.cs
@@ -0,0 +1,11 @@
+using BenchmarkDotNet.Running;
+
+namespace Testably.Abstractions.Benchmarks;
+
+internal static class Program
+{
+ public static void Main(string[] args)
+ {
+ BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
+ }
+}
diff --git a/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Testably.Abstractions.Benchmarks.csproj b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Testably.Abstractions.Benchmarks.csproj
new file mode 100644
index 00000000..8daef84b
--- /dev/null
+++ b/Tests/Benchmarks/Testably.Abstractions.Benchmarks/Testably.Abstractions.Benchmarks.csproj
@@ -0,0 +1,17 @@
+
+
+ false
+ false
+ Exe
+ false
+ ..\..\..\Build\Tests\$(MSBuildProjectName)
+ net8.0
+ $(NoWarn);MA0049
+
+
+
+
+
+
+
+