Skip to main content

Code Review Guidelines for QA

Code reviews are a critical phase where QA engineers ensure high-quality, testable, and maintainable code. This guide helps QA engineers conduct effective code reviews that catch issues early and maintain quality standards.

Why QA Code Reviews Matter​

"Why do we need testers to review code when we have code coverage tools that guarantee fully tested code?"

"Fully tested" is misleading. 100% code coverage does not equal high-quality tests nor correct functionality. Coverage only confirms the lines of code executed—not that the logic is correct, meaningful, or aligned with requirements.

Without a QA perspective, teams often overlook:

  • Missing test scenarios: Edge cases and error conditions not covered
  • Incorrect test logic: Tests that pass but don't validate the right behaviour
  • Missing business requirements: Code that doesn't implement acceptance criteria
  • Poor error handling: Missing validation or unhelpful error messages
  • Testability issues: Code that's difficult to test or maintain
  • Accessibility problems: Missing ARIA attributes or keyboard navigation

The examples below use an Activity Management React form, but the principles apply across products and codebases.

Example: Missing Functionality & Missing Tests​

Data transformation requirements for firstName​

  • Remove extra spaces and apply Title Case
  • Remove spaces around hyphens
  • Capitalise the first letter of the forename
  • Capitalise characters after hyphens and apostrophes

Existing Unit Tests​

it("capitalises initial letters", () => {
const { firstName } = transform({ firstName: "john" });
expect(firstName).toBe("John");
});

it("capitalises initial letters after spaces", () => {
const { firstName } = transform({ firstName: "lily rose" });
expect(firstName).toBe("Lily Rose");
});

it("capitalises initial letters after apostrophes", () => {
const { firstName } = transform({ firstName: "D'andre" });
expect(firstName).toBe("D'Andre");
});

it("capitalises initial letters after hyphens", () => {
const { firstName } = transform({ firstName: "Lily-rose" });
expect(firstName).toBe("Lily-Rose");
});

it("removes spaces around hyphens", () => {
const { firstName } = transform({ firstName: "Lily - Rose" });
expect(firstName).toBe("Lily-Rose");
});

Test Coverage Analysis​

Based on the requirements mentioned in the acceptance criteria, here's the test coverage analysis:

Test caseUnit test coverage
Capitalises initial letters✅ Yes
Capitalises initial letters after spaces✅ Yes
Capitalises initial letters after apostrophes✅ Yes
Capitalises initial letters after hyphens✅ Yes
Removes spaces around hyphens✅ Yes
Removes spaces around apostrophes❌ No
Removes extra spaces❌ No
Truncates spaces❌ No

These gaps revealed missing functionality and led to appropriate defects being raised.

Unit Test Review Checklist (QA-Focused)​

1. Does the code have tests?​

Some functionality still ships without any unit tests. Flag early.


2. Are all acceptance criteria covered?​

Use ACs + exploratory thinking to identify edge cases.


3. Are assertions meaningful?​

A test that “passes” without verifying behaviour is useless.

Bad example for a reverse-string function:

expect(result).not.toBe("");

Good example:

expect(result).toBe("cba");


4. Do tests follow test design principles?​

Use the AAA (Arrange–Act–Assert) pattern

Test one behaviour per test

Tests should be deterministic


5. Are test names clear and descriptive?​

Good test names describe input + behaviour + expected outcome.

  • ❌ it("should work")
  • ✅ it("capitalises the first letter of a single-word forename")

6. Are tests duplicated?​

  • Avoid repeating tests across similar fields
  • Remove duplicated acceptance tests if unit tests cover the same behaviour

7. Is the code testable?​

If not, recommend refactoring:

  • Large multi-purpose functions
  • Hidden dependencies
  • Tight coupling
  • Side effects that make tests unpredictable

8. Are boundary and edge cases covered?​

Examples:

  • Empty strings
  • Null/undefined
  • Unicode or accented characters
  • Trailing/leading/multiple spaces
  • Max-length strings

9. Are tests included for bug fixes?​

  • Every bug fix should include a unit test that reproduces the original bug and verifies the fix.

  • The test ensures the bug does not reoccur in the future (prevents regressions).

  • It serves as documentation of expected behaviour and improves confidence in future code changes.

When QA Can Block a Story Based on Unit Tests​

QA should block if:​

  • Key acceptance criteria are untested
  • Critical logic lacks negative or boundary tests
  • Tests are failing or flaky
  • Assertions are missing or meaningless
  • Test quality prevents understanding behaviour

QA should not block for:​

  • Style preferences
  • Choices between equivalent testing patterns
  • Minor naming or formatting issues

Using Copilot in Code Reviews​

GitHub Copilot can be used to support QA during code reviews, but they must not replace human judgement.

Reviewers are encouraged to use Copilot to:

  • Summarise pull requests and identify key changes

  • Highlight potential bugs, edge cases, and test gaps

  • Spot inconsistencies with coding standards or patterns

  • Suggest additional test scenarios

Copilot should not be relied on to:

  • Approve or reject pull requests

  • Validate business logic or requirements

  • Guarantee correctness, security, or compliance

Final responsibility for code quality, test coverage, and release readiness always remains with the human reviewer.

Advanced Practices: Mutation Testing​

Mutation testing evaluates test strength by injecting small changes (mutations) into the code. If tests don't catch the mutation, the test suite may be inadequate.

Tool example: Stryker Mutator

Summary​

Unit tests are essential for maintaining product quality, as they help identify faults early in the development cycle. However, high coverage alone does not guarantee high-quality code — tests must be meaningful, thorough, and effective.

QA Engineers play a critical role in reviewing unit tests to ensure:

  • All test conditions and requirements are covered

  • Missing scenarios are identified and supplemented with additional tests

  • Customer-focused perspectives are maintained

Effective unit test reviews strengthen the codebase, prevent defects from reaching production, and support a more reliable testing pyramid.

References​