Sorry, you need to enable JavaScript to visit this website.

BATS Helpers, assertions for testing shell scripts

The scripts that provision, deploy and back up a platform run with real credentials against real data, and they are usually the last piece of code anyone thinks to test. bats-helpers is our open-source library that makes testing them practical.

At a glance

Year
  • 2023
Status
  • Ongoing
Technologies

The code that runs closest to production: deployment scripts

Think about what actually happens when your website is deployed. A script does the work:

  • copies a database
  • runs updates
  • clears caches
  • imports configuration
  • sends a notification
  • hands the environment over

It runs on a developer's laptop, again in the build pipeline, and again on production hosting, usually holding credentials that reach real data.

Now think about how that script is tested. In most teams the application code has a test suite, a coverage report and a review process. The deployment scripts have none of that, and they are the ones running in the highest-consequence environment in the system.

That gap is not carelessness. It is that testing shell has always been awkward.

Why shell testing stops before it starts: no assertion vocabulary

There is a perfectly good test runner for Bash. BATS, the Bash Automated Testing System, will run your test files and report pass or fail.

What it does not give you is the vocabulary that makes tests worth reading: a way to assert that a command printed the right thing, to stand in for a command that would otherwise call a live service, to build a throwaway directory of fixtures, or to run the same check across a list of cases.

Without those pieces, each project ends up inventing its own version of them, the tests get written once, and shell testing quietly stops. We wrote the missing layer and published it instead.

What the library provides: assertions, command mocking and fixtures

bats-helpers(Opens in a new tab/window) sits on top of BATS and supplies the assertions and helpers a real test suite needs:

  • assertions for command output, strings, files, directories and Git repositories, so a check says what it means in one readable line
  • command mocking, with per-call output, exit status and side effects, so a script that would otherwise call a hosting API or a live database can be exercised safely
  • a step runner for asserting a sequence of calls in the order they should happen
  • a data provider for running a function across many cases
  • fixture and file utilities for building and restoring a sandbox directory
  • a helper for driving interactive prompts with scripted answers

It installs from npm next to bats-core, and it is developed in the open under an open-source licence. Its own suite runs on every change through GitHub Actions, with dependencies kept current automatically.

Where it earns its keep: the Bash underneath Vortex

The library exists because of Vortex(Opens in a new tab/window), our open-source Drupal(Opens in a new tab/window) project template. Underneath Vortex is a substantial amount of Bash: a provisioning script written to behave identically on a laptop, in the build pipeline and on hosting, plus the tooling that deploys, notifies, and downloads and exports databases.

Those are the scripts where a surprise is most expensive. Because bats-helpers exists, they are covered by tests that run on every change, which means we can improve them without wondering what we might have broken.

Tested deployment scripts, checked on every change, inherited by every project built on Vortex.

Every project built on Vortex inherits that safety, whether or not anyone on the team ever opens a Bash file. For a client, that reads as a quieter deployment: the scripts that touch your database and your live environment are covered by tests that run before the change does.

The standard, not the package: infrastructure scripts are code

The library itself is small. The habit behind it is the interesting part.

Infrastructure scripts are code. They run where mistakes are most expensive, and they deserve the same treatment as everything else:

  • version control
  • review
  • tests that run automatically
  • a failure that shows up in a pipeline rather than in front of your audience

Testing deployment scripts is still uncommon in our industry, which is precisely why we treat it as a baseline rather than a nice-to-have. For a client, that is the difference between trusting a deployment script and knowing what it does.

When we take on a platform, that discipline comes with us.

For teams whose deployment scripts are untested

Everything on this page is 3 of our services pointed at our own tooling: development of the library, the DevOps engineering it exists to protect, and the ongoing support and maintenance that keeps both current. The same standard applies to our AI-assisted delivery: whatever writes the change, the test suite is what decides it is safe to ship.

If you run a platform whose deployments are hand-run scripts nobody has tested, or a build pipeline whose shell nobody wants to touch, this is the shape the engagement takes. The infrastructure code gets read, covered by tests, and moved into the pipeline, so the failure you would have found in production shows up in a build instead.

If nobody on your team can say with confidence what your deployment script does on its bad day, show us the script.

  • Open source
  • Testing
  • Automation
  • DevOps
  • Continuous integration