All guides

Testing & native harnesses

Choose unit tests and integration checks, and understand their side effects.

4 min read · Maintained with the appSource guide · Improve this page

Test the change you made#

Start with the smallest suite or harness that covers the behavior. Add a regression test for a bug fix, then expand coverage if the change crosses project boundaries.

Unit tests#

Run these from the repository root. The --project syntax is intentional for Microsoft Testing Platform:

dotnet test --project tests\Hotshot.Core.Tests\Hotshot.Core.Tests.csproj
dotnet test --project tests\Hotshot.Capture.Tests\Hotshot.Capture.Tests.csproj
dotnet test --project tests\Hotshot.Editor.Tests\Hotshot.Editor.Tests.csproj
dotnet test --project tests\Hotshot.Gif.Tests\Hotshot.Gif.Tests.csproj

Core covers portable logic such as settings merging, naming, and library persistence. Capture, Editor, and GIF suites cover their corresponding image/document/media behavior.

Targeted integration harnesses#

Use an interactive Windows desktop for native capture/UI checks.

Area Command Important side effects
Library persistence/search benchmark dotnet run --project tests\Hotshot.Library.Harness\Hotshot.Library.Harness.csproj -c Release Generated data, not the user's library.
Native agent bridge and settings reload dotnet run --project tests\Hotshot.Agents.Harness\Hotshot.Agents.Harness.csproj -c Release -p:Platform=x64 Isolated profile, generated images, and its own synthetic window/region. No provider upload.
Recording pipeline dotnet run --project tests\Hotshot.Recording.Harness\Hotshot.Recording.Harness.csproj -- --window-only Records synthetic windows with all audio off and changes the clipboard to a generated capture.
Unobscured window capture dotnet run --project tests\Hotshot.Recording.Harness\Hotshot.Recording.Harness.csproj -- --window-screenshot Synthetic targets, occlusion, protection, and target-state checks.
Two-minute recording soak dotnet run --project tests\Hotshot.Recording.Harness\Hotshot.Recording.Harness.csproj -- --soak-seconds 120 Synthetic window; audio disabled; checks timeline, resizing, and memory growth.
PNG description metadata dotnet run --project tests\Hotshot.Descriptions.Harness\Hotshot.Descriptions.Harness.csproj Generated image; no model request by default.
OCR, redaction, and styled export dotnet run --project tests\Hotshot.Workbench.Harness\Hotshot.Workbench.Harness.csproj -p:Platform=x64 -- --ocr Generated text/images; requires Windows OCR support.
Update source dotnet run --project tests\Hotshot.Updates.Harness\Hotshot.Updates.Harness.csproj Makes network requests to the real release source; does not install or apply updates.

The recording harness without --window-only can also capture the monitor and exercise microphone input. Run that only when the desktop and audio are safe to capture. Its ordinary media output goes under %TEMP%\hotshot-harness.

Adding -- --copilot to the description harness submits only its generated test image to the production provider, requires Copilot sign-in, and consumes quota. Do not use that flag as a routine offline test.

For MCP companion build/publish commands, manifest checks, and the official client protocol harness, see agents/README.md. Native permission changes need bridge coverage as well as protocol/manifest coverage.

Native UI smoke checks#

Exit Hotshot first. Use an unmanaged Debug/build output, not an installed auto-updating release. The smoke script temporarily replaces/restores the real settings/history profile and forces local-only settings for its fixture. It is not a reason to skip a backup when changing data migrations.

For example, after the default x64 Debug build:

pwsh tests\Hotshot.App.Smoke.ps1 -Exe src\Hotshot.App\bin\x64\Debug\net10.0-windows10.0.26100.0\win-x64\Hotshot.exe -SettingsControlsOnly

If you changed the build configuration, architecture, or artifacts path, use the actual Hotshot.exe path printed by your build instead.

Selector Coverage
-SettingsControlsOnly Folder selection/cancel, token examples, and automatic persistence; no capture or clipboard changes.
-HeaderSearchOnly Embedded title-bar search, compact layouts, theme changes, and search navigation.
-HistoryNavigationOnly Filename browsing and automatic editor loading using generated PNGs.
-SettingsCaptureOnly Selection/capture of the actual Settings window; changes the clipboard.
-WorkbenchOnly Generated-image zoom, pinning, selection, comparison, and keyboard controls.
-AgentSettingsOnly Native agent configuration, consent, and optional review-mode persistence without an AI request.

With no selector, the smoke captures the real desktop locally and changes the clipboard; use a safe desktop. -VerifyStartup additionally tests/restores the startup registry entry and requires a Release build. -VideoFixture supplies an MP4 for video preview/frame-extraction coverage.

A synthetic test or cross-build is not a substitute for physical mixed-scale monitors, HDR display fidelity, Narrator usability, or real ARM64 execution. State what you actually tested and any remaining hardware gaps.

For an anonymous available-device report, use tests\Hotshot.Device.Validation.ps1 with the actual Recording/Product harness executables. -UiOnly checks the real native UI/accessibility, shared HDR/scRGB references and read-only display readiness without recording or clipboard changes; -RequireMixedDpi requires actual different-scale displays rather than implying acceptance from simulated tests. The Product harness creates a GUID-isolated profile and generated library; its separate media mode records only its own workspace without audio. Publication-only windows may exceed a portrait monitor's maximum track size and use a neutral background instead of private wallpaper. Production capture exclusions and real user data are unchanged. Native ARM64 CI and automated focus/peer tests are distinct from human Narrator and physical display acceptance. See compatibility and device validation.

Find your next step.

Search guides, settings, tools, and troubleshooting.

Ctrl/Cmd + K to search · Arrow keys to explore · Enter to open · Escape to close