Skipper

Enable and disable tests directly from a Google Spreadsheet — no code changes required.

What is Skipper?

Skipper is an open-source library that lets you control which tests run using a shared Google Spreadsheet. Mark a test as disabled in the sheet and Skipper skips it automatically — no pull requests, no deploys, no friction. Perfect for flaky-test management, feature flags in testing, and cross-team coordination.

Real-world use cases

Situations where teams reach for Skipper every day.

🔴

Intermittently failing tests

A test starts failing on CI every now and then with no obvious cause. Instead of commenting it out and pushing a commit, you disable it from the sheet in 10 seconds and re-enable it once it's fixed — without pulling anyone else into it.

🚀

Tests for unreleased features

You've already written tests for a feature that hasn't shipped yet. You keep them in the codebase but disable them in the sheet until the feature goes live — no hardcoded skips cluttering the repo.

👥

Cross-team coordination

The backend team is refactoring an API. The backend lead disables the affected integration tests directly from the sheet, without waiting for QA to open a PR or anyone to touch test files.

🌍

Environment-specific tests

Some tests only make sense on staging, not on CI — or the other way around. You keep one sheet per environment and manage exclusions there, with no conditional logic bleeding into the test code.

🧪

Experimenting with test strategies

You're trying out a new testing approach and want to temporarily bench an entire category of tests. You do it from the sheet, run your experiment, and restore everything — without leaving any trace in the project.

Integrations

Use Skipper with your language and test framework of choice.

skipper
JavaScript TypeScript

Core library for JavaScript and TypeScript projects. Monorepo with dedicated packages for each test runner. Skipper uses Skipper itself to manage its own test suite — see the live spreadsheet.

Supported frameworks

Jest Vitest Playwright Cypress Nightwatch
View on GitHub
skipper-php PHP

Skipper for PHP projects, with support for the most popular testing frameworks in the ecosystem.

Supported frameworks

PHPUnit 10 PHPUnit 11 PHPUnit 12 Pest v2 Pest v3 Behat 3 Codeception 5 PHPSpec 7 PHPSpec 8 Kahlan 5 Kahlan 6
View on GitHub
skipper-go Go

Skipper for Go projects, with adapters for the standard library and the most popular testing frameworks.

Supported frameworks

testing Testify Ginkgo
View on GitHub
skipper-dotnet .NET

Skipper for .NET projects, with adapters for the most popular testing frameworks in the ecosystem.

Supported frameworks

xUnit NUnit MSTest Playwright SpecFlow
View on GitHub
skipper-python Python

Skipper for Python projects, with adapters for the most popular testing frameworks in the ecosystem.

Supported frameworks

pytest unittest Playwright
View on GitHub
skipper-java Java

Skipper for Java projects, with adapters for the most popular testing frameworks in the ecosystem.

Supported frameworks

JUnit 5 TestNG Cucumber Playwright
View on GitHub

Getting Started

Up and running in 4 steps.

  1. 1

    Set up the Google Spreadsheet

    Create a new Google Spreadsheet and add three columns: testId, disabledUntil, and notes. Then create a Google Service Account, download its JSON credentials file, and share the spreadsheet with the service account email address.

    You can start from the ready-made template — just make a copy and use it as your own: Open the template spreadsheet →

  2. 2

    Install the package

    Install the adapter for your test runner:

    Jest
    npm install @get-skipper/jest
    Vitest
    npm install @get-skipper/vitest
    Playwright
    npm install @get-skipper/playwright
    Cypress
    npm install @get-skipper/cypress
    Nightwatch
    npm install @get-skipper/nightwatch
    composer require get-skipper/skipper-php

    Install the adapter for your test runner:

    testing
    go get github.com/get-skipper/skipper-go/testing
    Testify
    go get github.com/get-skipper/skipper-go/testify
    Ginkgo
    go get github.com/get-skipper/skipper-go/ginkgo

    Install the adapter for your test runner:

    xUnit
    dotnet add package GetSkipper.XUnit
    NUnit
    dotnet add package GetSkipper.NUnit
    MSTest
    dotnet add package GetSkipper.MSTest
    Playwright
    dotnet add package GetSkipper.Playwright
    SpecFlow
    dotnet add package GetSkipper.SpecFlow

    Add the dependency for your test runner to pom.xml:

    JUnit 5
    <dependency>
      <groupId>io.getskipper</groupId>
      <artifactId>skipper-junit5</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
    TestNG
    <dependency>
      <groupId>io.getskipper</groupId>
      <artifactId>skipper-testng</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
    Cucumber
    <dependency>
      <groupId>io.getskipper</groupId>
      <artifactId>skipper-cucumber</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
    Playwright
    <dependency>
      <groupId>io.getskipper</groupId>
      <artifactId>skipper-playwright</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
  3. 3

    Set the environment variables

    Skipper reads its configuration from two environment variables:

    SKIPPER_SPREADSHEET_ID The ID from your spreadsheet URL
    GOOGLE_CREDS_B64 Your service account JSON key, base64-encoded
  4. 4

    Connect Skipper to your test runner

    Each integration hooks into your framework's native setup mechanism — no changes to individual test files required. See the setup guide for your framework in the corresponding GitHub repository.

See it in action

What your test run looks like when Skipper is active.

 PASS  src/checkout/checkout.test.ts

  Checkout
     adds item to cart (23 ms)
     processes payment [skipper] disabled until 2025-12-31 · flaky on CI
     applies discount code (19 ms)

 SKIP  src/auth/sso.test.ts

  SSO
     signs in with Google [skipper] disabled until 2025-04-15 · SSO maintenance

Test Suites: 1 skipped, 1 passed, 2 total
Tests:       2 skipped, 2 passed, 4 total
Time:        1.842 s
PHPUnit 11.0.0 by Sebastian Bergmann and contributors.

..S.S                                                       5 / 5 (100%)

Time: 00:00.187, Memory: 8.00 MB

[skipper] CheckoutTest::testProcessesPayment — disabled until 2025-12-31 · flaky on CI
[skipper] SsoTest::testSignInWithGoogle — disabled until 2025-04-15 · SSO maintenance

OK, but there were issues!
Tests: 5, Assertions: 3, Skipped: 2.
--- PASS: TestAddsItemToCart (0.023s)
--- SKIP: TestProcessesPayment (0.00s)
    suite_test.go:14: [skipper] disabled until 2025-12-31 · flaky on CI
--- PASS: TestAppliesDiscountCode (0.018s)
--- SKIP: TestSignInWithGoogle (0.00s)
    suite_test.go:28: [skipper] disabled until 2025-04-15 · SSO maintenance
PASS
ok      github.com/myorg/myapp  0.045s
  CheckoutTests
      AddsItemToCart [23 ms]
      ProcessesPayment [skipper] disabled until 2025-12-31 · flaky on CI
      AppliesDiscountCode [19 ms]

  SsoTests
      SignInWithGoogle [skipper] disabled until 2025-04-15 · SSO maintenance

Passed!  Failed: 0, Passed: 2, Skipped: 2, Total: 4, Duration: 42 ms
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.myorg.CheckoutTest
[INFO]    addsItemToCart
[INFO]    processesPayment [skipper] disabled until 2025-12-31 · flaky on CI
[INFO]    appliesDiscountCode
[INFO] Running com.myorg.SsoTest
[INFO]    signInWithGoogle [skipper] disabled until 2025-04-15 · SSO maintenance
[INFO]
[INFO] Results:
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 2
[INFO]
[INFO] BUILD SUCCESS

FAQ

How should the Google Spreadsheet be structured?

Skipper expects a sheet with at least three columns: testId, disabledUntil, and notes. Each row represents one test. The testId is a unique identifier built from the test's file path, describe block, and test name — Skipper generates it automatically. The disabledUntil column accepts a date in YYYY-MM-DD format. The notes column is free text and is useful for leaving context about why a test was disabled.

Multiple sheets are supported within the same spreadsheet, which makes it easy to maintain separate configurations per environment — for example one sheet for CI and one for staging.

Why disabledUntil instead of an enabled flag?

A boolean enabled column works, but it has a subtle problem: a disabled test stays disabled until someone actively goes back and flips it. In practice, tests get forgotten.

disabledUntil forces you to set an expiry when you disable a test. Once that date passes, Skipper automatically treats the test as enabled again — no manual action needed. This keeps the spreadsheet tidy and prevents a growing list of permanently-skipped tests that nobody remembers to revisit. If you genuinely need to disable something indefinitely, set the date far in the future — it's an explicit choice rather than the path of least resistance.

Who can see or modify the tests?

Whoever you decide. Google Sheets handles access control natively: you can share the spreadsheet with specific people, restrict it to your organisation's domain, or keep it completely private. Every change is also tracked in the sheet's revision history, giving you a built-in audit trail of who updated a test and when — no extra tooling required.

Does Skipper use Skipper for its own tests?

Yes. Every repository in the get-skipper organization manages its test suite using Skipper. They all share a single public spreadsheet, each on its own dedicated sheet — so you can see the live state of every project's tests in one place:

View the get-skipper test spreadsheet →