# Add Missing Tests to Every Pull Request in a Symfony App

An agent reads a Symfony API pull request, adds PHPUnit tests for uncovered behavior, and returns test commits with the exact checks run.

[Run this on Rush](https://cloud.getrush.ai/run/test-every-pull-request/symfony/), in a Project that has your repository.

## What the agent does

The agent compares the pull request's entry API changes with the tests already protecting them. In wallabag/wallabag, the implementation is src/Controller/Api/EntryRestController.php and the functional suite includes tests/functional/Controller/Api/EntryRestControllerTest.php. Existing cases already cover fetching an entry, metadata-only detail and an invalid detail parameter. The agent looks for a missing behavior from the diff rather than claiming the whole entry API lacks tests.

It reads the existing authorized client and Doctrine fixture conventions before adding a case. The entry controller handles URL and hashed-URL lookup, and its existence endpoint queries by the current user's ID. Tests that touch those changes should verify the relevant response and ownership boundary through real application requests. Where a new case needs an entry, the agent creates or loads deterministic test data; an example that skips because no entry exists cannot prove the new branch is protected.

The test command comes from the repository, not a generic Symfony tutorial. composer.json requires PHP >=8.2 and PHPUnit ^9.6.22, sets bin-dir to bin, and keeps Symfony dependencies on the 5.4 series. CI invokes php bin/phpunit, not vendor/bin/phpunit. phpunit.xml.dist separates unit, integration and functional suites, uses tests/bootstrap.php and enables the Doctrine test extension. The agent preserves the existing deprecation policy and chooses the database setup from .github/workflows/continuous-integration.yml.

After writing focused functional assertions, it runs php bin/phpunit --testsuite functional --filter EntryRestControllerTest, then the wider PHPUnit suite. CI also builds assets with yarn build:dev and supports SQLite, MySQL and PostgreSQL, so the report identifies which database and supporting services the sandbox actually exercises. The agent changes tests and necessary test support only. If the API implementation fails a new expectation, it leaves the failure visible instead of altering application code under a test-writing assignment.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "codex",
  "input": "This pull request changes the entry API. Compare the diff with the existing PHPUnit functional tests and add coverage only for new or changed behavior that lacks assertions. Exercise the real Symfony request and Doctrine database paths with deterministic fixtures, including relevant ownership and validation cases. Read composer.json and CI to use the actual PHPUnit binary path; where bin-dir is bin, run php bin/phpunit. Run the affected functional tests and then the wider suite, recording the database and supporting services used. Do not change application code or weaken checks. Push verified test additions to this PR's authorized branch and comment with the behaviors covered and exact command results; report any defect or blocked check.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

The original pull request receives a focused test diff, normally in EntryRestControllerTest.php and any required test fixtures. The summary maps each added assertion to the changed entry behavior and lists the actual PHPUnit commands. It distinguishes focused functional coverage from a complete suite and identifies the selected database. Missing services, skipped cases and pre-existing failures remain part of the result rather than disappearing behind a passing exit code from a smaller command.

Reviewers inspect the credentials and entry ownership in each setup, confirm that the test reaches the changed controller branch, and check that a regression would fail an assertion. They look for hidden skips or unrelated fixture churn. The transcript supplies the command output behind the summary; repository CI remains responsible for verifying the final branch across its configured PHP and database combinations.

## Run it on every Symfony API pull request

Have your GitHub webhook receiver call POST https://api.prix.dev/o/{org}/sessions for eligible opened PRs. Replace the sample repository resource with the accessible open PR URL and include the entry API change's intended behavior in input. Install the Rush GitHub App first, and let your receiver authorize which branches the agent may update. Keep webhook dispatch rules on your server rather than adding unsupported event fields to the session body.

## Why run it on Rush?

PHPUnit functional tests can require extensions, generated assets, fixture records and database services before a controller request reaches application code. Rush gives this preparation a separate sandbox instead of modifying a developer's PHP installation or local reading-list database. The agent can investigate the changed entry path without borrowing the author's active checkout.

The work also arrives with a record that distinguishes test coverage from environment setup. A reviewer can read why php bin/phpunit was selected, which database was used and whether the functional case actually ran. Separate PRs can have separate sessions, avoiding shared fixtures or cached application state between unrelated test-writing tasks.

## Frequently asked questions

### Why does the example use php bin/phpunit?

Wallabag's composer.json configures Composer's binary directory as bin, and its CI runs php bin/phpunit. A generic vendor/bin/phpunit command would not match that setup. The agent reads your repository's configuration and uses its installed binary rather than assuming all Symfony projects agree.

### Does it add tests even when the API already has a suite?

Yes, but only for a gap introduced or exposed by the PR. The inspected entry suite already has success, metadata and invalid-parameter cases. The agent must identify the uncovered changed behavior instead of duplicating those examples to increase the test count.

### Will it test every supported database?

The report names the database combinations actually run. The inspected CI supports SQLite, MySQL and PostgreSQL, but a local sandbox run against one does not prove the others. Ask for a broader matrix explicitly if that is required for the change.

### What if a new test reveals that the entry API is wrong?

The agent reports the failing behavior and command without changing production code. It should not mark a case skipped or relax an assertion to satisfy the current implementation. The PR author can then correct the implementation or clarify the expected contract.
