-
Notifications
You must be signed in to change notification settings - Fork 80
Testing
The Community Toolkit makes it easy to test your components.
Each component is templated with a ./tests/
folder which contains a shared project which can handle both Unit Tests and UI tests. This project is equipped with a source-generator enhanced set of tools that does the heavy lifting for you.
Simply write your tests and they'll be run against all available platforms. For now, this includes both UWP and WinAppSdk, but may be expanded to more platforms in the future.
Before running tests, be sure to build the solution first to discover the generated tests.
Tests can easily be run from Visual Studio by opening the Test Explorer
pane from the Test
menu. Then just click the Double-Run/Play icon within the pane to run the tests. This will also deploy and run all tests.
To run a specific set of tests (or individual test), just click on the branch within the tree and click the single run/play icon instead.
Adding a new unit test is the same as adding any MSTest. There are plenty of existing examples within the repo to show various operations at work.
For the full list of examples and best practices provided in the test template, see the Example test class from our tooling.
If you don't require UI access, mark your test method with [TestMethod]
for a standard unit test. They'll run as normal MSTest unit tests.
Our tooling provides both the VisualUITestBase
class and the UIThreadTestMethod
attribute to help you write UI tests.
If you need the component to be fully realized within the UI, perform layout, or access the Visual Tree, you may want to inherit your test class from VisualUITestBase
.
The UIThreadTestMethod automatically dispatches to the UI for us to work with UI objects:
[UIThreadTestMethod]
public void SimpleUIAttributeExampleTest()
{
var component = new MyComponent();
Assert.IsNotNull(component);
}
The UIThreadTestMethod also handles async test methods as you'd expect:
[UIThreadTestMethod]
public async Task SimpleUIAttributeExampleTestAsync()
{
await Task.Delay(500);
var component = new MyComponent();
Assert.IsNotNull(component);
}
By declaring a XAML FrameworkElement as a test method parameter, the UIThreadTestMethod will:
- Execute on the UI thread.
- Automatically instantiate the declared FrameworkElement type with a parameter-less constructor.
- Load the FrameworkElement into the Visual Tree.
- Provides the constructed instance to your test.
This lets us test a control as it would behave within an actual application. The page will already be loaded by the time your test is called.
[UIThreadTestMethod]
public void SimpleUIExamplePageTest(ExampleMyComponentTestPage page)
{
// You can use the Toolkit Visual Tree helpers here to find the component by type or name:
var component = page.FindDescendant<MyComponent>();
Assert.IsNotNull(component);
var componentByName = page.FindDescendant("ProjectTemplateControl");
Assert.IsNotNull(componentByName);
}
See Tooling-Windows-Submodule/176 for tracking.
The UIThreadTestMethod
does not yet support forwarding the [DataRow]
attribute to the underlying test.
If you need to use [DataRow]
with a UIThreadTestMethod, you can use [TestMethod]
instead, and manually invoke the VisualUITestBase
to handle your needs:
[TestMethod]
[DataRow(0), DataRow(1), DataRow(2)]
public async Task ComplexAsyncUIExampleTest(int value)
{
await EnqueueAsync(() =>
{
var component = new ProjectTemplate_ClassicBinding();
Assert.IsNotNull(component);
});
}
To use [DataRow]
while loading a control into the Visual Tree:
[TestMethod]
[DataRow(0), DataRow(1), DataRow(2)]
public async Task ComplexAsyncLoadUIExampleTest(int value)
{
await EnqueueAsync(async () =>
{
// Create a new FrameworkElement
var component = new ProjectTemplate_ClassicBinding();
Assert.IsNotNull(component);
Assert.IsFalse(component.IsLoaded);
// Load the FrameworkElement into the Visual Tree for testing
await LoadTestContentAsync(component);
Assert.IsTrue(component.IsLoaded);
// Test code goes here
// TODO
// Unload the FrameworkElement from the Visual Tree
await UnloadTestContentAsync(component);
Assert.IsFalse(component.IsLoaded);
});
}
Remember, a well-written test:
- Tests a single concern at a time.
- Covers both success and failure scenarios to ensure the component aligns with an expected state.
- Ensures self-consistency. The test itself stays in a state that doesn't produce false positives.
- Is fast, repeatable and deterministic.
- Only tests what the component does, not what its dependencies do. Mock component dependencies where needed.
When fixing a bug, it's highly recommended to write a unit test which reproduces the bug first. This allows anybody to validate with certainty that:
- The reported bug was present.
- A given code change fixes the bug.
Find more in the general .NET Unit Testing best practices documentation.
- Home π
- Welcome π
- Principles βοΈ
- Roadmap πΊ
- .NET Foundation
- Why Microsoft supports this project
- License π
- Getting Started π
- Sample App π±
- NuGet Packages π¦
- Preview Packages π
- Toolkit Labs π§ͺ
- Questions β
- Discussions π₯
- Submitting an Issue βοΈ
- Good First Issue π
- Help Wanted π
- Bug Fixes π
- Feature Requests π«
- Create and Submit PullRequest π
- Documentation π
- Review PR π
- Avoid Roadblocks π§
- Required Dependencies π
- Quick Start β‘
- Sample Development π±
- Testing π§ͺ
- Accessibility Guideline βΏ
- Coding Style and Conventions β
- Building XAML Controls π
- CI and Infrastructure πΎ
- Updating ToolkitLabs.dev π
- Migration Guide from v7 to v8 π
- How the Project is Organized ποΈ
- Join the Toolkit Organization πͺ
- Hall of Fame π