Write 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.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Write 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.
import pytest
import json
import tempfile
import os
@pytest.fixturedefsample_users():
"""Provide test user data."""return [
{"id": 1, "name": "Alice", "email": "alice@test.com"},
{"id": 2, "name": "Bob", "email": "bob@test.com"},
]
@pytest.fixturedeftemp_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()
deftest_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.fixturedeftemp_config_file():
path = tempfile.mktemp(suffix=".json")
withopen(path, "w") as f:
json.dump({"key": "value"}, f)
yield path
os.unlink(path)
Mocking
from unittest.mock import patch, MagicMock, AsyncMock
# Mock a function@patch('mymodule.requests.get')deftest_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)asyncdeftest_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"] isTrue# Context manager mockdeftest_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"
Coverage
# 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
Go
Unit Tests
// math.gopackage math
import"errors"funcAdd(a, b int)int { return a + b }
funcDivide(a, b float64) (float64, error) {
if b == 0 {
return0, errors.New("division by zero")
}
return a / b, nil
}
// math_test.gopackage math
import (
"testing""math"
)
funcTestAdd(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)
}
})
}
}
funcTestDivide(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)
}
}
funcTestDivideByZero(t *testing.T) {
_, err := Divide(10, 0)
if err == nil {
t.Error("expected error for division by zero")
}
}
Run Tests
# 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=. ./...
Rust
Unit Tests
// src/math.rspubfnadd(a: i64, b: i64) ->i64 { a + b }
pubfndivide(a: f64, b: f64) ->Result<f64, String> {
if b == 0.0 { returnErr("division by zero".into()); }
Ok(a / b)
}
#[cfg(test)]mod tests {
use super::*;
#[test]fntest_add() {
assert_eq!(add(2, 3), 5);
assert_eq!(add(-1, 1), 0);
}
#[test]fntest_divide() {
letresult = divide(10.0, 2.0).unwrap();
assert!((result - 5.0).abs() < f64::EPSILON);
}
#[test]fntest_divide_by_zero() {
assert!(divide(10.0, 0.0).is_err());
}
#[test]#[should_panic(expected = "overflow")]fntest_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)
Bash Tests
Simple Test Runner
#!/bin/bash# test.sh - Minimal bash test framework
PASS=0 FAIL=0
assert_eq() {
local actual="$1" expected="$2" label="$3"if [ "$actual" = "$expected" ]; thenecho" PASS: $label"
((PASS++))
elseecho" 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"ifecho"$actual" | grep -q "$substring"; thenecho" PASS: $label"
((PASS++))
elseecho" 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
Integration Testing Patterns
API Integration Test (any language)
#!/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
Database Integration Test (Python)
import pytest
import sqlite3
@pytest.fixturedefdb():
"""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()
deftest_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)
deftest_empty_table(db):
count = db.execute("SELECT COUNT(*) FROM items").fetchone()[0]
assert count == 0
TDD Workflow
The red-green-refactor cycle:
Red: Write a failing test for the next piece of behavior
Green: Write the minimum code to make it pass
Refactor: Clean up without changing behavior (tests stay green)
# 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 ./...
Debugging Failed Tests
Common Issues
Test passes alone, fails in suite → shared state. Check for:
Global variables modified between tests
Database not cleaned up
Mocks not restored (afterEach / teardown)
Test fails intermittently (flaky) → timing or ordering issue: