{"id":50713851,"url":"https://github.com/abh80/harness","last_synced_at":"2026-06-09T17:04:19.017Z","repository":{"id":357653080,"uuid":"1237568495","full_name":"abh80/harness","owner":"abh80","description":"Harness is simple diff based testing framework, written in pure native powershell/bash script. Simple and Flexible to install works with any kind of project.","archived":false,"fork":false,"pushed_at":"2026-05-13T17:29:09.000Z","size":64,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-13T19:18:02.856Z","etag":null,"topics":["framework","powershell","test-automation","testing","tools"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/create-snap-harness","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abh80.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-13T09:53:28.000Z","updated_at":"2026-05-13T17:29:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/abh80/harness","commit_stats":null,"previous_names":["abh80/harness"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/abh80/harness","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abh80%2Fharness","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abh80%2Fharness/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abh80%2Fharness/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abh80%2Fharness/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abh80","download_url":"https://codeload.github.com/abh80/harness/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abh80%2Fharness/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34116464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework","powershell","test-automation","testing","tools"],"created_at":"2026-06-09T17:04:16.542Z","updated_at":"2026-06-09T17:04:19.003Z","avatar_url":"https://github.com/abh80.png","language":"PowerShell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Harness\n\n[![npm](https://img.shields.io/npm/v/create-snap-harness.svg)](https://www.npmjs.com/package/create-snap-harness?activeTab=readme)\n\nHarness is a simple diff based testing framework, written in pure native powershell/bash script. Simple and flexible to install, works with any kind of project.\n\nYou write a program, hit `record` to save what it prints, and from then on `test` runs it again and yells if anything changed. No clever assertions, no DSL, no framework to learn. If your program prints stuff, you can test it.\n\nAfter the `npx` scaffold, there's no Node dependency. Just scripts. Wipe Node off the machine and the harness keeps working.\n\n\u003e This project was made with agentic coding in mind and the templates carry their own CLAUDE.md (generated by LLMs).\n\n## Why\n\nMost testing frameworks make you learn the framework before you can test anything. This one only knows three things: what came out on stdout, what came out on stderr, what the exit code was. That's it. Diff the new output against the saved one. Match means pass, mismatch means fail. Done.\n\nWorks for cpp, java, python, scala, node, rust, go, a bash script you wrote last tuesday, whatever. The harness doesn't care what language you used or how you built it. If it runs and prints, it tests.\n\n## Quick start\n\n```bash\nnpx create-snap-harness my-project\ncd my-project\n# PowerShell\n.\\scripts\\install.ps1 -All\n.\\scripts\\build.ps1 -All\n.\\scripts\\record.ps1 -All\n.\\scripts\\test.ps1 -All\n# Bash\n./scripts/install.sh --all\n./scripts/build.sh --all\n./scripts/record.sh --all\n./scripts/test.sh --all\n```\n\nRun those four scripts in order the first time. After that you mostly just need `test`. Use `record` again whenever you intentionally changed the expected output.\n\n## Adding harness to an existing project\n\nAlready have a tree of programs and don't want a full scaffold? Drop scripts into a project root with `install`:\n\n```bash\nnpx create-snap-harness install            # current dir, .harness/scripts/, detected flavor\nnpx create-snap-harness install ./repo --shell both\nnpx create-snap-harness install --dir scripts --shell ps1   # legacy flat layout\n```\n\n`install` only touches `\u003ctarget\u003e/\u003cscriptsDir\u003e` — your `harness.toml` files, `__tests__/`, and sources are untouched. Re-run it any time to pick up template updates.\n\nScripts run a recursive scan from wherever you invoke them, so every `\u003cdir\u003e/harness.toml` (or convention `install/build/run/clean.\u003cext\u003e` script) in the tree gets picked up. Drop the scripts at the root, run `.\\.harness\\scripts\\test.ps1 -All` from there, and every program below gets tested.\n\nWant to target one subtree? Use `-Recurse` (PowerShell) or `--recurse` (Bash) — points the scan at a single directory and implies `-All` inside it:\n\n```powershell\n.\\.harness\\scripts\\build.ps1 -Recurse .\\chapter2\n.\\.harness\\scripts\\test.ps1  -Recurse .\\chapter2 -Filter default\n```\n\n```bash\n./.harness/scripts/build.sh --recurse ./chapter2\n./.harness/scripts/test.sh  --recurse ./chapter2 --filter default\n```\n\nHidden dirs (`.git`, `.harness`, …), `node_modules`, `__tests__`, and common build-output dirs (`dist`, `build`, `out`, `bin`, `obj`, `target`) are skipped automatically.\n\n## Flags\n\n```\nnpx create-snap-harness [\u003cname\u003e] [options]\n  --shell \u003cps1|sh|both\u003e           shell flavor (default: detected from OS)\n  --samples \u003clist\u003e                comma-separated subset of: cpp,java,scala,python,node,none\n  --no-git                        skip git init\n  --no-commit                     skip initial commit\n```\n\nSkip any of these and you'll get asked. Pass `--samples none` if you don't want the hello-world examples cluttering things up.\n\n## What gets scaffolded\n\n```\n\u003cproj\u003e/\n├── scripts/                       chosen shell flavor(s)\n│   ├── install.{ps1,sh}           run install step per program\n│   ├── build.{ps1,sh}             run build step\n│   ├── test.{ps1,sh}              run cases, diff stdout/stderr/exit\n│   ├── record.{ps1,sh}            capture current output as golden\n│   ├── clean.{ps1,sh}             run clean; --refs nukes expect files\n│   └── lib/{toml,common}.{ps1,sh}\n├── samples/\u003clang\u003e-hello/          example programs (delete or replace)\n├── README.md\n├── CLAUDE.md                      LLM authoring guide\n├── .gitignore\n└── .github/workflows/test.yml     only when --shell=both\n```\n\nThe samples are there so you can see a working setup before you wire up your own programs. Delete them when you don't need them anymore.\n\n## Program manifest\n\nEach program gets a `harness.toml`. Only `run` is required, the rest is optional.\n\n```toml\nname    = \"hello\"\ninstall = \"npm ci\"            # optional\nbuild   = \"tsc -p .\"          # optional\nrun     = \"node dist/main.js\" # required\nclean   = \"rimraf dist\"       # optional\n```\n\nHate config files? Skip the toml entirely and drop `install.\u003cext\u003e`, `build.\u003cext\u003e`, `run.\u003cext\u003e`, or `clean.\u003cext\u003e` scripts straight into the program folder. The runner finds them either way. Pick whichever feels less annoying for the program you're writing.\n\n## Test cases\n\nEach case is a folder under `\u003cprogram\u003e/__tests__/\u003cname\u003e/`:\n\n| File | Role | Written by `record` |\n|---|---|---|\n| `in.txt` | piped to stdin | never |\n| `args.txt` | extra CLI args appended to run cmd | never |\n| `expect.txt` | golden stdout (required for case to run) | always |\n| `expect.err.txt` | golden stderr | only when stderr non-empty |\n| `exit.txt` | expected exit code | only when ≠ 0 |\n\nThe flow: write `in.txt` and `args.txt` yourself, or skip them if your program doesn't need any input. Run `record` once you trust the output. Then `test` diffs every future run against what got saved.\n\n`expect.err.txt` and `exit.txt` only get created when they actually matter, so your test folders stay clean and you can tell at a glance which cases care about stderr or exit codes.\n\nWhen a diff fails, `test` prints both sides next to each other so you can see what changed. If the change was intentional, run `record` again. If it wasn't, you have a bug.\n\n## Development\n\n```bash\ngit clone https://github.com/abh80/harness.git\nnpm install\nnpm run build\nnpm test\nnode dist/cli.js \u003cargs\u003e\n```\n\nTests live in `tests/` (vitest). Templates in `templates/` ship verbatim, the build never touches them. If you change a template, the change goes straight into whatever the next scaffold produces.\n\n## License\n\nCreative Commons License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabh80%2Fharness","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabh80%2Fharness","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabh80%2Fharness/lists"}