Use when writing or modifying .txt test scripts in testdata/script/ for git-spice - covers txtar format, end-to-end testing, ShamHub forge simulation, interactive prompts, and golden file comparisons for branch operations and stack workflows.
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
skills listSkill Instructions
name: test-script description: Use when writing or modifying .txt test scripts in testdata/script/ for git-spice - covers txtar format, end-to-end testing, ShamHub forge simulation, interactive prompts, and golden file comparisons for branch operations and stack workflows.
Test Scripts
Overview
Write test scripts for git-spice commands as .txt files in txtar format.
Test scripts verify end-to-end behavior and are stored in testdata/script/.
Quick Reference
| Task | Command/Pattern |
|---|---|
| Run specific test | mise run test:script --run $name |
| Update golden files | mise run test:script --run $name --update |
| Create branch | gs branch create <name> -m <msg> |
| Make commit | gs commit create -m <msg> |
| Compare stdout | cmp stdout $WORK/golden/file.txt |
| Partial match | stdout 'expected substring' |
| Check file exists | exists filename |
| Compare with env vars | cmpenv stdout $WORK/golden/file.txt |
| Test interactive | env ROBOT_INPUT=$WORK/robot.golden ROBOT_OUTPUT=$WORK/robot.actual |
Common Mistakes
Avoid these errors when writing test scripts:
-
❌ Using shell operations: Test scripts don't support
>,>>,2>,|, or command substitution. Usecmp stdout,cmp stderr,stdout, andstderrinstead. -
❌ Using
catorls: Useexists filenameto check existence,cmp have_file want_fileto compare contents. -
❌ Forgetting
asandat: Always freeze time and author for deterministic Git hashes. -
❌ Using
git checkout -b: Usegs branch createinstead (unless testing non-git-spice scenarios). -
❌ Empty golden files with
(empty): Just leave content blank after-- path --.
Writing a test script
Test scripts are plain text files with a series of commands. Most test scripts follow this general structure:
# Brief description of what the test does.
# Wrap comments at 80 characters.
as 'Test <test@example.com>'
at '2025-10-18T21:28:29Z'
# Setup
cd repo
git init
git commit --allow-empty -m 'Initial commit'
gs repo init
# (Optional) ShamHub setup for forge interactions
shamhub init
shamhub register alice
shamhub new origin alice/example.git
git push origin main
# Login as user
env SHAMHUB_USERNAME=alice
gs auth login
# ...
some command
cmp stdout $WORK/golden/output.txt
-- repo/file.txt --
file inside repo
-- repo/path/to/another-file.txt --
another file inside repo
-- extra/supporting-file.txt --
supporting file outside repo.
may be copied into repo during test.
-- golden/output.txt --
expected output for comparison
Notes:
-
Deterministic Git hashes
To get Git SHAs that are consistent across test runs, always freeze time and author at the start of the script using the
atandascommands.as 'Test <test@example.com>' at '2025-10-18T21:28:29Z'The
atshould always use the current time at the moment of writing the test script. -
Repository initialization
Initialize the Git repository and git-spice within it:
cd repo git init git commit --allow-empty -m 'Initial commit' gs repo init -
ShamHub setup
For tests involving forge interactions, we use a simulation server called ShamHub. To set it up, use the
shamhubcommands:shamhub init shamhub register alice shamhub new origin alice/example.git git push origin main env SHAMHUB_USERNAME=alice gs auth login
Following setup, use git-spice via gs commands to perform actions.
Test script style
-
Naming
Follow the convention:
<command>_<scenario>.txtWhere<command>is the git-spice command being tested insnake_case, and<scenario>describes the specific test case. Examples:repo_sync_conflict.txtstack_submit_with_labels.txt
If the test script is a regression test for a specific issue, include the issue number in the name:
issue123_stack_rebase_does_not_do_a_thing.txt
-
Comments
Use comments (
#) to explain the purpose of each step. Wrap comments at 80 characters for readability.If the test script is a regression test for a specific issue, include a comment with the issue link at the top.
Common tasks
Creating branches
gs branch create <branch-name> -m <commit-msg>
This will create a new branch and commit all staged changes to it with the given commit message.
See gs branch create --help for more options.
Never use manual git checkout -b
unless specifically testing a non-git-spice branch creation scenario.
Making commits
gs commit create -m <commit-msg>
This will commit all staged changes to the current branch with the given commit message.
See gs commit create --help for more options.
Supporting files
Files needed by test scripts are defined
at the end of the script using -- path/to/file -- syntax.
For each such section,
everything after the -- path/to/file -- line
until the next -- path/to/another/file -- line, or the end of the file,
is treated as the contents of that file.
-- repo/feature.txt --
Initial content of feature.txt
-- extra/feature-new.txt --
Updated content of feature.txt
-- golden/output.txt --
Expected output of the command
Using golden files
If the expected output of any command is stored in a supporting file,
put it inside a golden/ subdirectory in the test script,
and refer to it using $WORK/golden/filename.
Tip:
For outputs that we do not control (e.g. git commit hashes),
save time by putting placeholder values in the golden files,
then run the test script with the --update flag to auto-update them.
(This only works for cmp comparisons, not cmpenv or cmpenvJSON.)
Verifying git state
-
View git graph:
git graph --branches cmp stdout $WORK/golden/graph.txt -
View git status:
git status --porcelain cmp stdout $WORK/golden/status.txt -
Verify git-spice branch relationships:
gs ls cmp stderr $WORK/golden/ls.txt -
Verify git-spice branch and commit details:
gs ll cmp stderr $WORK/golden/ll.txt
Verifying command output
-
Matching entire stdout
run some command cmp stdout $WORK/golden/output.txt -
Matching stdout partially
run some command stdout 'expected output substring' -
Matching entire stderr
run some command cmp stderr $WORK/golden/error.txt -
Matching stderr partially
run some command stderr 'expected error message substring' -
Comparing with environment variable substitutions
run some command cmpenv stdout $WORK/golden/output.txt cmpenv stderr $WORK/golden/error.txt(
$FOOplaceholders in the golden file will be replaced with their actual values from the test environment.) -
Comparing JSON output with environment variable substitutions
run some command --json cmpenvJSON stdout $WORK/golden/output.json(
$FOOplaceholders in the golden JSON file will be replaced with their actual values from the test environment.)
Testing Interactive Prompts
For commands with interactive prompts,
-
Declare a golden fixture file with pre-defined answers for each expected prompt. These are JSON-encoded answers separated by
===lines, with>comments that contain the rendered prompt text.-- robot.golden -- > Enter your name: "Alice" === > Choose an option: > 1) Option A > 2) Option B 2 -
Before invoking the interactive command, set the
ROBOT_INPUTenvironment variable to point to the fixture file, andROBOT_OUTPUTto capture rendered prompts.env ROBOT_INPUT=$WORK/robot.golden ROBOT_OUTPUT=$WORK/robot.actual -
Run the command that prompts for input.
gs some interactive command -
After the command completes, compare the captured output file with the golden fixture file.
cmp $WORK/robot.actual $WORK/robot.golden(Use
cmpenvif environment variable substitutions are needed.)
Testing opening browser URLs
For commands that open browser URLs,
set BROWSER_RECORDER_FILE to a file path
that will capture the URLs that were requested to be opened.
env BROWSER_RECORDER_FILE=$WORK/browser.log
gs branch submit --web
Verify the recorded URLs against the golden copy:
cmpenv $WORK/browser.log $WORK/golden/browser.log
Running test scripts
-
Run a specific test script:
mise run test:script --run $nameWhere
$nameis the script name without.txtextension. For example, to runtestdata/script/repo_sync_conflict.txt:mise run test:script --run repo_sync_conflict -
Auto-update golden files:
If a test script fails because the expected output has changed intentionally, use the
--updateflag to update golden files:mise run test:script --run $name --updateNote: This only works for
cmpcomparisons.cmpenvandcmpenvJSONdo not support--updatemode.
ShamHub
ShamHub is a simulated forge server (e.g., GitHub/GitLab) used for testing git-spice's forge interactions.
Outside of using git-spice (gs) commands,
ShamHub interactions are available through the shamhub command
defined at internal/forge/shamhub/cli.go.
Common shamhub commands:
shamhub init: Initialize ShamHub server, set environment variables.shamhub register <username>: Register users on ShamHub.shamhub new <remote> <owner/repo>: Create a new ShamHub repository and add as remote in the current Git repository.shamhub fork <owner/repo> <fork-owner>: Create a fork of a ShamHub repository under a different user.shamhub clone <owner/repo> <dir>: Clone an existing ShamHub repository into the given directory.shamhub merge [-prune] [-squash] <owner/repo> <pr>: Merge a Shamhub Change Request (Pull Request/Merge Request). Use-pruneto delete the source branch after merging. Use-squashto squash commits when merging.shamhub reject <owner/repo> <pr>: Reject a ShamHub Change Request and close it.shamhub dump changes/comments: Dump ShamHub state to stdout for verification. (Usecmp,cmpenv, andcmpenvJSONto verify output.)
Reference
For detailed command reference,
see testdata/script/README.md in the repository.
More by abhinav
View allUse when writing or improving messages for Git commits, or when asked to generate a commit message or pull request description.
Reference guide for code comment formatting rules and examples. The core rules are automatically applied via CLAUDE.md system instructions - this skill provides detailed examples and edge cases for reference.
Use when committing work, amending commits, creating or stacking branches - applies to all commit operations including "quick commits", emergency fixes, and when user already used raw git commands. ALWAYS use git-spice instead of git checkout, git commit, or git branch.
Use when creating new skills, editing existing skills, or verifying skills work before deployment