✂ Snip testing - cut-n-paste testing framework

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.

✂ Creating Snips

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.

Create a .c.snip file which is a separate C file containing a main method.

e.g. test/snips/mylib_test.c.snip

#include 

#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);
}
Create a .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.

✂ Usage

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.

✂ Benefits of Snip

Since all C code uses a pre-processor, snip is surprisingly natural to use.

✂ History

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.

✂ Implementation

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 😎

Snip recommends sanename, so that grep SNIP_ finds all your tested code.

Snip is a Linux tool: if you develop C on Windows, my heart goes out to you.