Copilot Chat Cookbook Deep Dive: Testing Code

Why this category matters

The Testing code category focuses on keeping test suites effective as code evolves. It covers generation, isolation, browser-level coverage, and adaptation after logic changes.

Use cases

  • Developers adding or repairing test coverage quickly
  • QA engineers validating AI-generated tests for reliability
  • Developers learning to review and strengthen AI-generated tests

The 4 examples in this category

  1. Generating unit tests
  2. Creating mock objects to abstract layers
  3. Creating end-to-end tests for a webpage
  4. Updating unit tests to match code changes

Diagram: Test generation and maintenance loop

+------------------------------+
| Production code intent       |
+------------------------------+
              |
              v
+------------------------------+
| Prompt for tests             |
| - normal paths               |
| - failures                   |
| - edge cases                 |
+------------------------------+
              |
              v
+------------------------------+
| Execute and inspect          |
| - flakiness                  |
| - missing assertions         |
| - poor isolation             |
+------------------------------+
              |
              v
+------------------------------+
| Refine tests                 |
| - mocks/stubs                |
| - fixtures                   |
| - updated expectations       |
+------------------------------+

1) Generating unit tests

Cookbook scenario:

  • Generate tests for input validation logic with success and failure paths.

Prompt pattern:

Generate unit tests for this function.
Validate both success and failure, and include edge cases.

What to verify:

  • Correct assertions for boundary values.
  • Error messages/types where relevant.
  • No duplicated or redundant test cases.

2) Creating mock objects

Cookbook scenario:

  • Mock a service dependency so server-side logic can be tested without database access.

Prompt pattern:

Create a unit test to ensure the service is called correctly.
Mock the service object.

Practical notes from cookbook:

  • Mention test framework (for example Vitest).
  • Provide existing test files via #file when you want style consistency.

What to verify:

  • Dependency calls use expected arguments.
  • Call counts and behavior assertions are meaningful.
  • Mocks are reset between tests.

3) Creating end-to-end tests

Cookbook scenario:

  • Generate Playwright tests for loading, success, and error states.

Prompt pattern:

Using Playwright, generate an e2e test to ensure the product displays correctly.

What to verify:

  • Stable selectors.
  • Correct API mocking/stubbing behavior.
  • Assertions for loading, happy path, and error UI.

4) Updating tests after code changes

Cookbook scenario:

  • Discount logic changed thresholds and tiers, requiring test updates.

Prompt pattern:

Given the update to the function, update unit tests that may fail or become outdated.

Expected response quality:

  • Identifies which old tests fail.
  • Flags misleading but passing tests.
  • Adds coverage for newly introduced behavior.

Quality checks for cookbook-generated tests

  • Determinism: avoid flaky time, randomness, or async race assumptions.
  • Clarity: test names encode behavior and condition.
  • Coverage intent: branch and edge coverage are explicit.
  • Maintainability: avoid over-mocking and brittle implementation-coupled assertions.

Worked example

Scenario

You changed discount logic and need unit tests updated safely.

// src/pricing/calculateDiscount.ts (original)
export function calculateDiscount(
  price: number,
  tier: "standard" | "premium" | "vip"
): number {
  if (tier === "standard") return price * 0.05;
  if (tier === "premium")  return price * 0.10;
  if (tier === "vip")      return price * 0.20;
  return 0;
}

The rule change raises the standard rate to 8 % and adds a new corporate tier at 15 %. Tests anchored to the old rates will silently pass the wrong values until someone manually spots the drift.

Prompt 1 (generate baseline tests)

Generate unit tests for this function.
Cover normal path, boundary values, and invalid input.

#file:src/pricing/calculateDiscount.ts

Prompt 2 (introduce mocks where needed)

If this function depends on external services, generate mock-based tests that verify call arguments and error handling.

Prompt 3 (update after rule change)

Given the new discount thresholds, update existing tests and list any obsolete assertions.

Validation checklist

  • Tests fail before fix and pass after fix when expected.
  • Boundary and failure paths are explicitly covered.
  • No time/randomness assumptions cause flakiness.

Key takeaways

  • Generated tests are a starting point; quality comes from targeted review.
  • Isolation via mocks is critical for fast and reliable unit tests.
  • End-to-end tests should include both happy and failure paths.
  • Test updates must track business-rule changes, not just syntax changes.


References

Post a Comment

0 Comments