test-patternsWrite and run tests across languages and frameworks. Use when setting up test suites, writing unit/integration/E2E tests, measuring coverage, mocking dependencies, or debugging test failures. Covers Node.js (Jest/Vitest), Python (pytest), Go, Rust, and Bash.
Install via ClawdBot CLI:
clawdbot install gitgoodordietrying/test-patternsWrite, run, and debug tests across languages. Covers unit tests, integration tests, E2E tests, mocking, coverage, and TDD workflows.
# Jest
npm install -D jest
# Add to package.json: "scripts": { "test": "jest" }
# Vitest (faster, ESM-native)
npm install -D vitest
# Add to package.json: "scripts": { "test": "vitest" }
// math.js
export function add(a, b) { return a + b; }
export function divide(a, b) {
if (b === 0) throw new Error('Division by zero');
return a / b;
}
// math.test.js
import { add, divide } from './math.js';
describe('add', () => {
test('adds two positive numbers', () => {
expect(add(2, 3)).toBe(5);
});
test('handles negative numbers', () => {
expect(add(-1, 1)).toBe(0);
});
test('handles zero', () => {
expect(add(0, 0)).toBe(0);
});
});
describe('divide', () => {
test('divides two numbers', () => {
expect(divide(10, 2)).toBe(5);
});
test('throws on division by zero', () => {
expect(() => divide(10, 0)).toThrow('Division by zero');
});
test('handles floating point', () => {
expect(divide(1, 3)).toBeCloseTo(0.333, 3);
});
});
// api.test.js
import { fetchUser } from './api.js';
test('fetches user by id', async () => {
const user = await fetchUser('123');
expect(user).toHaveProperty('id', '123');
expect(user).toHaveProperty('name');
expect(user.name).toBeTruthy();
});
test('throws on missing user', async () => {
await expect(fetchUser('nonexistent')).rejects.toThrow('Not found');
});
// Mock a module
jest.mock('./database.js');
import { getUser } from './database.js';
import { processUser } from './service.js';
test('processes user from database', async () => {
// Setup mock return value
getUser.mockResolvedValue({ id: '1', name: 'Alice', active: true });
const result = await processUser('1');
expect(result.processed).toBe(true);
expect(getUser).toHaveBeenCalledWith('1');
expect(getUser).toHaveBeenCalledTimes(1);
});
// Mock fetch
global.fetch = jest.fn();
test('calls API with correct params', async () => {
fetch.mockResolvedValue({
ok: true,
json: async () => ({ data: 'test' }),
});
const result = await myApiCall('/endpoint');
expect(fetch).toHaveBeenCalledWith('/endpoint', expect.objectContaining({
method: 'GET',
}));
});
// Spy on existing method (don't replace, just observe)
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
// ... run code ...
expect(consoleSpy).toHaveBeenCalledWith('expected message');
consoleSpy.mockRestore();
# Jest
npx jest --coverage
# Vitest
npx vitest --coverage
# Check coverage thresholds (jest.config.js)
# coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } }
pip install pytest pytest-cov
# calculator.py
def add(a, b):
return a + b
def divide(a, b):
if b == 0:
raise ValueError("Division by zero")
return a / b
# test_calculator.py
import pytest
from calculator import add, divide
def test_add():
assert add(2, 3) == 5
def test_add_negative():
assert add(-1, 1) == 0
def test_divide():
assert divide(10, 2) == 5.0
def test_divide_by_zero():
with pytest.raises(ValueError, match="Division by zero"):
divide(10, 0)
def test_divide_float():
assert divide(1, 3) == pytest.approx(0.333, abs=0.001)
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(-1, 1, 0),
(0, 0, 0),
(100, -50, 50),
])
def test_add_cases(a, b, expected):
assert add(a, b) == expected
import pytest
import json
import tempfile
import os
@pytest.fixture
def sample_users():
"""Provide test user data."""
return [
{"id": 1, "name": "Alice", "email": "alice@test.com"},
{"id": 2, "name": "Bob", "email": "bob@test.com"},
]
@pytest.fixture
def temp_db(tmp_path):
"""Provide a temporary SQLite database."""
import sqlite3
db_path = tmp_path / "test.db"
conn = sqlite3.connect(str(db_path))
conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
conn.commit()
yield conn
conn.close()
def test_insert_users(temp_db, sample_users):
for user in sample_users:
temp_db.execute("INSERT INTO users VALUES (?, ?, ?)",
(user["id"], user["name"], user["email"]))
temp_db.commit()
count = temp_db.execute("SELECT COUNT(*) FROM users").fetchone()[0]
assert count == 2
# Fixture with cleanup
@pytest.fixture
def temp_config_file():
path = tempfile.mktemp(suffix=".json")
with open(path, "w") as f:
json.dump({"key": "value"}, f)
yield path
os.unlink(path)
from unittest.mock import patch, MagicMock, AsyncMock
# Mock a function
@patch('mymodule.requests.get')
def test_fetch_data(mock_get):
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = {"data": "test"}
result = fetch_data("https://api.example.com")
assert result == {"data": "test"}
mock_get.assert_called_once_with("https://api.example.com")
# Mock async
@patch('mymodule.aiohttp.ClientSession.get', new_callable=AsyncMock)
async def test_async_fetch(mock_get):
mock_get.return_value.__aenter__.return_value.json = AsyncMock(return_value={"ok": True})
result = await async_fetch("/endpoint")
assert result["ok"] is True
# Context manager mock
def test_file_reader():
with patch("builtins.open", MagicMock(return_value=MagicMock(
read=MagicMock(return_value='{"key": "val"}'),
__enter__=MagicMock(return_value=MagicMock(read=MagicMock(return_value='{"key": "val"}'))),
__exit__=MagicMock(return_value=False),
))):
result = read_config("fake.json")
assert result["key"] == "val"
# Run with coverage
pytest --cov=mypackage --cov-report=term-missing
# HTML report
pytest --cov=mypackage --cov-report=html
# Open htmlcov/index.html
# Fail if coverage below threshold
pytest --cov=mypackage --cov-fail-under=80
// math.go
package math
import "errors"
func Add(a, b int) int { return a + b }
func Divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
// math_test.go
package math
import (
"testing"
"math"
)
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, 1, 0},
{"zeros", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Add(tt.a, tt.b)
if got != tt.expected {
t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
}
})
}
}
func TestDivide(t *testing.T) {
result, err := Divide(10, 2)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if math.Abs(result-5.0) > 0.001 {
t.Errorf("Divide(10, 2) = %f, want 5.0", result)
}
}
func TestDivideByZero(t *testing.T) {
_, err := Divide(10, 0)
if err == nil {
t.Error("expected error for division by zero")
}
}
# All tests
go test ./...
# Verbose
go test -v ./...
# Specific package
go test ./pkg/math/
# With coverage
go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# Run specific test
go test -run TestAdd ./...
# Race condition detection
go test -race ./...
# Benchmark
go test -bench=. ./...
// src/math.rs
pub fn add(a: i64, b: i64) -> i64 { a + b }
pub fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 { return Err("division by zero".into()); }
Ok(a / b)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
assert_eq!(add(-1, 1), 0);
}
#[test]
fn test_divide() {
let result = divide(10.0, 2.0).unwrap();
assert!((result - 5.0).abs() < f64::EPSILON);
}
#[test]
fn test_divide_by_zero() {
assert!(divide(10.0, 0.0).is_err());
}
#[test]
#[should_panic(expected = "overflow")]
fn test_overflow_panics() {
let _ = add(i64::MAX, 1); // Will panic on overflow in debug
}
}
cargo test
cargo test -- --nocapture # Show println output
cargo test test_add # Run specific test
cargo tarpaulin # Coverage (install: cargo install cargo-tarpaulin)
#!/bin/bash
# test.sh - Minimal bash test framework
PASS=0 FAIL=0
assert_eq() {
local actual="$1" expected="$2" label="$3"
if [ "$actual" = "$expected" ]; then
echo " PASS: $label"
((PASS++))
else
echo " FAIL: $label (got '$actual', expected '$expected')"
((FAIL++))
fi
}
assert_exit_code() {
local cmd="$1" expected="$2" label="$3"
eval "$cmd" >/dev/null 2>&1
assert_eq "$?" "$expected" "$label"
}
assert_contains() {
local actual="$1" substring="$2" label="$3"
if echo "$actual" | grep -q "$substring"; then
echo " PASS: $label"
((PASS++))
else
echo " FAIL: $label ('$actual' does not contain '$substring')"
((FAIL++))
fi
}
# --- Tests ---
echo "Running tests..."
# Test your scripts
output=$(./my-script.sh --help 2>&1)
assert_exit_code "./my-script.sh --help" "0" "help flag exits 0"
assert_contains "$output" "Usage" "help shows usage"
output=$(./my-script.sh --invalid 2>&1)
assert_exit_code "./my-script.sh --invalid" "1" "invalid flag exits 1"
# Test command outputs
assert_eq "$(echo 'hello' | wc -c | tr -d ' ')" "6" "echo hello is 6 bytes"
echo ""
echo "Results: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] && exit 0 || exit 1
#!/bin/bash
# test-api.sh - Start server, run tests, tear down
SERVER_PID=""
cleanup() { [ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null; }
trap cleanup EXIT
# Start server in background
npm start &
SERVER_PID=$!
sleep 2 # Wait for server
# Run tests against live server
BASE_URL=http://localhost:3000 npx jest --testPathPattern=integration
EXIT_CODE=$?
exit $EXIT_CODE
import pytest
import sqlite3
@pytest.fixture
def db():
"""Fresh database for each test."""
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT, price REAL)")
yield conn
conn.close()
def test_insert_and_query(db):
db.execute("INSERT INTO items (name, price) VALUES (?, ?)", ("Widget", 9.99))
db.commit()
row = db.execute("SELECT name, price FROM items WHERE name = ?", ("Widget",)).fetchone()
assert row == ("Widget", 9.99)
def test_empty_table(db):
count = db.execute("SELECT COUNT(*) FROM items").fetchone()[0]
assert count == 0
The red-green-refactor cycle:
# Tight feedback loop
# Jest watch mode
npx jest --watch
# Vitest watch (default)
npx vitest
# pytest watch (with pytest-watch)
pip install pytest-watch
ptw
# Go (with air or entr)
ls *.go | entr -c go test ./...
Test passes alone, fails in suite โ shared state. Check for:
afterEach / teardown)Test fails intermittently (flaky) โ timing or ordering issue:
awaitCoverage shows uncovered branches โ missing edge cases:
# Jest
npx jest -t "test name substring"
# pytest
pytest -k "test_divide_by_zero"
# Go
go test -run TestDivideByZero ./...
# Rust
cargo test test_divide
assert per test, but one logical check).test_returns_empty_list_when_no_users_exist beats test_get_users_2.tmp_path (pytest), t.TempDir() (Go), or tempfile (Node) for file-based tests.Generated Mar 1, 2026
A tech startup building a new web application needs to establish a robust testing framework from the outset to ensure code quality and prevent regressions. The team uses Node.js with Jest for unit testing and Python with pytest for backend API integration tests, enabling rapid iteration and reliable deployments.
An e-commerce company maintains a large codebase with frequent updates to payment processing and inventory management systems. They use this skill to write integration tests for API endpoints and mock external dependencies like payment gateways, ensuring high availability and reducing downtime during releases.
A financial institution requires rigorous testing for regulatory compliance in transaction processing and data security modules. The skill helps implement unit tests in Go for performance-critical components and coverage measurement to meet audit requirements, minimizing risk of errors.
A DevOps team integrates testing into CI/CD pipelines for a microservices architecture using multiple languages. They leverage the skill to automate test runs with Vitest for frontend services and pytest for backend, improving deployment speed and reliability across cloud environments.
Contributors to an open-source project use this skill to write and debug tests across different programming languages like Rust and Bash, ensuring cross-platform compatibility and facilitating community collaboration through standardized testing practices.
A company offers a cloud-based testing platform that integrates this skill's capabilities, allowing clients to automate test suites across languages without managing infrastructure. Revenue is generated through subscription tiers based on usage and support levels.
A consultancy provides expert services to help organizations adopt test-driven development and improve their testing strategies using this skill. Revenue comes from project-based contracts, workshops, and ongoing support for teams transitioning to modern testing practices.
A developer creates a CLI tool or IDE plugin that leverages this skill to streamline test writing and execution, offering a free basic version with premium features like advanced mocking and coverage analytics. Revenue is generated through paid upgrades and enterprise licenses.
๐ฌ Integration Tip
Integrate this skill into existing CI/CD pipelines by adding test scripts to package.json or pyproject.toml, and use environment variables to manage test configurations across different stages like development and production.
Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad-hoc servers, config edits, and CLI/type generation.
Connect to 100+ APIs (Google Workspace, Microsoft 365, GitHub, Notion, Slack, Airtable, HubSpot, etc.) with managed OAuth. Use this skill when users want to...
Build, debug, and deploy websites using HTML, CSS, JavaScript, and modern frameworks following production best practices.
YouTube Data API integration with managed OAuth. Search videos, manage playlists, access channel data, and interact with comments. Use this skill when users want to interact with YouTube. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
Scaffold, test, document, and debug REST and GraphQL APIs. Use when the user needs to create API endpoints, write integration tests, generate OpenAPI specs, test with curl, mock APIs, or troubleshoot HTTP issues.
Search for jobs across LinkedIn, Indeed, Glassdoor, ZipRecruiter, Google Jobs, Bayt, Naukri, and BDJobs using the JobSpy MCP server.