type AsyncFunc = () => Promise; type SyncFunc = () => void; const beforeFuncs: AsyncFunc[] = []; const itFuncs: { desc: string; fn: AsyncFunc }[] = []; const afterFuncs: SyncFunc[] = []; const stats = { total: 0, passed: 0, failed: 0, errors: [] as { type: 'before' | 'it' | 'after'; desc?: string; error: unknown; }[], }; export const before = (func: AsyncFunc) => { beforeFuncs.push(func); return func; }; export const it = (desc: string, func: AsyncFunc) => { itFuncs.push({ desc, fn: func }); }; export const after = (func: SyncFunc) => { afterFuncs.push(func); return func; }; export const describe = async (desc: string, func: () => Promise | void) => { console.log(desc); // 注册阶段 await func(); // before for (const f of beforeFuncs) { try { await f(); } catch (err) { stats.failed++; stats.errors.push({ type: 'before', error: err, }); console.error(' ✗ before failed:', err); } } // it for (const { desc, fn } of itFuncs) { stats.total++; try { console.log(' ' + desc); await fn(); stats.passed++; console.log(' ✓ passed'); } catch (err) { stats.failed++; stats.errors.push({ type: 'it', desc, error: err, }); console.error(' ✗ failed:', err); } } // after(无论如何都执行) for (const f of afterFuncs) { try { f(); } catch (err) { stats.failed++; stats.errors.push({ type: 'after', error: err, }); console.error(' ✗ after failed:', err); } } // 统计输出 printSummary(); }; const printSummary = () => { console.log('\n====== Test Summary ======'); console.log(`Total: ${stats.total}`); console.log(`Passed: ${stats.passed}`); console.log(`Failed: ${stats.failed}`); if (stats.errors.length) { console.log('\nErrors:'); for (const e of stats.errors) { console.log( `- [${e.type}]${e.desc ? ' ' + e.desc : ''}`, '\n ', e.error ); } } console.log('=========================='); };