Testing
August 7, 2026 · View on GitHub
Approach
For web applications, we champion the testing trophy approach popularized by Kent C. Dodds. Unlike the classic testing pyramid, this approach places the focus on writing a lot of integration tests rather than on writing a lot of unit tests.
___________
/ \ /\
/ E2E \ / \
/---------------\ / \
/ \ / \
/ \ / E2E \
/ INTEGRATION \ /----------\
\ / vs. / \
\ / / \
\-----------------/ / INTEGRATION \
\ UNIT / /------------------\
\-------------/ / \
/ \ / \
/ STATIC \ / UNIT \
/ \ / \
/___________________\ /____________________________\
For the details, please see the full article. But the gist is instead of focusing on achieving 100% code coverage, we aim to achieve highest possible code confidence and return of investment. Writing a lot of unit tests does help boost confidence (though only at micro scale), but also puts pressure on the cost of changes - almost any changes would break some tests. As such, focusing on how the app works on the larger scale such as at integration level and beyond, would allow us to develop with more flexibility while ensuring that what we changed/added do not break the existing feature set.
In the
trophyparadigm,staticrefers to a linting and type-checking which gives a huge confidence boosting during development and helps prevent bugs withundefinedvalue.
Also, just a note why end-to-end (functional) testing just takes a small portion in both diagrams? That's because end-to-end tests, despite being super powerful, are usually costly to setup and maintain.
See detailed comparison between different testing levels here
Implementation
static: We use ESLint for linting and Typescript for type-checking.
unit: We should really only write unit tests for utilities and helpers. We use Jest as the testing framework.
integration: We should have integration tests to cover all use cases. We don't make real network call here, so we should mock out our network client (or not (?), see TODO). We also use Jest.
e2e: Almost the same as integration test, except we drive the real application in a real browser. We use Playwright. In a way, e2e tests are valuable here because it can be used to test the whole application stack as well as a demo for usage and features of the app. End-to-end tests for Legend Query live in packages/legend-application-query-e2e — see its README for developer guidelines on running the suite, debugging failures, and adding new tests. The application under test runs against the mock depot server (fixtures/legend-mock-server) and browser-level engine mocks, so the suite requires no real backend and runs on every PR in CI (see the run-e2e-tests job in .github/workflows/test.yml).
Frontend component testing guidelines
When writing tests for React components, prefer queries that reflect how a user perceives the UI:
- Prefer
getByRole,getByLabelText,getByText, andgetByTitleovercontainer.querySelector(...). - Avoid selecting elements by CSS class names. Class names are implementation details and change frequently during refactors.
- If there’s no good user-facing query (e.g., purely decorative elements), it’s OK to fall back to DOM selectors, but keep this to a minimum.
- Use
data-testidsparingly as an escape hatch when no accessible query is practical.
TODO
- Mock server request instead of mocking the method that makes the network call, maybe this is the better way to write integration test (or even e2e tests)? https://kentcdodds.com/blog/stop-mocking-fetch?ck_subscriber_id=564011516 https://github.com/mswjs/msw