GeorgJung.TUnit.PairwiseDataSource 0.1.28

dotnet add package GeorgJung.TUnit.PairwiseDataSource --version 0.1.28
                    
NuGet\Install-Package GeorgJung.TUnit.PairwiseDataSource -Version 0.1.28
                    
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="GeorgJung.TUnit.PairwiseDataSource" Version="0.1.28" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GeorgJung.TUnit.PairwiseDataSource" Version="0.1.28" />
                    
Directory.Packages.props
<PackageReference Include="GeorgJung.TUnit.PairwiseDataSource" />
                    
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 GeorgJung.TUnit.PairwiseDataSource --version 0.1.28
                    
#r "nuget: GeorgJung.TUnit.PairwiseDataSource, 0.1.28"
                    
#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 GeorgJung.TUnit.PairwiseDataSource@0.1.28
                    
#: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=GeorgJung.TUnit.PairwiseDataSource&version=0.1.28
                    
Install as a Cake Addin
#tool nuget:?package=GeorgJung.TUnit.PairwiseDataSource&version=0.1.28
                    
Install as a Cake Tool

TUnit.PairwiseDataSource Icon TUnit.PairwiseDataSource

Build Status codecov

A TUnit plugin that provides pairwise (all-pairs) test case generation. Instead of testing every possible combination of parameter values (Cartesian product), pairwise testing generates a smaller set of test cases that covers every pair of parameter values at least once.

This project is closely based on Xunit.Combinatorial by Andrew Arnott. In particular, the harder parts of the pairwise generation logic are intentionally kept very close to that codebase rather than being a fresh reimplementation. That close ancestry is deliberate: one goal of this package is to make xUnit to TUnit migration easier, including preserving the same generated pairwise cases for equivalent inputs.

Why pairwise?

Research shows most software defects are triggered by interactions between at most two parameters. Pairwise testing exploits this by covering all two-way interactions with significantly fewer test cases:

Parameters Values each Cartesian product Pairwise
3 3 27 9
4 3 81 9
5 3 243 15
3 bools 2 8 4

Installation

dotnet add package TUnit.PairwiseDataSource

Usage

Use [PairwiseDataSource] in place of [MatrixDataSource] on your test methods. Parameter values are specified the same way, using [Matrix(...)] attributes:

using TUnit.PairwiseDataSource;

[Test, PairwiseDataSource]
public async Task MyTest(
    [Matrix("a", "b", "c")] string first,
    [Matrix("+", "-")] string op,
    [Matrix("x", "y")] string second)
{
    // Generates 6 test cases covering all pairs, instead of 12 (3×2×2) combinations
}

Automatic value generation

Just like [MatrixDataSource], boolean and enum parameters don't need explicit [Matrix(...)] attributes:

public enum Priority { Low, Medium, High }

[Test, PairwiseDataSource]
public async Task TestWithAutoValues(bool enabled, Priority priority)
{
    // Generates pairwise combinations of {true,false} × {Low,Medium,High}
}

Exclusions

Use [MatrixExclusion(...)] to exclude specific combinations:

[Test, PairwiseDataSource]
[MatrixExclusion("a", "+", "x")]
public async Task MyTest(
    [Matrix("a", "b", "c")] string first,
    [Matrix("+", "-")] string op,
    [Matrix("x", "y")] string second)
{
    // The combination ("a", "+", "x") will never appear
}

Migrating from Xunit.Combinatorial

If you're migrating from xUnit with Xunit.Combinatorial, the mapping is straightforward.

That migration story is not accidental. This package is deliberately built on the same underlying approach, and the pairwise strategy was ported closely enough that equivalent inputs produce the same pair sets. In practice, that means moving from xUnit to TUnit does not also force you to absorb a silent change in generated test cases.

Xunit.Combinatorial TUnit + PairwiseDataSource
[Theory, PairwiseData] [Test, PairwiseDataSource]
[Theory, CombinatorialData] [Test, MatrixDataSource]
[CombinatorialValues(1, 2, 3)] [Matrix(1, 2, 3)]
[CombinatorialRange(0, 5)] [MatrixRange<int>(0, 5)]
Bool/enum auto-generation Bool/enum auto-generation (same)

Example migration

Before (xUnit):

[Theory, PairwiseData]
public void MyTest(
    [CombinatorialValues("a", "b", "c")] string x,
    [CombinatorialValues("+", "-")] string y,
    [CombinatorialValues("1", "2")] string z)
{
}

After (TUnit):

[Test, PairwiseDataSource]
public async Task MyTest(
    [Matrix("a", "b", "c")] string x,
    [Matrix("+", "-")] string y,
    [Matrix("1", "2")] string z)
{
}

Analyzer: TUnit0049 and PWTUNIT001

TUnit's built-in analyzer emits TUnit0049 when [Matrix] is used without [MatrixDataSource]. It doesn't know about [PairwiseDataSource], so this package suppresses TUnit0049 automatically for NuGet consumers via its shipped build props.

This package ships a replacement analyzer (PWTUNIT001) that provides equivalent protection: it errors when [Matrix] is used on parameters but neither [MatrixDataSource] nor [PairwiseDataSource] is present. So after suppressing TUnit0049, you still get a build error if you forget the data source attribute.

Advanced package options

The package also exposes two optional MSBuild properties for consuming projects. Both are enabled by default, so you only need to set them if you want to opt out:

<PropertyGroup>
  <TUnitPairwiseDataSourceImplicitUsings>false</TUnitPairwiseDataSourceImplicitUsings>
  <TUnitPairwiseDataSourceSuppressTUnit0049>false</TUnitPairwiseDataSourceSuppressTUnit0049>
</PropertyGroup>
  • TUnitPairwiseDataSourceImplicitUsings Adds the implicit using TUnit.PairwiseDataSource; for you. Set it to false if you prefer explicit using statements.
  • TUnitPairwiseDataSourceSuppressTUnit0049 Suppresses TUnit's TUnit0049 analyzer diagnostic automatically. Set it to false if you want to keep TUnit's original diagnostic visible.

Algorithm

The pairwise test case generation algorithm in this repository is not merely inspired by Xunit.Combinatorial. PairwiseStrategy.cs is a close port of Andrew Arnott's implementation, preserving its behavior intentionally so that migrations can keep the exact same pairwise coverage.

That implementation in Xunit.Combinatorial is itself derived from Charlie Poole's NUnit implementation, originally based on Bob Jenkins' "jenny" tool.

Xunit.Combinatorial is an excellent project, and this package benefits directly from that work. The goal here is not to obscure that lineage, but to bring the same proven pairwise behavior into TUnit with an API that fits naturally alongside [MatrixDataSource].

License

This project is licensed under the MIT License - see LICENSE for details.

The pairwise algorithm implementation (PairwiseStrategy.cs) is derived from Xunit.Combinatorial by Andrew Arnott (itself based on Charlie Poole's NUnit implementation) and is licensed under the Microsoft Public License (Ms-PL). See ThirdPartyNotices.txt for the full license text.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.1.28 38 3/19/2026
0.1.27-g93188eced2 28 3/19/2026