Iyu.Conventions.Testing 0.3.0

dotnet add package Iyu.Conventions.Testing --version 0.3.0
                    
NuGet\Install-Package Iyu.Conventions.Testing -Version 0.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Iyu.Conventions.Testing" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Iyu.Conventions.Testing" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Iyu.Conventions.Testing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Iyu.Conventions.Testing --version 0.3.0
                    
#r "nuget: Iyu.Conventions.Testing, 0.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Iyu.Conventions.Testing@0.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Iyu.Conventions.Testing&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Iyu.Conventions.Testing&version=0.3.0
                    
Install as a Cake Tool

Iyu.Conventions.Testing

Convention checks for .NET libraries, run from a repository's own test project.

Two checks today:

  • Options reachability finds public options that nothing in the library reads.
  • Operational language finds log and exception messages that break a language rule.

The first finds public options that nothing in the library reads. An option nothing reads is a promise the library does not keep: a caller sets it, and nothing changes and nothing is reported. No build, test or review notices it, because nothing fails.

The package has no dependency beyond the runtime. Assertions throw RosterMismatchException, so it works with xUnit, NUnit, MSTest or anything else that treats an exception as a failure.

Usage

using System.Reflection;
using Iyu.Conventions.Testing;

public class ConventionsTests
{
    // The assemblies whose code may read the options. You choose them: a scanner that guesses which
    // assemblies to load can silently scan none and report nothing unread.
    private static readonly Assembly[] Libraries = [typeof(MyLibrary.Client).Assembly, typeof(MyLibrary.Storage.Store).Assembly];

    // Options the repository accepts as unread today, as a deliberate and visible decision.
    // Shrink this list; never grow it silently.
    private static readonly Dictionary<string, string[]> KnownUnread = new()
    {
        ["MyLibrary.ClientOptions"] = ["LegacyMode"],
    };

    [Fact]
    public void EveryPublicOption_IsRead() =>
        OptionsReachability.Scan(Libraries, OptionsTypes.NamedWith("Options"))
            .ShouldMatchRoster(KnownUnread);
}

The roster fails in both directions. A newly added option that nothing reads fails, and so does a known entry for an option that has since been wired: both are changes the roster has to record on purpose.

What counts as a read

  • A call to the option property's getter from any type outside the options type.
  • A read inside the options type, in a member the library calls from outside it (a computed property, a fluent method that returns this).
  • Not validation (0.3.0+): a read in the options type's own Validate… methods, or in an IValidateOptions<T> validator. A range check does not make an option take effect. A Validate… method on another type (a guardrail's ValidateInputAsync reading its own options) is a use.
  • Not a read made only to copy the options into a new instance: the compiler's record copy method, or any method returning the options type whose body creates one (a constructor call, a record copy, MemberwiseClone).

Reading is necessary, not sufficient. An option can be read and still have no effect, and that has no static signal. A property is attributed to the type that declares it.

Report

OptionsReachability.Scan returns an OptionsReachabilityReport:

Member Meaning
OptionTypes Every options type found
Unread Per options type (full name), the public properties nothing reads
Read Every read property, as Namespace.Type.Property
CrossAssemblyReads Reads whose reader lives in another assembly than the options type

Operational language

Log message templates and exception messages are read by operators at run time, pasted into issues and indexed by log pipelines. OperationalLanguage reads them from the compiled assemblies:

[Fact]
public void OperationalTextIsAscii()
{
    var report = OperationalLanguage.Scan(Libraries, OperationalLanguage.NonAscii);
    Assert.True(report.ExceptionLiteralsRead > 0, "the scan must see the library's exception messages");
    report.ShouldBeClean();
}
  • [LoggerMessage] templates, matched by attribute type name. The package does not depend on Microsoft.Extensions.Logging.
  • String literals whose next object construction in the method builds an exception. This covers throw new X("…"), string.Format("…", …) passed to one, and interpolated messages.
  • It does not read documentation comments, or string literals that never reach an exception (user-facing text).

The rules are plain predicates. ContainsHangul and NonAscii are built in; pass your own for anything else.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 393 9/29/2026
0.2.0 282 9/28/2026
0.1.0 906 9/19/2026