Mastering Sharness: A Shell‑Based Test Framework for Git and Beyond
This article introduces Sharness, a lightweight shell‑script testing framework derived from Git's own test suite, explains its structure, test case format, built‑in functions, debugging tricks, extensions, and provides practical code examples for writing robust TAP‑compatible tests.
What Is Sharness?
Sharness is a shell‑script based testing framework that runs on Linux and macOS, producing output compliant with the Test Anything Protocol (TAP). It originated from the Git project, was extracted by Christian Couder, and is hosted at https://github.com/chriscool/sharness .
Key Advantages
Simplicity : Creating a file with cat >expect <<-EOF and comparing it with the program output using test_expect_success is straightforward.
Easy Debugging : Individual test scripts can be run with -v for verbose output or -d to keep the temporary directory. Inserting test_pause pauses execution and drops you into a subshell with the test environment.
Git Test Framework Structure
The original Git test framework organizes test scripts as tNNNN‑<name>.sh, modifies PATH to prioritize the repository’s binaries, and creates an isolated temporary directory for each test case.
Writing a Git Test Script
A typical test script starts with a test_description variable, sources the framework code, defines global variables or helper functions, and then uses test_expect_success (or related functions) to declare test cases. The script ends with test_done.
#!/bin/sh
# Copyright (c) 2018 Jiang Xin
test_description='Test git pack‑redundant'
# ... (description omitted for brevity)
. ./test‑lib.sh
master_repo=master.git
shared_repo=shared.git
# create commits, packs, etc.
test_expect_success 'setup master repo' '
git init --bare "$master_repo" &&
create_commits_in "$master_repo" A B C D E F G H I J K L M N O P Q R
'
# ... more test cases ...
test_doneSharness Test Case Format
Each test case can have one, two, or three arguments for test_expect_success:
Two arguments – a description and the command to run.
Three arguments – a pre‑condition, a description, and the command.
test_expect_success 'initial checksum' '
(cd bare.git && git checksum --init &&
test -f info/checksum &&
test -f info/checksum.log) &&
cat >expect <<-EOF
INFO[<time>]: initialize checksum
EOF
sed -e "s/\[.*\]/[<time>]/" bare.git/info/checksum.log >actual &&
test_cmp expect actual
'Built‑In Functions
test_expect_success– start a test that should succeed. test_expect_failure – mark a known‑failure test. test_must_fail – ensure a command fails. test_cmp – compare two files. test_path_is_file, test_path_is_dir – verify existence. test_must_be_empty – assert a file is empty. test_seq – generate numeric sequences. test_pause – pause execution for debugging. test_done – finish the test suite.
Extending Sharness
Custom scripts placed in the sharness.d directory (with a .sh suffix) are automatically sourced, allowing users to add helper functions, set environment variables such as GIT_AUTHOR_DATE, or wrap commands to avoid side effects.
create_pack_in () {
repo="$1" &&
name="$2" &&
pack=$(git -C "$repo/objects/pack" pack‑objects -q pack) &&
eval $name=$pack &&
eval P$pack=$name:$pack
}Practical Use Cases
Sharness is employed in projects like git‑repo to test command‑line tools, and can be adapted for non‑CLI utilities by creating fake applications and invoking them within test scripts. The framework also supports reusing test suites across different protocols (e.g., HTTP vs. local).
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
