GetSkipper.MSTest 1.1.0

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

skipper-dotnet

Test-gating for .NET — skip tests dynamically via a Google Spreadsheet, without touching your test code.

NuGet

What is Skipper?

Skipper reads a Google Spreadsheet to decide which tests to skip. Each row has:

testId disabledUntil notes
Tests/Unit/AuthTests.cs > AuthTests > CanLogin 2026-06-01 Flaky on CI
Tests/E2E/LoginTests.cs > LoginTests > UserCanLogin
  • disabledUntil is in the future → test is skipped automatically
  • disabledUntil is empty or in the past → test runs normally
  • Test not in spreadsheet → test runs normally (opt-out model)

No code changes required in your tests. Configure once, gate everywhere.


Packages

Package Description NuGet
GetSkipper.Core Google Sheets client, resolver, writer NuGet
GetSkipper.XUnit xUnit v2/v3 integration NuGet
GetSkipper.NUnit NUnit 3/4 integration NuGet
GetSkipper.MSTest MSTest v3 integration NuGet
GetSkipper.Playwright Playwright for .NET NuGet
GetSkipper.SpecFlow Reqnroll (SpecFlow) BDD NuGet

Quick Start

xUnit (zero changes to your tests)

// AssemblyInfo.cs — add once to your test project
using GetSkipper.XUnit;

[assembly: TestFramework("GetSkipper.XUnit.SkipperTestFramework", "GetSkipper.XUnit")]
[assembly: SkipperConfig(
    SpreadsheetIdEnvVar = "SKIPPER_SPREADSHEET_ID",
    CredentialsFile = "service-account.json")]

// Your tests remain unchanged:
public class AuthTests
{
    [Fact]
    public void CanLogin() { /* ... */ }
}

NUnit (zero changes to your tests)

// AssemblyInfo.cs
using GetSkipper.NUnit;

[assembly: SkipperConfig(
    SpreadsheetId = "1abc...",
    CredentialsFile = "service-account.json")]

// Your tests remain unchanged:
[TestFixture]
public class AuthTests
{
    [Test]
    public void CanLogin() { /* ... */ }
}

MSTest (zero changes to your tests)

// SkipperSetup.cs — add once to your test project
using GetSkipper.Core;
using GetSkipper.Core.Credentials;
using GetSkipper.MSTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;

public static class SkipperSetup
{
    [GlobalTestInitialize]
    public static async Task InitAsync()
        => await SkipperGlobalHooks.ConfigureAsync(new SkipperConfig
        {
            SpreadsheetId = "1abc...",
            Credentials = new FileCredentials("service-account.json"),
        });

    [GlobalTestCleanup]
    public static Task CleanupAsync() => SkipperGlobalHooks.AfterAllTestsAsync();
}

// Intercept each test (call from a second [GlobalTestInitialize] or use one method):
public static class SkipperTestGate
{
    [GlobalTestInitialize]
    public static void BeforeTest(TestContext ctx) => SkipperGlobalHooks.BeforeTest(ctx);
}

Playwright (change base class only)

using GetSkipper.NUnit;
using GetSkipper.Playwright;

[assembly: SkipperConfig(SpreadsheetId = "1abc...", CredentialsFile = "service-account.json")]

[TestFixture]
public class LoginTests : SkipperPageTest  // was: PageTest
{
    [Test]
    public async Task UserCanLogin()
    {
        await Page.GotoAsync("/login");
        // automatic skip is handled before this line
    }
}

Reqnroll / SpecFlow (zero changes to step definitions)

// reqnroll.json
{
  "bindingAssemblies": [
    { "assembly": "GetSkipper.SpecFlow" }
  ]
}
SKIPPER_SPREADSHEET_ID=1abc... SKIPPER_CREDENTIALS_FILE=./service-account.json dotnet test

Spreadsheet Format

Column Required Description
testId Yes Canonical test identifier
disabledUntil No ISO-8601 date (2026-06-01). Empty = enabled
notes No Free text

Test ID formats

Framework Format
xUnit / NUnit / MSTest Tests/Unit/AuthTests.cs > AuthTests > CanLogin
Playwright Tests/E2E/LoginTests.cs > LoginTests > UserCanLogin
Reqnroll Features/Auth/Login.feature > User authentication > User can log in

Sync Mode

Reconcile the spreadsheet with your test suite (append new tests, remove deleted ones):

SKIPPER_MODE=sync dotnet test

Typically run on main after all tests pass:

# .github/workflows/ci.yml
- name: Run tests in sync mode
  if: github.ref == 'refs/heads/main'
  env:
    SKIPPER_MODE: sync
    SKIPPER_SPREADSHEET_ID: ${{ secrets.SKIPPER_SPREADSHEET_ID }}
    GOOGLE_CREDS_B64: ${{ secrets.GOOGLE_CREDS_B64 }}
  run: dotnet test

Credentials

Three ways to supply the Google service account:

// 1. JSON file (local dev)
Credentials = new FileCredentials("./service-account.json")

// 2. Base-64 encoded JSON (CI secrets)
Credentials = new Base64Credentials(Environment.GetEnvironmentVariable("GOOGLE_CREDS_B64")!)

// 3. Inline object
Credentials = new ServiceAccountCredentials(
    clientEmail: "skipper@project.iam.gserviceaccount.com",
    privateKey: "-----BEGIN RSA PRIVATE KEY-----\n...")

Environment Variables

Variable Default Description
SKIPPER_MODE read-only Set to sync to reconcile spreadsheet
SKIPPER_SPREADSHEET_ID Spreadsheet ID (used with SpreadsheetIdEnvVar)
GOOGLE_CREDS_B64 Base-64 credentials (used with CredentialsEnvVar)
SKIPPER_DEBUG Set to any value for verbose logging

License

MIT — see LICENSE.

Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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 was computed.  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.

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
1.1.0 41 4/10/2026
1.0.0 92 3/17/2026