jocyscom/focuslogger/qa-tester
Claude Code and agent skill by jocyscom/focuslogger
- community
Checking that the SKILL.md file is still in the repository.
Create and maintain automated tests in Microsoft-native/.NET projects with a minimal stack — MSTest runner, `System.Windows.Automation` for Windows desktop, Playwright for real browser smoke. Code-first, single-source-of-truth. Use whenever the user wants to write, review, structure, migrate, or plan tests for any .NET project (unit, API, database, WPF, WinUI, MAUI, Blazor, Razor) — even when the request says "test" without naming a framework.
Install
npx vskill@latest install jocyscom/focuslogger/qa-testerSKILL.md
QA Tester
Core philosophy: one test runner, minimum tools, executable code is the spec.The fewer different tools a codebase has, the lower the cognitive load on every engineer and AI that touches it. Prefer in-box Microsoft APIs; every extra dependency is a cost, not a feature.
1. First principles
Each principle has a why so you can judge edge cases instead of pattern-matching on the rule.
- Minimum tool surface. Two tools that do the job beat five that do it elegantly. Why: every extra framework is cognitive debt owed by the next person who opens the repo.
- In-box first. Prefer APIs that ship with .NET or Windows. Why: a test that runs with
dotnet teston a clean checkout is the test that actually gets run. - Code-first. A test is the spec. Do not duplicate intent into Gherkin + bindings + helpers. Why: every layer of indirection is another place the next AI has to look.
- Readable beats clever. A new engineer should understand a test in under 30 seconds.
- Lightest abstraction that still reads well. Inline → helper → screen object → fixture. Why: page objects are a symptom of test duplication, not a solution.
- Stable selectors. Roles, accessible names,
AutomationId. Never CSS tied to layout internals. Why: a fragile selector is a test that will break for reasons unrelated to what it's checking. If a stable selector doesn't exist, fix the product first. - Deterministic waits. Use framework auto-waits or in-box event subscriptions. Why:
Thread.Sleephides real race conditions and taxes everyone else's suite time. - Test the lowest layer that gives confidence. Unit → API/integration → UI. Why: UI tests are slow, flaky, and tell you less than the integration test that already covers the same rule.
- Isolation. No shared mutable state. Each test sets up and tears down its own world. Why: ordered tests and shared fixtures produce heisenbugs whose failure mode depends on run order — impossible to reproduce locally and demoralising for everyone on call.
- Minimal change. Edit small. Don't rewrite suites unless asked. Why: a "while I'm in here" refactor turns a 5-line fix into a 500-line review and blocks the actual bug shipping.
- Test project must be simpler than the app. One
{Project}.Testsproject by default. Mirror the product folder layout 1:1. Split into more projects only when a real constraint (headless CI, massive scale, different TFM) forces it. Why: a test project fractured into more pieces than the app it tests is absurd — every extra csproj duplicates infrastructure, slows the loop, and makes newcomers wonder which project to open. - Performance data is a byproduct of functional tests. If a code path already runs in CI under a unit / integration / UI test, attaching a lightweight in-box collector gives you perf coverage equal to your functional coverage at near-zero marginal cost. Why: a parallel "perf suite" that re-implements the same sign-in / order / search scenarios is pure duplication, and it creates coverage gaps wherever the two suites drift. Dedicated load/stress/soak tests exist only for what functional tests genuinely cannot express: concurrency, saturation, sustained throughput, and memory growth over time. See §6a.
2. The two-tool stack
| Tool | Ships from | Used for | |
|---|---|---|---|
MSTest (Microsoft.NET.Test.Sdk + MSTest.TestFramework + MSTest.TestAdapter) | NuGet / Microsoft | Everything .NET: unit, service, DB integration, API integration, Windows desktop UI via `System.Windows.Automation`, view-model tests for WPF/WinUI/MAUI-desktop. | |
Playwright (Microsoft.Playwright + Microsoft.Playwright.MSTest) | NuGet / Microsoft | Real-browser web UI smoke. Runs under the same MSTest runner as everything else — one test explorer, one dotnet test command. |
That's the whole stack. `System.Windows.Automation` is in-box (no NuGet), so it doesn't appear in the package list but is the default for any Windows desktop test.
Performance collection (§6a) uses only in-box instrumentation — EventPipe / dotnet-trace, dotnet-gcdump, dotnet-counters, SQL Server Extended Events, Playwright tracing, ETW via wpr.exe — plus one Microsoft-owned load generator (Microsoft.Crank). Collectors are runtime/OS facilities, not "tools", so the two-tool rule is unchanged.
Quick exclusion list (see `references/legacy-bdd.md` for inherited-project support):
| Excluded | Why | |
|---|---|---|
| Appium / WinAppDriver | Driver process, HTTP wire protocol, installer step. System.Windows.Automation does the same job in-box. Exception: MAUI mobile (Android/iOS) — keep it in a dedicated Tests/UI.Mobile/ project. | |
| FlaUI | Thin wrapper around System.Windows.Automation. Use the in-box API directly. | |
| Selenium | Playwright replaces it. | |
| Cypress / TestCafe / WebDriverIO | Playwright replaces all of them. | |
| NUnit / xUnit | One runner per repo — MSTest for Microsoft-aligned codebases. | |
| SpecFlow / Reqnroll | Inherited-project support only. See `references/legacy-bdd.md`. | |
| Testcontainers for SQL Server | Use SqlLocalDB — no Docker dependency. | |
| bunit | Use WebApplicationFactory<T> + HTTP first. |
Before adding any third tool, write one sentence justifying it. If the sentence is "it would be more convenient", reject it.
3. Layer → test type (the whole decision matrix)
| You want to test … | Use | Perf dimension it already measures (piggyback, §6a) | |
|---|---|---|---|
| A pure business rule | MSTest unit test — direct instantiation, no framework | Method CPU, allocations, hot-path micro-regressions | |
| A rule that needs HTTP / auth / DI / EF | MSTest + `WebApplicationFactory<T>` — in-process HTTP against the real middleware pipeline | End-to-end latency, middleware cost, per-request allocations, SQL count + text + shape (N+1 detector) | |
| Real SQL Server behaviour (constraints, triggers, migrations) | MSTest + `SqlLocalDB` — sqllocaldb create + a connection string, no Docker | Query duration, logical reads, CPU time, actual plan, missing-index hints | |
| A Razor / MVC page that renders mostly server-side | MSTest + `WebApplicationFactory<T>` + `HttpClient` — HTTP test, not a browser test | Same as integration-api | |
| Genuine browser behaviour a server-side test can't express | MSTest + Playwright — keep the suite small, one or two happy-path tests per area | Navigation + resource timings, LCP/CLS/INP, long tasks, JS heap, network waterfall | |
| A WPF / WinUI view-model rule | MSTest — instantiate the VM directly. Under MVVM this is 90% of desktop test coverage. | VM method CPU + allocations | |
| A WPF / WinUI launch / binding / wiring check | MSTest + `System.Windows.Automation` — Process.Start(exe) + AutomationElement.FromHandle + InvokePattern / ValuePattern | Startup time, frame time, UI-thread stalls, managed allocs during interaction | |
| A MAUI view-model rule | MSTest — direct VM instantiation | VM CPU + allocations | |
| MAUI on the Windows target | MSTest + `System.Windows.Automation` — MAUI/Windows is a UIA tree | Same as WPF | |
| MAUI on Android / iOS | Appium, isolated in Tests/UI.Mobile/ — the single intentional exception | — (mobile perf is its own discipline) | |
| Concurrency, throughput ceiling, saturation, soak, memory growth under load | MSTest + `Microsoft.Crank` scenario in {Project}.Tests.Perf/ — the only place dedicated load/stress/soak lives. See §6a. | Thread-pool starvation, GC pressure under load, leak detection via bracketed gcdump |
Default rule of thumb: MSTest + System.Windows.Automation covers every .NET desktop scenario; MSTest + Playwright covers every web scenario. If you reach for a third tool, re-read §2.
4. Writing style — code-first, business-readable second
When the user says:
Given a valid user, when they sign in, then they should see the dashboard
Write this:
The Given/When/Then phrasing lives in test name + comments + `[TestCategory]` tags + `[Description]`. No .feature file, no bindings, no regex maintenance, no indirection. A reporter that lifts [Description] + [TestCategory] into Markdown covers every "but stakeholders need to read it" objection without introducing BDD tooling.
5. Discoverability — finding tests from a code path (and vice versa)
For Code ↔ UI mapping (web routes, desktop menu breadcrumbs), see the `solution-patterns` skill. This section covers Code ↔ Test only.
This section is load-bearing. Renaming any convention here breaks every future locate-or-create query.
5.1 Test project naming
Default: one test project per product project — {Project}.Tests, sibling to {Project}. Why: a test project more complex than the app it tests is absurd; the whole point of §1.1 (minimum tool surface) applies to the test tree too. One csproj, one namespace root, one dotnet test command.
Split into multiple projects only when one of these is actually true:
- Headless CI constraint. UI tests need a graphical session; unit and integration tests must pass on a headless build server. Split into
{Project}.Tests(headless-safe) and{Project}.Tests.UI(requires a desktop session). Tag the UI csproj so CI can skip it in headless runs, e.g.<IsTestProject>true</IsTestProject>plus a[TestCategory("ui-interactive")]filter. - Large codebase. Hundreds of product files and thousands of tests where a single csproj's compile + test-discovery time noticeably slows the loop. This is rare in practice.
- Fundamentally different runtime. e.g. product targets
net8.0but one test layer needsnet48for COM interop. - Dedicated perf/load/soak suite.
{Project}.Tests.Perf/housesMicrosoft.Crankscenarios and long-running soak tests. Its runtime constraints are genuinely different: long durations, non-parallel with the functional suite, its own CI job, statistical gating instead of pass/fail per run. See §6a.5. Do not put piggyback perf collectors here — those belong next to the functional tests whose coverage they inherit.
Do not split because "separation of concerns" or "unit vs integration is cleaner" — those are solved by folder structure and [TestCategory] tags, not by csproj boundaries. Extra csprojs bring: duplicated [AssemblyInitialize] code, duplicated TestSandbox/TestHelpers, multiple InternalsVisibleTo grants, separate Directory.Packages.props entries, and separate test hosts that all have to be kept in sync. Pay that cost only when a real constraint forces it.
Naming, whichever variant you pick: {Project}.Tests or {Project}.Tests.UI. One spelling forever. Never {Project}Tests, never Test.{Project}, never {Project}.UnitTests.
5.2 File-to-file mapping (deterministic)
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.ai/skills/qa-tester/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/jocyscom/focuslogger/qa-tester)