diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 000000000..c7b5bc9ce --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-stryker": { + "version": "3.10.0", + "commands": [ + "dotnet-stryker" + ] + } + } +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 075b1386d..efc54c6d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,21 +2,25 @@ name: build on: pull_request: - branches: [ "master" ] + branches: ["master"] push: - branches: [ "master" ] - + branches: ["master"] jobs: build: - runs-on: windows-latest steps: - - uses: actions/checkout@v3 - - name: Setup .NET - uses: actions/setup-dotnet@v2 - with: - dotnet-version: 6.0.x - - name: Run nuke build - run: ./build.ps1 + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v2 + with: + dotnet-version: 6.0.x + - name: Build + run: ./build.ps1 Compile + - name: Unit Test + run: ./build.ps1 RunUnitTests --skip Compile + - name: Mutation Test + run: ./build.ps1 RunMutationTests --skip RunUnitTests + env: + STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/.gitignore b/.gitignore index 37731856c..2ad38f682 100644 --- a/.gitignore +++ b/.gitignore @@ -673,3 +673,4 @@ fabric.properties ocelot.json /src/2-Services/Identity/Api/Identity.Api/keys /src/6-Docker/mssqldata/Entropy.bin +/.nuke/temp/execution-plan.html diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 607f91310..0801fcd2d 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -76,6 +76,8 @@ "Information", "Preparation", "Restore", + "RestoreDotNetTool", + "RunMutationTests", "RunUnitTests" ] } @@ -95,6 +97,8 @@ "Information", "Preparation", "Restore", + "RestoreDotNetTool", + "RunMutationTests", "RunUnitTests" ] } diff --git a/src/1-BuildingBlocks/Web.MVC/Exceptions/GrpcGlobalExceptionHandler.cs b/src/1-BuildingBlocks/Web.MVC/Exceptions/GrpcGlobalExceptionHandler.cs index 0a42e5dca..79b16bb69 100644 --- a/src/1-BuildingBlocks/Web.MVC/Exceptions/GrpcGlobalExceptionHandler.cs +++ b/src/1-BuildingBlocks/Web.MVC/Exceptions/GrpcGlobalExceptionHandler.cs @@ -1,6 +1,7 @@ using Grpc.Core; using Grpc.Core.Interceptors; using Microsoft.Extensions.Logging; +using System.Text.Json; namespace TaskoMask.BuildingBlocks.Web.MVC.Exceptions { @@ -27,7 +28,7 @@ public override async Task UnaryServerHandler( } catch (Exception exception) { - _logger.LogError(exception, exception.Message); + _logger.LogError(exception, $"request : {JsonSerializer.Serialize(request)}"); throw new RpcException(new Status(StatusCode.Cancelled, exception.Message)); } diff --git a/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/Boards.Write.Tests.Unit.csproj b/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/Boards.Write.Tests.Unit.csproj index dcf29e275..25922d1b4 100644 --- a/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/Boards.Write.Tests.Unit.csproj +++ b/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/Boards.Write.Tests.Unit.csproj @@ -22,6 +22,7 @@ + diff --git a/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/stryker-config.json b/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/stryker-config.json new file mode 100644 index 000000000..2ea2af5f3 --- /dev/null +++ b/src/2-Services/Boards/Tests/Boards.Write.Tests.Unit/stryker-config.json @@ -0,0 +1,23 @@ +{ + "stryker-config": { + "solution": "../../../../../TaskoMask.sln", + "project": "Boards.Write.Api.csproj", + "thresholds": { + "high": 90, + "low": 60, + "break": 30 + }, + "mutate": [ + "**/*UseCase.cs" + ], + "reporters": [ + "html", + "progress" + ], + "project-info": { + "module": "TaskoMask", + "name": "github.com/hamed-shirbandi/taskomask", + "version": "master" + } + } +} \ No newline at end of file diff --git a/src/2-Services/Identity/Tests/Identity.Tests.Unit/StrykerOutput/2023-10-08.15-03-19/reports/mutation-report.html b/src/2-Services/Identity/Tests/Identity.Tests.Unit/StrykerOutput/2023-10-08.15-03-19/reports/mutation-report.html new file mode 100644 index 000000000..0e6c361f8 --- /dev/null +++ b/src/2-Services/Identity/Tests/Identity.Tests.Unit/StrykerOutput/2023-10-08.15-03-19/reports/mutation-report.html @@ -0,0 +1,315 @@ + + + + + + + + + + Your browser doesn't support custom elements. + Please use a latest version of an evergreen browser (Firefox, Chrome, Safari, Opera, etc). + + + + + diff --git a/src/2-Services/Identity/Tests/Identity.Tests.Unit/stryker-config.json b/src/2-Services/Identity/Tests/Identity.Tests.Unit/stryker-config.json new file mode 100644 index 000000000..d3a9389fc --- /dev/null +++ b/src/2-Services/Identity/Tests/Identity.Tests.Unit/stryker-config.json @@ -0,0 +1,23 @@ +{ + "stryker-config": { + "solution": "../../../../../TaskoMask.sln", + "project": "Identity.Api.csproj", + "thresholds": { + "high": 90, + "low": 60, + "break": 30 + }, + "mutate": [ + "**/*UseCase.cs" + ], + "reporters": [ + "html", + "progress" + ], + "project-info": { + "module": "TaskoMask", + "name": "github.com/hamed-shirbandi/taskomask", + "version": "master" + } + } +} \ No newline at end of file diff --git a/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/Owners.Write.Tests.Unit.csproj b/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/Owners.Write.Tests.Unit.csproj index 4c4ff6555..4587ee781 100644 --- a/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/Owners.Write.Tests.Unit.csproj +++ b/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/Owners.Write.Tests.Unit.csproj @@ -21,6 +21,7 @@ + diff --git a/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/stryker-config.json b/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/stryker-config.json new file mode 100644 index 000000000..382efdd94 --- /dev/null +++ b/src/2-Services/Owners/Tests/Owners.Write.Tests.Unit/stryker-config.json @@ -0,0 +1,23 @@ +{ + "stryker-config": { + "solution": "../../../../../TaskoMask.sln", + "project": "Owners.Write.Api.csproj", + "thresholds": { + "high": 90, + "low": 60, + "break": 30 + }, + "mutate": [ + "**/*UseCase.cs" + ], + "reporters": [ + "html", + "progress" + ], + "project-info": { + "module": "TaskoMask", + "name": "github.com/hamed-shirbandi/taskomask", + "version": "master" + } + } +} \ No newline at end of file diff --git a/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/Tasks.Write.Tests.Unit.csproj b/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/Tasks.Write.Tests.Unit.csproj index 99781c665..424f35b69 100644 --- a/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/Tasks.Write.Tests.Unit.csproj +++ b/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/Tasks.Write.Tests.Unit.csproj @@ -22,6 +22,7 @@ + diff --git a/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/stryker-config.json b/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/stryker-config.json new file mode 100644 index 000000000..104e07289 --- /dev/null +++ b/src/2-Services/Tasks/Tests/Tasks.Write.Tests.Unit/stryker-config.json @@ -0,0 +1,23 @@ +{ + "stryker-config": { + "solution": "../../../../../TaskoMask.sln", + "project": "Tasks.Write.Api.csproj", + "thresholds": { + "high": 90, + "low": 60, + "break": 30 + }, + "mutate": [ + "**/*UseCase.cs" + ], + "reporters": [ + "html", + "progress" + ], + "project-info": { + "module": "TaskoMask", + "name": "github.com/hamed-shirbandi/taskomask", + "version": "master" + } + } +} \ No newline at end of file diff --git a/src/6-Build/Build.cs b/src/6-Build/Build.cs index e40848270..4e74aeea3 100644 --- a/src/6-Build/Build.cs +++ b/src/6-Build/Build.cs @@ -14,11 +14,10 @@ using static Nuke.Common.Tools.NuGet.NuGetTasks; using static Nuke.Common.Tools.NuGet.NuGetPackSettingsExtensions; using Nuke.Common.IO; -using Nuke.Common.Utilities.Collections; class Build : NukeBuild { - public static int Main() => Execute(x => x.RunUnitTests); + public static int Main() => Execute(x => x.RunMutationTests); [Parameter] readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; @@ -27,10 +26,9 @@ class Build : NukeBuild readonly Solution Solution; [Parameter] - AbsolutePath TestResultDirectory = RootDirectory + "/Artifacts/Test-Results/"; + AbsolutePath TestResultDirectory = RootDirectory + "/.nuke/Artifacts/Test-Results/"; Target Information => _ => _ - .Before(Preparation) .Executes(() => { Log.Information($"Solution path : {Solution}"); @@ -46,6 +44,12 @@ class Build : NukeBuild TestResultDirectory.CreateOrCleanDirectory(); }); + Target RestoreDotNetTool => _ => _ + .Executes(() => + { + DotNet(arguments: "tool restore"); + }); + Target Clean => _ => _ .DependsOn(Preparation) .Executes(() => @@ -91,4 +95,21 @@ class Build : NukeBuild .AddLoggers($"trx;LogFileName={z.Name}.trx") .SetCoverletOutput(TestResultDirectory + $"{z.Name}.xml"))); }); + + Target RunMutationTests => _ => _ + .DependsOn(RunUnitTests,RestoreDotNetTool) + .Executes(() => + { + //It uses dashboard report for CI + string report = "--reporter dashboard"; + + //It uses reports specified in reports section in stryker-config.json + if (IsLocalBuild) + report = ""; + + var testProjects = Solution.AllProjects.Where(s => s.Name.EndsWith(".Tests.Unit")); + + foreach (var testProject in testProjects) + DotNet(workingDirectory: testProject.Directory, arguments: $"stryker {report}"); + }); }