ClickMasters
← Back to all FAQ cards

QA & Software Testing

Automated Testing Services FAQs

What is the difference between unit tests, integration tests, and E2E tests?

Unit tests test individual functions or modules in isolation all dependencies are mocked. They are fast (milliseconds each), easy to write, and catch logic bugs in pure business code. Integration tests test multiple components working together typically an API endpoint with a real database (no mocking). They are slower (seconds each, due to database startup) but catch real bugs that unit tests miss SQL errors, schema mismatches, incorrect query logic. End-to-end tests run in a real browser and simulate complete user workflows login, navigate, interact, verify the outcome. They are slowest (seconds to minutes each) but catch integration failures between frontend, backend, and database. The test pyramid principle: many unit tests (fast, cheap), a moderate number of integration tests (medium speed, high value), and a small number of focused E2E tests (slow, high confidence). ClickMasters implements all three layers each type catches a class of bugs the others miss.

Why does ClickMasters use Testcontainers instead of mocking the database?

Mocking the database in integration tests produces tests that pass even when the application has bugs specifically bugs that would only manifest with a real database: SQL syntax errors (a mocked database accepts any SQL string), schema migration state (a mocked database is not aware of your actual schema a test can pass with a mocked database even if the column it queries does not exist), transaction behaviour (mocked databases cannot simulate database-level constraint violations, transaction rollbacks, or concurrent writes), and ORM behaviour differences (some ORM queries produce different SQL in different environments Testcontainers uses the same database engine as production, ensuring the same SQL is executed). Testcontainers starts a real PostgreSQL Docker container for the test run the exact same database engine, configuration, and schema as production. Tests that pass with Testcontainers have a much higher probability of passing in production.

What is React Testing Library and how does it differ from Enzyme?

React Testing Library (RTL) is a testing utility that renders React components and provides queries for finding elements in the way a user would find them (by role, label, text), not in the way a developer would find them (by component name, props, or state). The design principle: test the behaviour a user would observe, not the implementation details of the component. RTL encourages: querying by accessible role (`getByRole('button', {name: 'Submit'})`), testing user interactions (`await userEvent.click(button)`), and asserting on visible outcomes (text appears, element is visible, navigation occurs) not on React state, prop values, or component hierarchy. Enzyme (the previous dominant React testing library) encouraged testing implementation details component internal state, lifecycle methods, direct prop manipulation. Enzyme tests break when components are refactored (even if user-visible behaviour is unchanged). RTL tests survive refactors because they test what the user sees, not how the code works. Enzyme is deprecated as of React 18; RTL is the current standard.

How do you determine what coverage percentage to require?

Code coverage percentage is a proxy metric for test suite quality not a target in itself. 100% coverage does not mean a codebase is bug-free; 80% coverage with well-written tests is more valuable than 95% coverage with superficial tests. ClickMasters recommends: 80% minimum line and branch coverage as a CI gate (below this threshold, there are clearly untested paths that represent risk), with a focus on 100% coverage of critical paths (authentication, payment processing, data access control every branch tested). Coverage should be measured on branches (not just lines) a function with `if/else` that is only tested for the `if` case has 100% line coverage but 50% branch coverage. The coverage gate in CI is a floor, not a ceiling the goal is not to reach exactly 80% and stop, but to ensure the floor is never dropped below as new code is added. ClickMasters configures per-directory coverage thresholds where appropriate stricter for security-critical modules, standard for utility code.