diff --git a/.gitignore b/.gitignore index 14e94713d..93dae7365 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,10 @@ test-results/ playwright-report/ blob-report/ playwright/.cache/ +/packages/metrics-dotnet/Mutation.Metrics.CLI/bin +/packages/metrics-dotnet/Mutation.Metrics.CLI/obj +/packages/metrics-dotnet/Mutation.Metrics.Tests/bin +/packages/metrics-dotnet/Mutation.Metrics.Tests/obj +/packages/metrics-dotnet/MutationMetrics/.vs +/packages/metrics-dotnet/MutationMetrics/bin +/packages/metrics-dotnet/MutationMetrics/obj diff --git a/packages/metrics-dotnet/Mutation.Metrics.CLI/Mutation.Metrics.CLI.csproj b/packages/metrics-dotnet/Mutation.Metrics.CLI/Mutation.Metrics.CLI.csproj new file mode 100644 index 000000000..86b5a02d3 --- /dev/null +++ b/packages/metrics-dotnet/Mutation.Metrics.CLI/Mutation.Metrics.CLI.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/packages/metrics-dotnet/Mutation.Metrics.CLI/Program.cs b/packages/metrics-dotnet/Mutation.Metrics.CLI/Program.cs new file mode 100644 index 000000000..df8f75483 --- /dev/null +++ b/packages/metrics-dotnet/Mutation.Metrics.CLI/Program.cs @@ -0,0 +1,13 @@ +using Mutation.Metrics.Core; +using System.Text.Json; + + +for (int i = 0; i < args?.Length; i++) +{ + if (args[i] == "--reporter") + { + var report = Metrics.GenerateScore(args[i+1]); + var json = JsonSerializer.Serialize(report); + Console.WriteLine(json); + } +} diff --git a/packages/metrics-dotnet/Mutation.Metrics.Tests/GlobalUsings.cs b/packages/metrics-dotnet/Mutation.Metrics.Tests/GlobalUsings.cs new file mode 100644 index 000000000..8c927eb74 --- /dev/null +++ b/packages/metrics-dotnet/Mutation.Metrics.Tests/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/packages/metrics-dotnet/Mutation.Metrics.Tests/Metrics/MetricsTest.cs b/packages/metrics-dotnet/Mutation.Metrics.Tests/Metrics/MetricsTest.cs new file mode 100644 index 000000000..75e0cca0e --- /dev/null +++ b/packages/metrics-dotnet/Mutation.Metrics.Tests/Metrics/MetricsTest.cs @@ -0,0 +1,15 @@ +using FluentAssertions; + +namespace Mutation.Metrics.Core +{ + public class MetricsTest + { + + [Fact] + public void Metrics_GenerateScore_Success() + { + var result = Metrics.GenerateScore("ReportSample//stryker-report.json"); + result.Covered.Should().Be(24); + } + } +} \ No newline at end of file diff --git a/packages/metrics-dotnet/Mutation.Metrics.Tests/Mutation.Metrics.Tests.csproj b/packages/metrics-dotnet/Mutation.Metrics.Tests/Mutation.Metrics.Tests.csproj new file mode 100644 index 000000000..e8497e7c6 --- /dev/null +++ b/packages/metrics-dotnet/Mutation.Metrics.Tests/Mutation.Metrics.Tests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/packages/metrics-dotnet/Mutation.Metrics.Tests/ReportSample/stryker-report.json b/packages/metrics-dotnet/Mutation.Metrics.Tests/ReportSample/stryker-report.json new file mode 100644 index 000000000..5d698ec36 --- /dev/null +++ b/packages/metrics-dotnet/Mutation.Metrics.Tests/ReportSample/stryker-report.json @@ -0,0 +1,1378 @@ +{ + "schemaVersion": "2", + "thresholds": { + "high": 80, + "low": 60 + }, + "projectRoot": "/home/user/src/project/", + "files": { + "/home/user/src/project/1/SomeFile0.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "1", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "2", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "3", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "4", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "5", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "6", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/1/SomeFile1.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "7", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "8", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "9", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "10", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "11", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "12", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/1/SomeFile2.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "13", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "14", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "15", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "16", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "17", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "18", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/1/SomeFile3.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "19", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "20", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "21", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "22", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "23", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "24", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/1/SomeFile4.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "25", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "26", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "27", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "28", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "29", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "30", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/1/SomeFile5.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "31", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "32", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "33", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "34", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "35", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "36", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/2/SomeFile0.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "37", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "38", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "39", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "40", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "41", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "42", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/2/SomeFile1.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "43", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "44", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "45", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "46", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "47", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "48", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/2/SomeFile2.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "49", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "50", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "51", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "52", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "53", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "54", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/2/SomeFile3.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "55", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "56", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "57", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "58", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "59", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "60", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/2/SomeFile4.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "61", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "62", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "63", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "64", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "65", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "66", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + }, + "/home/user/src/project/2/SomeFile5.cs": { + "language": "cs", + "source": "void M(){ int i = 0 \u002B 8; }", + "mutants": [ + { + "id": "67", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "68", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "69", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "70", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Killed", + "static": false, + "killedBy": [] + }, + { + "id": "71", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + }, + { + "id": "72", + "mutatorName": "This name should display", + "replacement": "0 -8", + "location": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "status": "Survived", + "static": false, + "killedBy": [] + } + ] + } + } +} \ No newline at end of file diff --git a/packages/metrics-dotnet/MutationMetrics/Metrics.cs b/packages/metrics-dotnet/MutationMetrics/Metrics.cs new file mode 100644 index 000000000..ec8594c76 --- /dev/null +++ b/packages/metrics-dotnet/MutationMetrics/Metrics.cs @@ -0,0 +1,70 @@ +using Mutation.Metrics.Core.Models; +using System.Text.Json; + +namespace Mutation.Metrics.Core +{ + public static class Metrics + { + public static MetricResult GenerateScore(string fullPath) + { + try + { + double killed = 0; + double timeOut = 0; + double survived = 0; + double noCoverage = 0; + double runtimeErrors = 0; + double compileErrors = 0; + double ignored = 0; + double pending = 0; + + using StreamReader reader = new(fullPath); + var reporterFile = reader.ReadToEnd(); + + JsonReport report = JsonSerializer.Deserialize(reporterFile, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + + foreach (var files in (report.Files)) + { + foreach (var mutants in files.Value.Mutants) + { + var status = Enum.Parse(mutants.Status); + switch (status) + { + case MutantStatus.Killed: + killed++; + break; + case MutantStatus.Timeout: + timeOut++; + break; + case MutantStatus.Survived: + survived++; + break; + case MutantStatus.NoCoverage: + noCoverage++; + break; + case MutantStatus.CompileError: + compileErrors++; + break; + case MutantStatus.Ignored: + ignored++; + break; + case MutantStatus.Pending: + pending++; + break; + case MutantStatus.RunTimeError: + runtimeErrors++; + break; + } + } + } + return new MetricResult(killed, timeOut, survived, noCoverage, runtimeErrors, compileErrors, ignored, pending); + } + catch (IOException e) + { + Console.WriteLine("The file could not be read:"); + Console.WriteLine(e.Message); + } + return new MetricResult(); + } + } +} diff --git a/packages/metrics-dotnet/MutationMetrics/Models/JsonReport.cs b/packages/metrics-dotnet/MutationMetrics/Models/JsonReport.cs new file mode 100644 index 000000000..28712b2e4 --- /dev/null +++ b/packages/metrics-dotnet/MutationMetrics/Models/JsonReport.cs @@ -0,0 +1,19 @@ +namespace Mutation.Metrics.Core.Models +{ + public struct JsonReport + { + public string SchemaVersion { get; set; } + public IDictionary Thresholds { get; set; } + public IDictionary Files { get; set; } + } + + public struct SourceFile + { + public ISet Mutants { get; set; } + } + + public struct JsonMutant + { + public string Status { get; set; } + } +} diff --git a/packages/metrics-dotnet/MutationMetrics/Models/MetricResult.cs b/packages/metrics-dotnet/MutationMetrics/Models/MetricResult.cs new file mode 100644 index 000000000..da78e1e74 --- /dev/null +++ b/packages/metrics-dotnet/MutationMetrics/Models/MetricResult.cs @@ -0,0 +1,27 @@ +namespace Mutation.Metrics.Core.Models +{ + public struct MetricResult + { + public double Detected { get; private set; } + public double Undetected { get; private set; } + public double Covered { get; private set; } + public double Valid { get; private set; } + public double Invalid { get; private set; } + public double TotalMutants { get; private set; } + public double MutatioScore { get; private set; } + public double MutatioScoreBasedOnCoveredCode { get; private set; } + + + public MetricResult(double killed, double timeOut, double survived, double noCoverage, double runtimeErrors, double compileErrors, double ignored, double pending) + { + Detected = killed + timeOut; + Undetected = survived + noCoverage; + Covered = Detected + survived; + Valid = Detected+ Undetected; + Invalid = runtimeErrors + compileErrors; + TotalMutants = Valid + Invalid + ignored + pending; + MutatioScore = (Detected / Valid) * 100; + MutatioScoreBasedOnCoveredCode = (Detected / Covered) * 100; + } + } +} diff --git a/packages/metrics-dotnet/MutationMetrics/Models/MutantStatus.cs b/packages/metrics-dotnet/MutationMetrics/Models/MutantStatus.cs new file mode 100644 index 000000000..e58d67f91 --- /dev/null +++ b/packages/metrics-dotnet/MutationMetrics/Models/MutantStatus.cs @@ -0,0 +1,14 @@ +namespace Mutation.Metrics.Core.Models +{ + public enum MutantStatus + { + Pending, + Killed, + Survived, + Timeout, + CompileError, + RunTimeError, + Ignored, + NoCoverage + } +} diff --git a/packages/metrics-dotnet/MutationMetrics/Mutation.Metrics.Core.csproj b/packages/metrics-dotnet/MutationMetrics/Mutation.Metrics.Core.csproj new file mode 100644 index 000000000..fa71b7ae6 --- /dev/null +++ b/packages/metrics-dotnet/MutationMetrics/Mutation.Metrics.Core.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/packages/metrics-dotnet/MutationMetrics/MutationMetrics.sln b/packages/metrics-dotnet/MutationMetrics/MutationMetrics.sln new file mode 100644 index 000000000..36661c28b --- /dev/null +++ b/packages/metrics-dotnet/MutationMetrics/MutationMetrics.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34525.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mutation.Metrics.Core", "Mutation.Metrics.Core.csproj", "{2E2712FE-1DA1-4F43-8463-64F8B4746B0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mutation.Metrics.Tests", "..\Mutation.Metrics.Tests\Mutation.Metrics.Tests.csproj", "{E15C8608-9235-4DFA-9F36-3349F8B97A93}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mutation.Metrics.CLI", "..\Mutation.Metrics.CLI\Mutation.Metrics.CLI.csproj", "{9056BD21-9CFF-4952-BC80-48B152CAB4A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2E2712FE-1DA1-4F43-8463-64F8B4746B0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E2712FE-1DA1-4F43-8463-64F8B4746B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E2712FE-1DA1-4F43-8463-64F8B4746B0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E2712FE-1DA1-4F43-8463-64F8B4746B0D}.Release|Any CPU.Build.0 = Release|Any CPU + {E15C8608-9235-4DFA-9F36-3349F8B97A93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E15C8608-9235-4DFA-9F36-3349F8B97A93}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E15C8608-9235-4DFA-9F36-3349F8B97A93}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E15C8608-9235-4DFA-9F36-3349F8B97A93}.Release|Any CPU.Build.0 = Release|Any CPU + {9056BD21-9CFF-4952-BC80-48B152CAB4A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9056BD21-9CFF-4952-BC80-48B152CAB4A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9056BD21-9CFF-4952-BC80-48B152CAB4A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9056BD21-9CFF-4952-BC80-48B152CAB4A8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D3F1A0FC-3272-415F-8D7D-6E5B68F8CA20} + EndGlobalSection +EndGlobal