All jobs

Write Unit Tests for an ASP.NET Core Project

Yes. An agent runs coverage on an ASP.NET Core API, adds xUnit tests for the thinnest logic files, and opens a pull request with the delta.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads the .NET layout before it writes tests. In realworld-apps/aspnetcore-realworld-example-app it finds global.json pinning SDK 10.0.402 with rollForward: latestFeature, the web project at src/Conduit/Conduit.csproj (EF Core Sqlite/SqlServer, JWT Bearer, FluentValidation, Mediator source generator, Mapperly, Swashbuckle), and tests at tests/Conduit.IntegrationTests/ with xUnit 2.9.3, Microsoft.AspNetCore.Mvc.Testing and Microsoft.NET.Test.Sdk. Feature slices live under src/Conduit/Features/ (Articles, Comments, Users, Profiles, Tags, Favorites, Followers) as Mediator handlers such as Articles/Create.cs and Users/Login.cs.

Existing coverage is integration-heavy: CreateTests, EditTests, DeleteTests, LoginTests, PasswordHashingTests and friends go through SliceFixture and ApiFactory rather than pure unit tests beside each handler. The agent runs the suite with coverage (dotnet test with a coverlet or DataCollector argument the project already accepts, or adds the smallest coverlet package reference on the test project when none exists) and ranks src/Conduit files by line coverage, focusing on handlers and helpers that hold branching logic (ArticleExtensions, ProfileReader, follower and favorite commands) rather than controller shells or envelope DTOs.

For the five weakest logic files it adds xUnit tests that exercise behaviour: duplicate tag collapsing in Create.Handler, authorization failures on edit/delete for the wrong user, profile mapping when the current user is null, validator failures from FluentValidation rules. New tests may live under a new tests/Conduit.UnitTests/ project mirroring the feature folders, or beside integration tests when that matches the repo; they construct handlers with in-memory DbContext and StubCurrentUserAccessor the way CreateTests already does, instead of asserting on private fields.

It re-runs dotnet test with coverage, puts before/after percentages in the pull request description, and changes production code only when a test exposes a real bug (called out explicitly). SDK version stays on the global.json pin. Build scripts such as build.sh / Makefile targets are left alone unless the only documented way to run tests with coverage is through them, in which case the pull request quotes that command.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Run the test suite with coverage, pick the five least-covered files that hold real logic, and write xUnit tests for them that exercise behaviour, not implementation details. Do not change production code unless a test reveals a bug; if it does, say so in the description. Open a pull request with the coverage before and after.",
  "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

What comes back is a pull request on a new branch. In a Conduit-shaped repo it adds xUnit test classes (and a unit test project if one was missing), keeps src/Conduit unchanged absent a documented bugfix, and may add a coverlet package reference on the test project so coverage can be collected in CI the same way.

The description reports coverage before and after, names the five files chosen, and links each to the new tests. The trajectory keeps dotnet test output and the coverage summary.

Before merging, a reviewer checks that tests hit behaviour (status codes, persisted tags, auth failures) rather than Mediator internals, that the SDK matches global.json, and that any production diff is a real bugfix. Once merged, dotnet test in CI runs the new cases.

Run it on every coverage drop on main

Schedule a weekly run or trigger from your coverage reporter when src/Conduit coverage falls past a threshold. Your server sends this request with the repository in resources so the agent opens a pull request that restores the thin files.

Use the API key webhook for completion events and stay within max_concurrent when sweeping several .NET services.

The use case this job follows, with its automation and trigger: Write the missing tests.

Why run it on Rush?

Collecting .NET coverage and iterating on handler tests needs the SDK pin, restore, and a quiet machine. On Rush the agent restores against global.json, runs dotnet test with coverage in its sandbox, and only surfaces a pull request when the new tests pass and the delta is written down.

The proof is the coverage summary and the xUnit output in the trajectory, not a claim that "tests were added". Several APIs can be hardened in parallel, each with a reviewable pull request.

Frequently asked questions

Unit tests or more integration tests?

The job targets unit-level behaviour around handlers and helpers. It reuses in-memory EF and stubs from SliceFixture when that is the project's pattern, but it does not replace the existing Conduit.IntegrationTests suite.

Which .NET SDK does it use?

The one in global.json (currently 10.0.402 with rollForward: latestFeature). It does not invent a different major.

Will it modify Mediator handlers to make them testable?

Only if a test exposes a bug, and then the pull request says so. Otherwise production code stays put; handlers are already constructable with a DbContext and ICurrentUserAccessor.

xUnit, NUnit or MSTest?

Whatever the test project already references. This RealWorld port uses xUnit, so new tests use [Fact] and Assert from xUnit.