Skip to content

Commit

Permalink
Add [DoesNotReturn] attribute to instruct code coverage about unreach…
Browse files Browse the repository at this point in the history
…able lines
  • Loading branch information
jnyrup committed Mar 13, 2022
1 parent 19e8476 commit 430b367
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 8 deletions.
24 changes: 17 additions & 7 deletions Build/Build.cs
Expand Up @@ -50,12 +50,15 @@ class Build : NukeBuild

AbsolutePath ArtifactsDirectory => RootDirectory / "Artifacts";

AbsolutePath TestResultsDirectory => RootDirectory / "TestResults";

string SemVer;

Target Clean => _ => _
.Executes(() =>
{
EnsureCleanDirectory(ArtifactsDirectory);
EnsureCleanDirectory(TestResultsDirectory);
});

Target CalculateNugetVersion => _ => _
Expand Down Expand Up @@ -140,7 +143,10 @@ class Build : NukeBuild
.SetConfiguration("Debug")
.EnableNoBuild()
.SetDataCollector("XPlat Code Coverage")
.SetResultsDirectory(RootDirectory / "TestResults")
.SetResultsDirectory(TestResultsDirectory)
.AddRunSetting(
"DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.DoesNotReturnAttribute",
"DoesNotReturnAttribute")
.CombineWith(
projects,
(_, project) => _
Expand All @@ -160,14 +166,15 @@ class Build : NukeBuild
{
ReportGenerator(s => s
.SetProcessToolPath(ToolPathResolver.GetPackageExecutable("ReportGenerator", "ReportGenerator.dll", framework: "net6.0"))
.SetTargetDirectory(RootDirectory / "TestResults" / "reports")
.AddReports(RootDirectory / "TestResults/**/coverage.cobertura.xml")
.SetTargetDirectory(TestResultsDirectory / "reports")
.AddReports(TestResultsDirectory / "**/coverage.cobertura.xml")
.AddReportTypes("HtmlInline_AzurePipelines_Dark", "lcov")
.SetClassFilters("-System.Diagnostics.CodeAnalysis.StringSyntaxAttribute")
.SetClassFilters(
"-System.Diagnostics.CodeAnalysis.StringSyntaxAttribute",
"-System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute")
.SetAssemblyFilters("+FluentAssertions"));
string link = RootDirectory / "TestResults" / "reports" / "index.html";
string link = TestResultsDirectory / "reports" / "index.html";
Serilog.Log.Information($"Code coverage report: \x1b]8;;file://{link.Replace('\\', '/')}\x1b\\{link}\x1b]8;;\x1b\\");
});

Expand All @@ -192,7 +199,10 @@ class Build : NukeBuild
.SetConfiguration("Debug")
.EnableNoBuild()
.SetDataCollector("XPlat Code Coverage")
.SetResultsDirectory(RootDirectory / "TestResults")
.SetResultsDirectory(TestResultsDirectory)
.AddRunSetting(
"DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.DoesNotReturnAttribute",
"DoesNotReturnAttribute")
.CombineWith(
testCombinations,
(_, v) => _.SetProjectFile(v.project).SetFramework(v.framework)));
Expand Down
2 changes: 2 additions & 0 deletions Src/FluentAssertions/AssertionExtensions.cs
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq.Expressions;
using System.Net.Http;
Expand Down Expand Up @@ -999,6 +1000,7 @@ public static void Should(this TypeSelectorAssertions _)
InvalidShouldCall();
}

[DoesNotReturn]
private static void InvalidShouldCall()
{
throw new InvalidOperationException("You are asserting the 'AndConstraint' itself. Remove the 'Should()' method directly following 'And'.");
Expand Down
1 change: 1 addition & 0 deletions Src/FluentAssertions/Common/Services.cs
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using FluentAssertions.Execution;

namespace FluentAssertions.Common
Expand Down
18 changes: 18 additions & 0 deletions Src/FluentAssertions/DoesNotReturnAttribute.cs
@@ -0,0 +1,18 @@
// copied from https://source.dot.net/#System.Private.CoreLib/NullableAttributes.cs
#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>Applied to a method that will never return under any circumstance.</summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
#if SYSTEM_PRIVATE_CORELIB
public
#else
internal
#endif
sealed class DoesNotReturnAttribute : Attribute
{
}
}
#endif
3 changes: 3 additions & 0 deletions Src/FluentAssertions/Execution/FallbackTestFramework.cs
@@ -1,3 +1,5 @@
using System.Diagnostics.CodeAnalysis;

namespace FluentAssertions.Execution
{
/// <summary>
Expand All @@ -13,6 +15,7 @@ internal class FallbackTestFramework : ITestFramework
/// <summary>
/// Throws a framework-specific exception to indicate a failing unit test.
/// </summary>
[DoesNotReturn]
public void Throw(string message)
{
throw new AssertionFailedException(message);
Expand Down
5 changes: 4 additions & 1 deletion Src/FluentAssertions/Execution/ITestFramework.cs
@@ -1,4 +1,6 @@
namespace FluentAssertions.Execution
using System.Diagnostics.CodeAnalysis;

namespace FluentAssertions.Execution
{
/// <summary>
/// Represents an abstraction of a particular test framework such as MSTest, nUnit, etc.
Expand All @@ -13,6 +15,7 @@ internal interface ITestFramework
/// <summary>
/// Throws a framework-specific exception to indicate a failing unit test.
/// </summary>
[DoesNotReturn]
void Throw(string message);
}
}
2 changes: 2 additions & 0 deletions Src/FluentAssertions/Execution/LateBoundTestFramework.cs
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;

Expand All @@ -8,6 +9,7 @@ internal abstract class LateBoundTestFramework : ITestFramework
{
private Assembly assembly;

[DoesNotReturn]
public void Throw(string message)
{
Type exceptionType = assembly.GetType(ExceptionFullName);
Expand Down
2 changes: 2 additions & 0 deletions Src/FluentAssertions/Execution/NSpecFramework.cs
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;

Expand Down Expand Up @@ -27,6 +28,7 @@ public bool IsAvailable
}
}

[DoesNotReturn]
public void Throw(string message)
{
Type exceptionType = assembly.GetType("NSpec.Domain.AssertionException");
Expand Down
2 changes: 2 additions & 0 deletions Src/FluentAssertions/Execution/TestFrameworkProvider.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using FluentAssertions.Common;

Expand All @@ -22,6 +23,7 @@ internal static class TestFrameworkProvider

#endregion

[DoesNotReturn]
public static void Throw(string message)
{
if (testFramework is null)
Expand Down
2 changes: 2 additions & 0 deletions Src/FluentAssertions/Execution/XUnit2TestFramework.cs
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace FluentAssertions.Execution
Expand All @@ -25,6 +26,7 @@ public bool IsAvailable
}
}

[DoesNotReturn]
public void Throw(string message)
{
Type exceptionType = assembly.GetType("Xunit.Sdk.XunitException");
Expand Down

0 comments on commit 430b367

Please sign in to comment.