knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
Running mutation tests in CI gives you a persistent, objective record of test quality that evolves alongside your codebase. This guide covers GitHub Actions setup, badge reporting, and practical tips for keeping CI runs fast.
muttest locally; the score is always up to date.Create .github/workflows/test-mutation.yaml:
on: push: branches: [main] pull_request: branches: [main] name: Mutation Testing jobs: mutation-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: r-lib/actions/setup-r@v2 with: use-public-rspm: true - uses: r-lib/actions/setup-r-dependencies@v2 with: extra-packages: | jakubsob/muttest - name: Run mutation tests shell: Rscript {0} run: | plan <- muttest::muttest_plan(c( muttest::arithmetic_operators(), muttest::comparison_operators() )) muttest::muttest(plan)
Adjust source_files and mutators to match your package.
The muttest repository ships a badge workflow that writes a JSON endpoint to a badges branch and renders it as a shield. See the badge workflow in the muttest repository for the full implementation pattern.
The badge in your README looks like:
[](https://github.com/YOUR_ORG/YOUR_REPO/actions/workflows/test-mutation.yaml)
Mutation testing multiplies your test runtime: running N mutants means running your test suite N times. Keep CI fast by being selective:
Mutate:
git diff to scope a PR run)Skip:
A practical approach: define a narrow source_files list in your CI plan covering only the high-value files, and run the broader set locally or on a nightly schedule.
To enforce a minimum mutation score, parse the output or use R's exit codes:
score <- muttest::muttest(plan) if (score < 0.7) { message(sprintf("Mutation score %.1f%% is below threshold 70%%", score * 100)) quit(status = 1) }
Start with a threshold that reflects your current score, then tighten it over time as you improve your tests.
source_files tightly — the fewer files, the fewer mutants, the faster the run.git diff --name-only origin/main...HEAD.Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.