Video and screenshots
With video on, an attempt on the web engine writes video/video.webm under .e2e/results/<result>/attempt-<n>/. A screencast belongs to one page, so each later page the attempt opens (after App.RestartAsync, App.ClearStateAsync, or a reconnect) adds a segment, video/video-part<n>.webm, and each segment has the instant it began, StartedAt. retain-on-failure records every attempt and deletes the video of one that passed. A browser provider that records (Kernel’s replay.mp4) records in place of the screencast, and writes its own file, or gives a link and no local file. The video.webm files are the screencast’s. MobileEngine on a local simulator or emulator records the whole device screen to video/video.mp4 with agent-device, with the taps shown unless MobileOptions.VideoTouches is false; a hosted device provider’s own recording is not used yet. new WebEngineOptions { Screencast = new WebScreencastOptions { Size = new WebViewport(960, 540), Quality = 70 } } sets the frame size and the JPEG quality of the screencast; the size defaults to the page’s viewport. A mode set on the target or on a test is required: an engine that cannot record it (DocumentEngine, the MAUI DevFlow engine) fails the session start with UNSUPPORTED_ARTIFACT. A mode from the config root or E2E_VIDEO skips such an engine. The retry modes (on-first-retry, on-all-retries) need NUnit [Retry]; xUnit v3 has no retry, so they record nothing there. A video masks nothing and keeps what the screen showed, secrets included.
Visual comparison
Section titled “Visual comparison”ToHaveScreenshotAsync compares what the app shows against a PNG stored next to the test file. It works on the web engine and on MobileEngine over agent-device. DocumentEngine fails with UNSUPPORTED_CAPABILITY.
await Expect.That(Screen).ToHaveScreenshotAsync("checkout.png");await Expect.That(Screen.GetByRole("button", "Pay")).ToHaveScreenshotAsync("pay-button.png");await Expect.That(Screen).ToHaveScreenshotAsync("feed.png", new ScreenshotOptions{ Mask = [Screen.GetByTestId("timestamp")], MaxDiffPixels = 50,});Expect.That(Screen) compares the whole viewport. Expect.That(locator) compares the box of its one match, scrolled into view first. Without a name the screenshot is named after the test, my-test-title-1.
- Stored at
<test file>-snapshots/<name>-<target>-<os>.png, for exampleCheckoutTests.cs-snapshots/checkout-web-linux.png. The test file is the file the call is written in. The OS isdarwin,linux, orwin32. Commit the files. - Missing. The first run writes the screenshot and fails. Look at it, commit it, and run again. In CI (
CIset) nothing is written into the project: the screenshot is attached under.e2e/results/atsnapshots/<path in the project>, so it can be downloaded and committed. - Update.
E2E_UPDATE_SNAPSHOTS=1 dotnet testwrites each missing or different screenshot and passes. A fixture can also overrideUpdateSnapshots. Screenshots are per OS, so write CI’s from a CI job. - Different. The matcher captures again until one matches or the assertion timeout passes, then fails with the number of differing pixels and three images under
.e2e/results/<result>/attempt-<n>/screenshots/:-diff,-actual, and-expected. - Options.
Threshold(0 to 1, default 0.2),MaxDiffPixels,MaxDiffPixelRatio(the smaller wins when both are set),Mask,MaskColor(#rrggbb, default#ff00ff), andTimeout..Notpasses once the screen differs from a stored screenshot. - Secrets. Secure fields are covered in every screenshot. After a test fills a
Secret, the matcher still compares. It masks secure fields only, so a secret the app shows anywhere else is in the image.