Snip is a tool born out of frustration with unit testing C programs. It allows you to cut and paste the code you want to test, run a different make file, and execute the result, in milliseconds.
In the file you want to cut code from, add //SNIP_testme comments marking which code you wish to cut and paste.
#include#include //SNIP_testme static int my_pure_method(int input) { // code to be tested } //SNIP_testme
Almost always //SNIP_xxx markers should come after the #includes, so that snip tests can be built with mocks and stubs for dependencies. Snip enables mocking C, even with static musl-cc compilation.
.c.snip file which is a separate C file containing a main method.
e.g. test/snips/mylib_test.c.snip
#includeCreate a#include "my_stubs.h" #include "my_asserts.h" //SNIP_FILE SNIP_testme ../../mylib.c int main(int argc , char *argv[]) { int rc; rc = my_pure_method(0); snip_assert("zero", rc == 0); rc = my_pure_method(1); snip_assert("zero", rc == 0); rc = my_pure_method(2); snip_assert("zero", rc == 0); }
.c.make file in the same directory which is bash file (not make).
e.g. test/snips/mylib_test.c.make
#!/bin/bash
set -euo pipefail
cd $(dirname $0)
snip_test=mylib_test
musl-gcc -Wall -Werror -Wno-unused-function -g -O0 \
$snip_test.c \
-o $snip_test \
-lm \
&& ./$snip_test \
&& rm -f ./$snip_test ./${snip_test}.c
Usually, this template is sufficent, but it can be as complicated as you like.
sniprun mylib_test.c.snip
This does the templating, compiles, links and runs the test in one step, then deletes the temporary files.
If a test fails, the generated .c file is not deleted, to aid debugging. A successful run will delete the temp files.
main() methods.Since all C code uses a pre-processor, snip is surprisingly natural to use.
With nginx modules (which this project was written for) the main() method is compiled into nginx.o which most code uses. This means you can't create a test binary with nginx.o and another main() method. C programs can only have one main.
This is fixable in nginx.c, but this code is out of control of plugin developers. Hence snip.
To my knowledge, in 2026, over 500,000 tests have been written with snip. It works. Claude likes it.
Like all good developer tools, snip is implemented in bash.
A .deb is available here: snip.deb
which installs sniprun in /usr/bin.
Here is a Claude SKILL.md, because nobody actually writes code anymore.
snip consists of two files: snipcat & sniprun.
/usr/bin/snipcat
#!/bin/bash
#
# Snip Cat - Cat a delimited snip out of a file
#
tag=$1
file=$2
if [[ -z "$tag" ]] || [[ -z "$file" ]]
then
echo "Usage: $0 SNIP_TAG file"
exit 1
fi
cat $file | awk -v TAG="$tag" '
BEGIN {
doecho=0;
}
/.*/ {
if (match($0, TAG)) {
if (!doecho) doecho=1;
else doecho=0;
next;
}
if (doecho) print $0;
}
'
/usr/bin/sniprun
#!/bin/bash
#
# Snip Test - Unit testing the way you wish you didn't have to do it
#
#
# CD to the .in files directory
#
in="$1"
basedir=$(dirname $in)
snipfile=$(basename $in)
cd "$basedir"
if [ ! -f $snipfile ]
then
echo "File not found: $1"
exit 1
fi
if [ ! -f ${snipfile%.*}.make ]
then
echo "No make file: ${snipfile%.*}.make"
exit 1
fi
if [ ! -x ${snipfile%.*}.make ]
then
echo "Make not executable: ${snipfile%.*}.make"
chmod +x ${snipfile%.*}.make || exit 1
fi
cat $snipfile | awk '
/^.*$/ {
print $0;
}
/^\/\/SNIP_FILE.*/ {
system("snipcat " $2 " " $3);
}
' > ${snipfile%.*}
./${snipfile%.*}.make
yep, TDD was always that simple 😎
grep SNIP_ finds all your tested code.