testit is a minimal testing package for R with zero dependencies. If you can write an R expression that returns TRUE, you can write a test with testit.
Installation
From CRAN:
install.packages('testit')Development version:
install.packages('testit', repos = 'https://yihui.r-universe.dev')Quick start
The core idea: wrap conditions in parentheses () inside assert(). If the condition is TRUE, the test passes silently. If it is FALSE, you get an error with the message you provided.
You can put multiple conditions in one assert() call, and mix in setup code (lines without parentheses are just evaluated normally):
assert('basic arithmetic works', {
x = 1 + 1
(x == 2)
(x > 0)
})To test if two objects are identical, use %==% (a shortcut for identical()). When a %==% comparison fails inside assert(), you get a helpful diff showing what was different:
How it works
testit has one rule: an expression in parentheses () is a test condition that must evaluate to TRUE. Everything else is ordinary R code.
assert('a descriptive message about what you are testing', {
# setup code (no parentheses = not checked)
x = sqrt(4)
# test conditions (parentheses = must be TRUE)
(x == 2)
(x > 0)
(is.numeric(x))
})That’s it. No special matchers to memorize, no DSL to learn.
Testing for errors, warnings, and messages
Use has_error(), has_warning(), and has_message() to verify that code signals the expected condition:
Snapshot testing
Snapshot tests let you verify printed output by recording it in a Markdown file. Place files named test-*.md in your tests/testit/ directory:
The R code block (```r) is executed and its output is compared to the following plain code block (```). If the output changes, the test fails with a diff. To accept the new output, run:
test_pkg(update = TRUE)You can write explanatory text anywhere in the file – only code blocks are evaluated.
Setting up tests in your package
Create the directory
tests/testit/in your package.Write test files named
test-*.R(and optionallytest-*.mdfor snapshots).Create
tests/test-all.Rwith:
library(testit) is required because test scripts call assert() and other testit functions directly. Without it, you will get errors like “could not find function assert”.
That’s all. R CMD check will run your tests automatically. In RStudio, you can also press Ctrl/Cmd + Shift + T to run tests during development. For this to work, go to the menu Build > Configure Build Tools... and make sure “Use devtools package functions if available” is unchecked (otherwise RStudio will try to use testthat conventions instead).
Helper files
If you have shared setup code, put it in files named helper*.R (e.g., helper.R, helper-utils.R) in the same test directory. They are sourced before any test file runs.
Global helpers in the parent directory (e.g., tests/helper.R) are also sourced – before the subdirectory-level helpers. This is useful when you have multiple test subdirectories (e.g., tests/testit/, tests/test-cran/) and want to share common utilities across all of them.
Accessing internal functions
test_pkg() runs your tests inside the package namespace, so you can call non-exported (internal) functions directly – no need for the ::: operator.
Comparison with testthat
testit is intentionally minimal. There is one rule to remember: parentheses around an expression means “this must be TRUE.” There are no matchers like expect_equal vs. expect_identical vs. expect_equivalent to choose between.
The tradeoff is that you get fewer bells and whistles (no mocking, no parallel execution). If you want a simple, dependency-free testing tool that stays out of your way, testit is a good fit.
If you want to convert your existing testthat tests to testit, you may take a look at this post https://yihui.org/en/2026/05/testthat-to-testit/. If you use AI assistance, this should be a straightforward task.

Although he did not really mean it, Xunzi said something that happens to apply well to unit testing:
不积跬步,无以至千里;不积小流,无以成江海。
(A journey of a thousand miles begins with a single step; a great river is formed from many small streams.)
This package is free and open source software, licensed under MIT.