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