A C# browser quality-engineering framework built on .NET LTS, xUnit, and Selenium WebDriver. Runtime selection, dependency resolution, deterministic application ownership, driver/session lifecycle, synchronization, browser contexts, evidence, and teardown each have an explicit owner while native WebDriver behavior remains visible.
Important
Required browser CI is independent of public demonstration sites. The default application is a repository-owned C# loopback fixture; deployed applications and Selenium Grid are explicit execution choices rather than hidden dependencies.
Start here: capabilities · architecture · quick-start · repository-map · documentation
| Plane | Purpose | Primary evidence |
|---|---|---|
| Framework contract | Configuration, lifecycle, waits, artifact safety | xUnit + coverage |
| Primary browser | Authentication/navigation/context behavior | Chrome + TRX/Cobertura/browser evidence |
| Native browser primitives | JavaScript, cookies, frames, alerts, child-window lifecycle | WebDriver/xUnit assertions |
| Extended browser | Engine compatibility | Chrome + Firefox |
| Remote execution | Driver-location portability | Optional Selenium Grid |
| Dependency integrity | Exact NuGet graph + advisory policy | Locked restore/build |
| Security | C# SAST, repository/dependency/configuration/secret, dependency-diff risk | CodeQL, NuGet Audit, Trivy, Dependency Review |
| Documentation | README/workflow/governance consistency | Documentation contract status |
flowchart LR
CHANGE[Repository change] --> SDK[Repository-selected .NET SDK]
SDK --> LOCK[Locked NuGet graph]
LOCK --> TEST[xUnit tests]
TEST --> SESSION[BrowserTestSession]
SESSION --> CFG[TestSettings]
SESSION --> DRIVER[WebDriverFactory]
TEST --> PAGE[Page objects + native context APIs]
PAGE --> WAIT[BrowserWait]
DRIVER --> BROWSER[Chrome · Firefox · Edge · Grid]
BROWSER --> FIX[LocalUiServer]
SESSION --> ART[Minimal failure evidence]
ART --> GATES[CI gates]
GATES --> RESULT[Qualified repository change]
classDef entry fill:#DDF4FF,stroke:#0969DA,color:#24292F,stroke-width:1.5px;
classDef policy fill:#FBEFFF,stroke:#8250DF,color:#24292F,stroke-width:1.5px;
classDef runtime fill:#FFF8C5,stroke:#9A6700,color:#24292F,stroke-width:1.5px;
classDef evidence fill:#DAFBE1,stroke:#1A7F37,color:#24292F,stroke-width:1.5px;
class CHANGE,SDK,LOCK,TEST entry;
class CFG,DRIVER,WAIT policy;
class SESSION,PAGE,BROWSER,FIX runtime;
class ART,GATES,RESULT evidence;
linkStyle default stroke:#57606A,stroke-width:1.4px;
xUnit owns test/fixture lifetime, Selenium owns browser semantics, framework services own configuration/driver/wait/evidence policy, and the local application remains repository-owned. See docs/ARCHITECTURE.md for deeper ownership boundaries.
Prerequisites are the SDK selected by global.json and a supported local browser. Selenium Manager resolves compatible local driver binaries.
dotnet restore UiTests.csproj --locked-mode
dotnet build UiTests.csproj --configuration Release --no-restore
dotnet test UiTests.csproj --configuration Release --no-buildCompatibility/integration examples:
TEST_BROWSER=firefox dotnet test UiTests.csproj
TEST_BASE_URL=https://test.example.internal TEST_BROWSER=chrome dotnet test UiTests.csproj
TEST_BROWSER=chrome SELENIUM_GRID_URL=http://localhost:4444/wd/hub dotnet test UiTests.csprojFor runtime variables, browser lifecycle, native context primitives, synchronization, Grid policy, evidence, security, dependencies, and triage, see docs/OPERATIONS.md.
.
├── .github/
├── docs/
├── Framework/
├── PageObjects/
└── Tests/
- Pinned toolchain:
global.jsonselects the repository SDK and required automation restorespackages.lock.jsonin--locked-mode. - Fail-closed advisories: HIGH/CRITICAL NuGet advisories are build-breaking; warnings/analyzer findings are errors.
- Deterministic target: required browser gates use the repository-owned
http://127.0.0.1:3200fixture. - Single driver boundary: tests do not construct WebDrivers directly;
WebDriverFactoryowns local/Grid construction policy. - One session owner: one xUnit test instance owns one WebDriver and deterministic teardown.
- Observable synchronization: implicit wait remains zero; explicit waits describe browser/application state rather than elapsed time.
- Explicit context ownership: frames, alerts, cookies, JavaScript, and child windows use native WebDriver semantics with restoration/cleanup where context changes.
- Minimal evidence: automatic capture is sanitized URL + screenshot; page source is explicit opt-in because it can contain hidden sensitive data.
- Separate Grid/integration: browser transport location and deployed application state remain independent failure domains.
| Gate | Responsibility |
|---|---|
ci.yml |
Exact SDK, locked/audited restore, build, deterministic Chrome, TRX/Cobertura/browser evidence |
extended.yml |
Chrome/Firefox compatibility under the same dependency/build contract |
security.yml |
CodeQL, locked NuGet audit, Trivy, Dependency Review when available |
docs.yml |
README links, badges, Mermaid, repository-map, documentation governance |
The workflows expose stable aggregate jobs ci-gate, extended-gate, and security-gate; repository rules/settings are a separate governance layer.
| Guide | Use it for |
|---|---|
docs/ARCHITECTURE.md |
Runtime/dependency, fixture, driver, session, synchronization, evidence, security boundaries |
docs/TEST_STRATEGY.md |
Deterministic targets, browser matrix, negative testing, security gates, exit criteria |
docs/OPERATIONS.md |
Commands, runtime config, browser lifecycle diagram, context APIs, waits, Grid, evidence, supply chain, triage |
CONTRIBUTING.md |
Change-quality expectations |
The deeper browser-lifecycle flow and operating detail live in /docs; the main README intentionally retains only the architecture diagram above.
Prefer the lowest-cost boundary that contributes the semantics under test. A strong Selenium framework makes the failing boundary obvious: toolchain, dependency graph, security policy, configuration, fixture lifecycle, browser construction, browser-context ownership, synchronization, application behavior, evidence, Grid transport, or deployed environment.