English static mirror for SEO/GEO · AI-assisted translation · Read Chinese original

Test-Driven Development (TDD) and Unit Testing for Uno Platform

Forum topic · ✨步子哥 · 2026-02-17

Summary

Chapter 17 of an Uno Platform guide covering the essential role of testing in cross-platform C# development. It explains why testing is a load-bearing wall rather than optional in projects targeting up to seven runtimes (Windows, macOS, iOS, Android, WebAssembly, Linux, embedded). The chapter introduces test-driven development, dependency injection for testability, and the Arrange-Act-Assert pattern. It presents xUnit examples with [Fact] and [Theory]/[InlineData] for a DiscountService, then shows how Moq mocking isolates ViewModels from platform APIs like geolocation. Uno.UITest (Appium-based) covers UI automation with AutomationId in XAML, while Verify-based snapshot testing catches pixel-level visual regressions. A GitHub Actions YAML example demonstrates CI integration for unit and UI tests across Windows and macOS runners.

Key points

  • Why testing is non-negotiable in Uno Platform: C# code runs on up to seven runtimes (Windows, macOS, iOS, Android, WebAssembly, Linux, embedded). Code that works on Windows can break in WebAssembly due to memory limits, and smooth iOS animations can stutter on low-end Android. Tests form a "load-bearing wall" that catches bugs at the earliest stage, and TDD elevates them to "executable specifications."
  • Testability requires Dependency Injection (DI): A class should not create its own dependencies. The BadViewModel example creates new HttpClient() directly, forcing tests to hit a real network. The recommended pattern defines an IDataService interface, with ApiDataService for production and Mock<IDataService> injected via the constructor of ProductsViewModel in tests.
  • Unit tests target pure logic in ViewModel/Service layers: They run fast, need no simulator, and follow the Arrange-Act-Assert pattern. xUnit's [Fact] marks single-case tests; [Theory] + [InlineData] runs the same logic across multiple inputs.
  • Moq isolates platform APIs: For WeatherViewModel, which depends on IGeolocationService and IWeatherService, mocks return a fixed New York location and weather payload. Times.Once and Times.Never verifications confirm interaction contracts, distinguishing Mocks (verify behavior) from Stubs (return data only).
  • Uno.UITest (Appium-based) handles UI flows: Scripts use IApp to tap UsernameTextBox, enter text, dismiss the keyboard, tap LoginButton, and assert that HomeWelcomeText appears within a timeout. The critical XAML discipline is setting AutomationId on every locatable element; using visible text (e.g., "登录") would break under localization to "Login".
  • Snapshot testing catches visual regressions: Tools such as Verify record a baseline rendering (e.g., settings_page_screenshot.png) and diff any subsequent run. Best used inside code review, since any intentional UI change forces a manual baseline update.
  • CI integration preserves test value: A layered strategy pairs fast compile-time unit tests (run on every push) with pre-merge UI tests on device farms. The included GitHub Actions YAML runs dotnet test --collect:"XPlat Code Coverage" on windows-latest for unit tests and macos-latest (needed for iOS + Android emulators) for UI tests, gated by needs: unit-tests.

Hands-on exercises

1. Create an xUnit project for an Uno app and write at least five tests around one business-logic class, covering normal, boundary, and exception cases. Use [Theory] + [InlineData] to parameterize. 2. Use Moq to test a class that depends on an external service, simulating varied return data and exception paths. 3. Write Uno.UITest scripts for critical flows such as login and form submission, ensuring every locatable XAML element exposes an AutomationId, then run them against a local emulator.

Tags

#uno-platform#tdd#unit-testing#xunit#moq#dependency-injection#uitest#ci-cd

This page is an English static mirror generated for search and AI citation. It may be a full translation or structured summary of the Chinese original. Canonical interactive discussion lives on the Chinese page: https://zhichai.net/topic/176922798