For the complete documentation index, see llms.txt. This page is also available as Markdown.

Functional Testing with AI Agents

Turn business requirements into functional tests with Claude Code, Cursor, or Codex, then create and verify ContextQA cases through MCP.

Quick answer

Start with a requirement, turn it into an observable expected outcome, and ask your coding agent to test that behavior at the most useful layer. Functional testing describes what the software must do, not a particular framework: a functional rule can be checked through a function, an API, or a browser. ContextQA MCP can turn requirements into cases, but you still need to review their assertions and inspect real execution results.

This guide follows a report-export permission rule from a decision table to code-level checks and a ContextQA browser workflow. The example is illustrative; it does not describe a particular customer's authorization model.

Functional, integration, and end-to-end are different dimensions

A functional test asks whether an approved user can export a ready report and whether a disallowed request is denied. An integration test asks whether real connected components cooperate correctly. An end-to-end test asks whether the full selected journey works. One test may satisfy more than one description.

Use fast code-level checks for numerous rule combinations, real API tests for authorization enforcement, and selected browser flows for the user's experience. A disabled button is useful UX evidence, but it cannot establish that an API rejects a forbidden request. See unit, integration, and end-to-end testing for those layers.

Prerequisites

You need an agreed requirement, named roles and states, representative disposable data, the existing test command, and an environment where you can verify the outcome. Record unresolved policy questions instead of asking the agent to invent them.

For our example, report export is allowed only when the requester belongs to the report's tenant, the role is admin or analyst, and the report state is ready. A viewer cannot export. Tenant checks happen before role or readiness checks so a cross-tenant request does not disclose a report's state.

The small runnable example uses Node.js 24 or later and its built-in test runner. No ContextQA access is needed for the local exercise. Node test runner.

1. Make a decision table before generating tests

Requirement
Given
Expected outcome

F-01

Same tenant, analyst, ready report

Export permitted

F-02

Same tenant, admin, ready report

Export permitted

F-03

Same tenant, viewer, ready report

Denied; no file produced

F-04

Same tenant, analyst, building report

Denied as not ready

F-05

Different tenant, admin, ready report

Denied without revealing report state

F-06

Same tenant, unknown role, ready report

Denied by default

Discuss ambiguous states such as cancelled, failed, deleted, and expired reports. Determine what should happen if permission is revoked between opening the page and clicking Export. These are product questions; fluent generated steps are not a substitute for an agreed answer.

2. Ask the agent to preserve the business rule

Use this prompt with Claude Code, Cursor, or Codex:

This makes the handoff reviewable for a QA manager or product owner who does not use the agent's editor. Each result answers a requirement rather than merely listing how many scripts were generated.

3. Run a small policy example

Create report-policy.mjs:

Create report-policy.test.mjs beside it:

Run:

This is a functional decision table executed at the unit level. It verifies the illustrated policy function, not a deployed application's authentication or storage. To test your real product, import the policy it actually calls, then use API and browser checks to establish enforcement. Do not accept a separate test-only policy function as evidence about production code.

4. Verify the action, its absence, and the artifact

For an allowed export, assert the file type, expected headers or schema, known row values, tenant identity, and report identifier. Use a small seeded dataset with an exact expected result. “File exists” can pass even if the file contains an error page, an empty body, or another user's records.

For a denied export, verify the documented denial and the absence of the forbidden side effect. Decide how to observe that reliably: no successful export response, no new export record, or a bounded check that no download starts. The strongest check depends on your architecture. If the test cannot inspect the required state, mark that part unverified.

Test stale sessions and permissions changed mid-flow separately. Keep setup assertions clear so a missing seeded report is diagnosed as a precondition problem rather than a product authorization failure.

5. Create corresponding ContextQA cases through MCP

Set up ContextQA MCP, confirm the correct workspace, and inspect available tools. The documented generate_tests_from_requirements tool accepts requirements_text. Supply the decision table, approved staging URL, role fixtures, and exact expected behavior in that requirements text. Generation does not establish execution or coverage quality. Generation reference.

Use get_test_case_steps to review the created cases, then the documented execution/status/result tools to obtain evidence. A terminal completion state is not itself a passing assertion. See case management and execution results.

Review and debugging

When expected and actual behavior disagree, establish which requirement is authoritative before changing code or tests. A screenshot of “Access denied” is a good result for the viewer case and a defect for the allowed analyst case. Keep that interpretation attached to the role and seeded state.

If a locator changes, repair how the test finds the same intended element. Do not remove the authorization assertion or broaden the target to a different action. Retries, generated explanations, and self-healing proposals should retain the original evidence and expected outcome.

Common questions

Does functional testing mean browser testing?

No. It checks required behavior at the layer that exposes the relevant risk. Browser testing is one execution method.

Can AI derive tests from a ticket?

It can propose cases, but incomplete acceptance criteria remain incomplete. Review roles, state, boundaries, and expected results before treating the generated cases as coverage.

How do we keep the tests portable?

Store native tests and requirement IDs in Git. For ContextQA cases, follow export and portability, inspect assertions and fixtures after export, and rerun them before claiming equivalent coverage.

Next step: Connect ContextQA MCP to translate one decision table into reviewable cases. For a demonstration using your roles and report workflow, book a functional-testing demo.

Last updated

Was this helpful?