Step 00: Basic Test Function
このステップでは、最も基本的なテスト関数 test() を実装します。async/await にも対応しています。
目標
test(name, fn)関数でテストケースを登録できるit(name, fn)をtestのエイリアスとして提供- 同期・非同期の両方のテストをサポート
runTests()でテストを実行し結果を表示
実装
src/index.ts
typescript
export type TestFunction = () => void | Promise<void>;
interface TestCase {
name: string;
fn: TestFunction;
}
export interface TestResult {
name: string;
status: "passed" | "failed";
error?: Error;
}
export interface TestSummary {
total: number;
passed: number;
failed: number;
results: TestResult[];
}
const testCases: TestCase[] = [];
export function test(name: string, fn: TestFunction): void {
testCases.push({ name, fn });
}
export const it = test;
export async function runTests(): Promise<TestSummary> {
const results: TestResult[] = [];
for (const testCase of testCases) {
try {
await testCase.fn();
results.push({ name: testCase.name, status: "passed" });
console.log(` ✓ ${testCase.name}`);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
results.push({ name: testCase.name, status: "failed", error: err });
console.log(` ✗ ${testCase.name}`);
console.log(` Error: ${err.message}`);
}
}
const passed = results.filter((r) => r.status === "passed").length;
const failed = results.filter((r) => r.status === "failed").length;
console.log("");
console.log(`Tests: ${passed} passed, ${failed} failed, ${results.length} total`);
return { total: results.length, passed, failed, results };
}
export function clearTests(): void {
testCases.length = 0;
}使用例
typescript
import { test, it, runTests } from "../src/index.js";
test("should pass a simple test", () => {
const result = 1 + 1;
if (result !== 2) {
throw new Error(`Expected 2 but got ${result}`);
}
});
it("should work with it alias", () => {
const arr = [1, 2, 3];
if (arr.length !== 3) {
throw new Error("Array length should be 3");
}
});
test("should handle async tests", async () => {
const result = await Promise.resolve(42);
if (result !== 42) {
throw new Error(`Expected 42 but got ${result}`);
}
});
test("should fail intentionally", () => {
throw new Error("This test is expected to fail");
});
runTests().then((summary) => {
if (summary.failed > 0) {
process.exit(1);
}
});出力例
✓ should pass a simple test
✓ should work with it alias
✓ should handle async tests
✗ should fail intentionally
Error: This test is expected to fail
Tests: 3 passed, 1 failed, 4 totalエクスポート API
| API | 説明 |
|---|---|
test(name, fn) | テストケースを登録 |
it(name, fn) | test のエイリアス |
runTests() | テストを実行し結果を返す |
clearTests() | テストケースをクリア |
実行方法
bash
cd impls/00-basic-test-function
bun run exampleまたは:
bash
pnpm example:00ポイント解説
テストケースの収集
test() 関数は、テストケースをグローバルな配列に登録するだけです。これにより、ファイルが読み込まれた時点でテストが自動的に収集されます。
async/await 対応
runTests() 内で await testCase.fn() を使用することで、同期・非同期の両方のテスト関数を透過的に扱えます。
エラーハンドリング
テスト内で例外が投げられると、そのテストは失敗として扱われます。この段階では単純に throw new Error() でアサーションを行っていますが、次のステップで expect() を導入します。