AJM Softwares · Technical note
Start with risks and expected behavior
List the user and system behaviors that would cause the most harm if they broke: creating an account, saving an enquiry, changing an important record, applying permissions, or completing a payment. Define what a user should observe when each action succeeds and when it fails.
Turn those expectations into tests before choosing a tool. A test that mirrors the user's outcome is less likely to pass while the actual workflow is broken than a test tied only to a private function name or a particular CSS class.
Use the right level for each check
Test small business rules directly with unit tests. Use integration tests for boundaries such as request validation, database behavior, and service adapters. Use browser tests for a small set of important journeys that need the real interface, navigation, and form behavior to work together.
Keep slower end-to-end tests focused on user-visible outcomes and keep broad business-rule coverage close to the code where it can run quickly. No single level replaces the others: a browser test may show that a flow works, while a focused integration test can explain exactly which boundary broke.
Cover failures and state transitions
Add cases for invalid inputs, empty values, permission denials, duplicate submissions, dependency timeouts, and partial failures that matter to the feature. Verify both the response and the resulting state, such as whether a failed request left an unexpected database record behind.
When behavior changes, add a regression test that would have caught the original bug. Use controlled clocks, fixtures, and test data rather than depending on external services or the current time where possible.
Keep tests isolated and useful in continuous integration
Tests should be repeatable on a clean machine and should not depend on execution order or shared mutable data. Browser test guidance recommends isolated tests and assertions that wait for the visible result, which reduces timing-related failures.
Run the relevant tests, type checks, linting, and production build in the release workflow. Treat a failing test as evidence to investigate; do not make a flaky check green by weakening the assertion until it no longer protects the behavior.
