> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qa.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# PR Testing

> Review a pull request on a preview environment before merge, or against the deployed environment after merge.

A change review reads the pull request or merge request, selects existing tests that cover the user-facing changes, creates tests for what is missing, runs them, and posts the result on the request.

## When the tests run

Pick the timing that matches where the new code is reachable. These are two options, not two steps.

<CardGroup cols={2}>
  <Card title="Before merge" icon="eye" href="#on-a-preview-environment-before-merge">
    Preview environment. The review runs against that request's own deployment,
    before the code reaches your main branch.
  </Card>

  <Card title="After merge" icon="code-merge" href="#after-merge-when-you-have-no-preview-environment">
    No preview environment. Run the review after the merge lands and the deploy
    finishes. The agent tests the merged diff against staging or production.
  </Card>
</CardGroup>

### On a preview environment, before merge

QA.tech gets the target from one of these:

* A deployment your Git host reports, including [GitHub Deployments](/configuration/github-deployments) created from Actions
* A preview URL in a `@qa.tech` comment on the request
* A [Vercel preview](/configuration/vercel-preview-protection) bypass, when deployment protection would block the agent
* For a mobile app, the [build you upload for that pull request](/pr-testing/agents/mobile). Mobile reviews use the binary, not a preview URL.
* For an API application, the [preview base URL](/pr-testing/agents/api)

### After merge, when you have no preview environment

Run the review after the merge lands and the deploy finishes. The agent reads the merged diff and tests against staging or production. The result is posted on the merged request.

* [GitHub](/pr-testing/github#after-merge)
* [GitLab](/pr-testing/gitlab#after-merge)

<Note>
  A post-merge change review tests the merged code. The [post-merge
  agent](/configuration/github-app#post-merge-agent) is a later step on GitHub:
  it can promote tests from that review into your regression suite. It does not
  replace the review.
</Note>

## How it works in practice

Here's what happens when you open a PR that changes your checkout flow:

**1. Automatic Detection**

```
PR opened: "Add Apple Pay to checkout"
→ PR Review agent activates
```

**2. Change Classification**

```
Analyzing diff...
├─ checkout.tsx: USER-FACING ✓
├─ payment-methods.ts: USER-FACING ✓
└─ README.md: DOCS ONLY ✗

Classification: USER-FACING changes detected
```

**3. Coverage Assessment**

```
Existing tests found:
├─ "Complete checkout with credit card" ✓
├─ "Complete checkout with PayPal" ✓
└─ Apple Pay integration: NOT COVERED ⚠️
```

**4. Test Generation**

```
Creating new test:
"Complete checkout flow with Apple Pay"
├─ Add item to cart
├─ Navigate to checkout
├─ Select Apple Pay as payment method
├─ Verify payment confirmation
└─ Verify order appears in account
```

**5. Execution & Review**

```
Running against PR preview environment...
✅ All tests passing (3/3)

Posting GitHub review:
"✅ Tests passing - Apple Pay integration verified"
```

This entire workflow runs autonomously - no human intervention required.

## How a review works

This applies to every CI. The CI guides below cover only how the review starts.

### What a review does

| Feature                           | Description                                                                          |
| :-------------------------------- | :----------------------------------------------------------------------------------- |
| ✅ **Intelligent Test Selection**  | AI semantically matches PR changes to relevant tests (typically 5-15 tests selected) |
| ✅ **Gap-Only Test Generation**    | Creates 1-3 tests only when coverage gaps exist; most PRs create zero new tests      |
| ✅ **Persistent Test Suite**       | Auto-generated tests become permanent regression tests for future PRs                |
| ✅ **Preview Environment Testing** | Tests against PR preview deployments                                                 |
| ✅ **Approval/Rejection**          | Posts reviews with pass/fail verdicts                                                |
| ✅ **Manual Trigger**              | Comment `@qa.tech` on a PR to trigger, re-run, or steer a review on demand           |
| ❌ **Backend-Only Testing**        | Requires UI access - can't test microservices without frontend                       |

### How a review runs

```
PR opened/updated
  ↓
1. Classify Changes
   → User-facing? Continue
   → Docs/infra only? Skip testing, post info comment
  ↓
2. Assess Coverage
   → Find relevant existing tests
   → Identify gaps in coverage
  ↓
3. Create Tests (if needed)
   → Generate tests for untested functionality
   → Configure dependencies (e.g., login tests)
  ↓
4. Run Tests
   → Execute against PR preview environment
   → Wait for completion
  ↓
5. Post Review
   → ✅ Approve if all tests pass
   → ❌ Decline if tests fail
   → ℹ️ Informational if untestable
```

The agent posts reviews with:

* **Verdict:** Pass/fail/unable to verify
* **What was tested:** Description of coverage
* **Results summary:** Patterns and themes
* **Test details:** Table with individual test results

**Reviews focus on test results only** - no code quality opinions, implementation suggestions, or references to other bot comments.

### Test Selection and Creation

#### How Tests Are Selected

The agent uses AI to semantically match PR changes to test goals - not keyword matching.

**Example: PR changes checkout payment flow**

```
Your project: 645 total tests

Agent analyzes:
├─ "Complete checkout with credit card" → RELEVANT ✓
├─ "Complete checkout with PayPal" → RELEVANT ✓
├─ "Verify payment confirmation email" → RELEVANT ✓
├─ "User profile photo upload" → NOT RELEVANT ✗
└─ "Search products by category" → NOT RELEVANT ✗

Selected: 12 tests covering payment & checkout flows
```

**Selection mechanics:**

* Runs ALL tests it determines are relevant (no arbitrary limits)
* Only considers tests with `status='enabled'`
* More intelligent than running all tests every time

#### When Tests Are Created

Tests are created only when coverage gaps exist, such as when you're developing a new feature not yet covered by your testing suite.

<Tip>
  **Writing acceptance criteria?** Include test requirements in your Linear/Jira
  ticket or PR description. The agent reads this context and uses it to create
  more accurate tests for your new feature. See [Recommended Workflow for New
  Features](/best-practices/creating-tests#recommended-workflow-for-new-features)
  for details.
</Tip>

| PR Type          | Existing Tests Selected | New Tests Created       | Total |
| :--------------- | :---------------------- | :---------------------- | :---- |
| Bug fix in login | 3-7                     | 0 (already covered)     | 3-7   |
| Small feature    | 5-10                    | 1-2 (fill gaps)         | 6-12  |
| Major feature    | 15-25                   | 3-5 (new functionality) | 18-30 |
| Refactor         | 10-20                   | 0 (no new behavior)     | 10-20 |
| Docs/infra only  | 0                       | 0 (untestable via UI)   | 0     |

**Example: PR adds Apple Pay to checkout**

```
Agent assesses existing coverage:
├─ "Complete checkout with credit card" ✓ Exists
├─ "Complete checkout with PayPal" ✓ Exists
└─ Apple Pay integration ✗ Gap identified

Decision: Create 1 new test
→ "Complete checkout with Apple Pay"
```

**Created tests:**

* Stay in your suite labeled 'ephemeral'
* Available for future PRs
* Manage in Settings → Test Cases (filter by 'ephemeral' to find them)

**Example lifecycle:**

```
PR #42: Add Apple Pay
├─ Agent creates "Complete checkout with Apple Pay"
├─ Test runs on PR #42 ✅
└─ Test persists with 'ephemeral' label

PR #58: Refactor checkout UI
├─ Agent finds existing test
├─ Runs it (no new test created) ✅
└─ Your suite now protects against Apple Pay regressions
```

**The agent prevents duplicates** by reading all existing tests first and using semantic deduplication. If one slips through, simply delete it in the UI.

**Self-limiting:** As your test suite grows, fewer tests are created automatically - better coverage means fewer gaps. Most PRs (bug fixes, refactors) create zero new tests.

<Tip>
  **Mobile and Responsive Testing:** When a PR mentions mobile, tablet, or
  responsive design changes, the AI agent may automatically test with
  appropriate device presets. The agent detects keywords like "mobile",
  "tablet", "responsive", or "Safari mobile" and can override device presets
  when creating or running tests. See [Device
  Presets](/test-features/device-presets) for configuring device settings.
</Tip>

### Common questions

**Will generated tests clutter my test suite?**

No. The agent only creates tests for coverage gaps. Most bug fixes and refactors create none, and a large feature usually adds a few focused tests. Better coverage means fewer gaps, so fewer tests are generated over time.

**The agent created tests I don't need. What can I do?**

* Add review context with specific guidelines in the integration settings.
* Update existing tests so they cover the functionality.
* The agent follows the patterns in your existing tests.

**What happens when the organization is out of credits?**

QA.tech posts one comment on the request with an upgrade link. No tests run, and no review is posted.

## Pick your CI

Each guide is only the pull request setup. The same CI names under [Regression Testing](/regression-testing/overview) run a test plan instead.

<CardGroup cols={3}>
  <Card title="GitHub" icon="github" href="/pr-testing/github">
    App, Change Review Action, after merge, or mobile.
  </Card>

  <Card title="GitLab" icon="gitlab" href="/pr-testing/gitlab">
    Merge request reviews on deploy, comment, CI, or API.
  </Card>

  <Card title="Bitrise" icon="mobile" href="/pr-testing/bitrise">
    Review the mobile build Bitrise produced.
  </Card>

  <Card title="Envoyer" icon="php" href="/pr-testing/envoyer">
    Not supported. See what to use instead.
  </Card>

  <Card title="API" icon="code" href="/pr-testing/api">
    Bitbucket, Jenkins, CircleCI, or any HTTP client.
  </Card>

  <Card title="Writing PR descriptions" icon="pen" href="/best-practices/pr-testing">
    Give the review the context it needs.
  </Card>
</CardGroup>

## Give the review enough context

The agent reads the request description, the diff, and linked tickets. A description that states what changed, why, and what to test produces a more relevant review. See [Writing PR descriptions](/best-practices/pr-testing).
