Đo trước, tối ưu sau. Cả Jest lẫn Vitest đều in được thời gian từng file (--reporter=verbose, Jest có --detectOpenHandles để tìm handle treo). Thường 10% số test chiếm phần lớn thời gian.
Các hướng cắt, theo thứ tự hiệu quả:
1. Bỏ chờ thật. Mọi sleep, waitForTimeout(3000), polling trong test → fake timers hoặc chờ theo điều kiện (waitFor) thay vì chờ theo giây.
2. Đổi tầng test. Nhiều nhóm test qua E2E những thứ đáng lẽ test ở tầng logic. Một kịch bản E2E vài chục giây có thể thay bằng vài test hàm chạy mili giây; giữ E2E cho vài luồng quan trọng nhất.
3. Chạy song song. Vitest/Jest mặc định chạy song song theo file — điều kiện là test phải độc lập dữ liệu. Nếu đang phải --runInBand vì dùng chung DB thì gốc vấn đề là cách ly dữ liệu, sửa chỗ đó.
4. Tách pipeline. Test nhanh (unit) chạy mọi commit; test chậm (integration, E2E) chạy khi mở PR hoặc trước khi deploy. Lập trình viên nhận phản hồi trong 1-2 phút.
5. Dựng môi trường một lần. DB container, migration, seed nên chạy một lần cho cả suite thay vì mỗi file.
Ngưỡng nên nhắm: bộ test nhanh dưới ~2 phút. Quá đó là người ta sẽ bắt đầu push mà không chạy.