Skip to content
/ tc Public

tc - theodore calvin's language-agnostic testing framework 🚁 | simple, portable, unix-style testing for any language

License

Notifications You must be signed in to change notification settings

ahoward/tc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

tc - theodore calvin's testing framework 🚁

language-agnostic testing for unix hackers

Theodore Calvin - the man, the legend
theodore "tc" calvin - helicopter pilot, testing framework namesake, legend

|=o=o=o=o=o=o=o=o=o=o=o=|      tc v1.0.0 - island hopper
           |                   testing any language, anywhere
       ___/ \___      (o)       🚁 fly safe, test well
     (( tc      ))======\
       \_______/        (o)
         ^   ^
      ^-----------^

TL;DR

What: Language-agnostic test framework. Write tests once, run against any language (bash, python, rust, go, whatever).

How: Tests are directories. Your code reads input.json from stdin, writes expected.json to stdout. That's it.

Get Started:

# clone and install
git clone https://github.com/ahoward/tc.git
cd tc

# IMPORTANT: Add to PATH (avoids conflict with Unix traffic control command)
export PATH="$PWD/tc/bin:$PATH"

# verify
tc --version

# try the hello-world example
tc examples/hello-world

# create your first test
tc new tests/my-feature

That's it. See full docs for advanced features.


⚠️ PATH Setup (avoid Unix tc conflict)

tc conflicts with the Unix traffic control command. You MUST add this project's tc to your PATH.

# Add to PATH for current session
export PATH="$PWD/tc/bin:$PATH"

# Add to shell config for persistence (optional)
echo 'export PATH="$PWD/tc/bin:$PATH"' >> ~/.bashrc  # or ~/.zshrc

Verify:

which tc        # should show: ./tc/bin/tc (NOT /usr/sbin/tc)
tc --version    # should show: tc v1.0.0 - island hopper

what is tc?

tc is a dead-simple testing framework that lets you:

  • test any language with the same test suite
  • organize tests as directories with json input/output
  • run tests with zero dependencies (just jq)
  • port code between languages without rewriting tests

philosophy

simple β€’ portable β€’ language-agnostic β€’ unix β€’ spec-driven

πŸ€– In the AI age, specifications and tests are permanent while implementations are disposable.

Tests are the spec. Code is a build artifact. Port languages freely, keep tests forever.

πŸ”¬ experimental: multi-language dao demo

See projects/ and examples/multi-lang-dao/ for a working example of identical DAO interfaces in 5 languages (Ruby, Go, Python, JavaScript, Rust) all passing the same test suite.

Vision: Disposable applications. Swap languages freely, keep tests forever.

See docs/THEORY.md for the full system adapter pattern vision.

commands

# test execution
tc                          # run all tests (KISS!)
tc <suite-path>             # run single test suite
tc <path> --all             # run all suites in directory tree
tc <path> --tags TAG        # run suites matching tag
tc <path> --parallel        # run all suites in parallel (auto CPU detection)
tc <path> --parallel N      # run with N parallel workers

# test generation
tc new <test-path>          # generate new test suite
tc init [directory]         # initialize test directory with README

# discovery & metadata
tc list [path]              # list all test suites with metadata
tc tags [path]              # show all available tags
tc explain <suite>          # explain what a test suite does

# info
tc --version                # show version
tc --help                   # show help

output modes

TTY mode (terminal): Clean single-line status with 🚁 spinner, fail-fast behavior Non-TTY mode (CI/CD): Traditional verbose output with full logs Override: TC_FANCY_OUTPUT=true/false

documentation

β†’ full docs | β†’ tc new guide | β†’ system adapter theory (WIP)

example

my-feature/
β”œβ”€β”€ run                    # executable: reads input.json, writes json to stdout
└── data/
    └── scenario-1/
        β”œβ”€β”€ input.json     # test input
        └── expected.json  # expected output
tc my-feature  # βœ“ pass or βœ— fail

pattern matching

tc supports simple pattern matching in expected.json for dynamic values:

{
  "id": "<uuid>",
  "status": "pending",
  "created_at": "<timestamp>",
  "count": "<number>",
  "message": "<string>"
}

Patterns:

  • <uuid> - validates UUID v4 format
  • <timestamp> - validates ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SS)
  • <number> - any JSON number
  • <string> - any string value
  • <boolean> - true or false
  • <null> - null value
  • <any> - matches anything

Works everywhere:

  • Nested objects
  • Array elements
  • Mixed with exact values

No configuration needed - patterns are auto-detected.

custom patterns

Define your own patterns via TC_CUSTOM_PATTERNS:

export TC_CUSTOM_PATTERNS="email:^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
ipv4:^([0-9]{1,3}\.){3}[0-9]{1,3}$
phone:^\+?[0-9]{10,15}$"

Then use in expected.json:

{
  "email": "<email>",
  "server": "<ipv4>",
  "contact": "<phone>"
}

Format: pattern_name:regex (one per line, standard regex syntax)

features

test execution:

  • run single test suite
  • semantic json comparison (order-independent)
  • pattern matching (<uuid>, <timestamp>, <number>, <string>, etc.)
  • timeout management
  • result persistence (tc-result files)
  • hierarchical test discovery (--all flag)
  • tag-based filtering (--tags flag)
  • parallel execution (--parallel flag, auto-detect CPU cores)
  • single-line animated status (TTY mode: helicopter 🚁, spinner, colors)
  • fail-fast on first error (TTY mode stops immediately, shows log path)
  • final stats summary (colored counts: passed/failed/errors, cumulative time)
  • traditional verbose output (non-TTY mode for CI/CD)
  • machine-readable logs (JSONL format in tc/tmp/report.jsonl)

test generation:

  • scaffold generation (tc new)
  • test directory initialization (tc init)
  • metadata flags (--tags, --priority, --description)
  • template system (--from, --list-examples)
  • TDD workflow (tests fail until implemented)

discovery & metadata:

  • list all tests (tc list)
  • show available tags (tc tags)
  • explain test suite (tc explain)
  • AI-friendly metadata format

quality:

  • dogfooding (tc tests itself!)

roadmap:

  • pattern-based selection
  • distributed test execution

ai-driven development

β†’ tc-kit: AI-driven testing ⚠️ EXPERIMENTAL

tc-kit integrates with spec-kit for automatic test generation from specifications. Perfect for AI-assisted development workflows where specs and tests are permanent while implementations are disposable.

Quick start:

# Generate tests from spec
/tc.specify

# Implement to pass tests
edit tc/tests/my-feature/user-story-01/run

# Validate & refine
/tc.validate
/tc.refine

See AI.md for full documentation.

installation

Prerequisites: bash 4.0+, jq

# Install jq
brew install jq                     # macOS
sudo apt-get install jq             # Ubuntu/Debian

# Clone tc
git clone https://github.com/ahoward/tc.git
cd tc

# Add to PATH
export PATH="$PWD/tc/bin:$PATH"

# Verify
tc --version

See the TL;DR section above for PATH setup details.

license

mit license - see LICENSE


made with β˜• and helicopters

"the chopper's fueled up and ready to go. let's test some code." β€” tc

🚁 fly safe, test well

an #n5 joint 🚬

About

tc - theodore calvin's language-agnostic testing framework 🚁 | simple, portable, unix-style testing for any language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •