m MiniEHR / learn
Foundry ↗About MiniEHROpen workspace ↗
LESSON 7 OF 95 min read

7. Read tests and practice changes

Tests express behavior that must continue to work. A test passing says something about the executed code and assertions; it does not prove every user interaction or grant engineering approval.

Unit tests

Read PatientTests.cs:

csharp
[Fact]
public void RegistrationNormalizesSyntheticMrn()
{
    var patient = Patient.Register(" syn-001 ", " Synthetic ", " Example ",
        new DateOnly(2000, 1, 1));
    Assert.Equal("SYN-001", patient.MedicalRecordNumber);
    Assert.Equal("Synthetic", patient.GivenName);
    Assert.NotEqual(Guid.Empty, patient.Id);
    Assert.Equal(1, patient.Version);
}

Arrange the inputs, act by registering, assert the observable results. [Fact] is a single test. [Theory] with [InlineData] runs cases for supplied inputs. Assert.Throws<ArgumentException>(...) expects a failure of that type. An assertion failure makes the case fail; it is not an API response.

ClinicalRulesTests.cs covers closure, stale versions, invalid vitals, and note rules. No HTTP server is needed for these domain operations.

Integration tests

FoundationTests.cs defines TestApi using WebApplicationFactory<Program>. It runs the real application's pipeline in a test host and overrides the connection string. Tests send HTTP requests through a client and inspect real SQLite state. This is not a mock of the entire service/store system, and it need not listen on port 5080.

Named shared in-memory SQLite databases require an open connection to retain their contents. Other tests use temporary files to verify behavior across restarts. Cleanup disposes connections and removes the synthetic files.

Read these next:

Latest observed result

Candidate 0d4d28b584c5316af614aaa11ad12760a8e74254, tree 01e0d88ee52e4fa235a782ec96f2011e8395890b:

Test projectPassedFailedSkipped
UnitTests1500
IntegrationTests4000
readiness/Checks301
Total5801

The readiness skip is intentional; no application test is skipped. The dotnet runner exited 0. Foundry exited 1 because its discovery/result identity check found 23 unmatched identities. Never summarize this as a Foundry full-evidence pass. The command and engineering interpretation are in lesson 8.

Exercises with answers

These begin as reading exercises. Implementation requires an assigned ownership scope, an attributable session, and Foundry-supervised validation. Do not make domain changes under a frontend-only ownership declaration.

Exercise 1: Predict normalization

What does registering " syn-learn-002 " store as MRN? Find the exact call.

Answer: SYN-LEARN-002; Required trims it and ToUpperInvariant uppercases it.

Exercise 2: Predict a failed correction

A patient is version 2. A request submits version 1 with valid new names. What happens, and does the record change?

Answer: the domain throws StalePatientVersionException, the service translates it to a conflict, the API returns 409, and this request does not save a correction.

Exercise 3: Write a focused domain test

In an appropriately assigned tests workstream, add a case proving whitespace-only notes are rejected without changing an existing note's text/version. Follow the existing Assert.Throws pattern. Validate the outcome, not the internal sequence of helper calls. Check existing cases first to avoid a duplicate test.

Expected reasoning: validation occurs before assignment/version increment in ClinicalNote.Correct, so both original values remain after rejection.

Exercise 4: Trace full replacement

A vital contains blood pressure and heart rate. PUT sends only heart rate plus valid versions. What is stored?

Answer: heart rate remains and both blood-pressure fields become null. This PUT replaces measurements; it is not a partial patch. Sending only one blood-pressure value instead fails validation.

Exercise 5: Explain a closure race

One request adds a note while another closes the same open version. Find the conditional parent update and the transaction. Why can't the losing write leave a persisted note behind?

Answer: content and parent-version update are in one transaction; failure rolls back the content. Race integration tests check persisted state, not just status.

Exercise 6: Plan a small frontend improvement

Choose one helpful label or empty-state message. Identify the rendering function, check synthetic/closed behavior and narrow layouts, and declare the touched paths. For a simple wording change, manual/source checks may suffice. For changed write behavior, test rejected writes and post-save refresh failures as well.

Safe investigation sequence

Read Foundry status/recover and task/workstream ownership first. Form a specific hypothesis, inspect the failed assertion and exact candidate, change the smallest relevant code, and validate through Foundry. Record actual failure, repair, exit codes, and candidate identities. A role change by the same author does not create an independent review.

Next: Foundry workflow.

MiniEHR learning guide · Based on this project’s source · Read on GitHub