Frontend Unit Testing as Documentation: Challenges and Practices
The team combats outdated documentation and costly front‑end maintenance by treating unit tests for the use‑case layer as living documentation, using BDD‑style Given‑When‑Then tests that assert only observable behavior, which improves code readability, eases onboarding, and provides a reliable safety net for future changes.
Background: The merchant system provides stable services for merchants on the platform, but documentation often lags behind code changes, making it hard to trace business logic later.
Difficulty: Front‑end code can grow to thousands of lines, mixing UI, DOM interactions, and business logic. Maintaining such large files is costly, and many developers avoid writing unit tests because of the high learning curve.
Concept – “Unit Test as Documentation”: To address the pain points, the team treats unit tests as living documentation. By focusing tests on the usecase layer (business‑logic only) and keeping it independent of UI frameworks, tests become a reliable source of truth.
Use Cases: Identify modules that implement business logic. The clean‑architecture approach separates the usecase layer (which orchestrates business flow) from entities (data adapters). This makes the usecase layer an ideal entry point for testing.
Test Design: The team adopts BDD (Given‑When‑Then) rather than TDD because it aligns with the documentation goal. Test cases are written in the GWT style to describe business behavior instead of low‑level implementation details.
Example – Test Template and Code Snippets: /* usecase focuses on flow description, e.g., URL generation, activity checks */ async function exportActivityLog({count, formValues}) { if (count > 5000) { message.error('导出文件数量不得超过5000!'); return; } const res = await checkIsDuringTheEventApi(); if (res.isDuring) { message.error('活动期间,功能暂不可用,如有疑问联系运营'); return; } const url = generateDownloadUrl({ formValues }); downloadExcelFile(url); } function init() { const checkIsDuringTheEventApi = jest.fn(); const downloadExcelFile = jest.fn(); const exportActivityLog = buildMakeExportActivityLog({checkIsDuringTheEventApi, downloadExcelFile}); return { checkIsDuringTheEventApi, downloadExcelFile, exportActivityLog }; } describe('exportActivityLog', () => { it('should export when activity is not ongoing', () => { const { checkIsDuringTheEventApi, downloadExcelFile, exportActivityLog } = init(); // mock API response checkIsDuringTheEventApi.mockResolvedValue({ isDuring: false }); exportActivityLog({ count: 100, formValues: {} }); expect(downloadExcelFile).toBeCalled(); }); it('should block export when count exceeds limit', () => { const { downloadExcelFile, exportActivityLog } = init(); exportActivityLog({ count: 6000, formValues: {} }); expect(downloadExcelFile).not.toBeCalled(); }); });
Assertion Strategy: Tests assert only on observable behavior (e.g., whether a function was called) rather than internal implementation details. Each test contains a single assertion to keep responsibilities clear.
Conclusion: By treating unit tests as documentation, the team improves code readability, reduces onboarding cost, and creates a stable safety net for future changes. The approach has already yielded hundreds of reusable test cases across projects.
DeWu Technology
A platform for sharing and discussing tech knowledge, guiding you toward the cloud of technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.