Skip to content

Commit 44cdae5

Browse files
Add XAML unit testing guidelines
1 parent 585cb8b commit 44cdae5

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
description: "Guidelines for writing XAML unit tests in the Controls.Xaml.UnitTests project"
3+
---
4+
5+
# XAML Unit Testing Guidelines
6+
7+
This guide provides conventions for writing XAML unit tests in `src/Controls/tests/Xaml.UnitTests/`.
8+
9+
## 1. File Naming and Location for Issue Tests
10+
11+
When writing a test for a GitHub issue:
12+
13+
- **Location**: Place the test file in the `Issues/` folder
14+
- **Naming convention**: `MauiXXXXX.xaml` and `MauiXXXXX.xaml.cs` (where XXXXX is the GitHub issue number)
15+
16+
**Example:**
17+
```
18+
src/Controls/tests/Xaml.UnitTests/Issues/
19+
├── Maui12345.xaml
20+
└── Maui12345.xaml.cs
21+
```
22+
23+
## 2. Basic Test Pattern
24+
25+
Most unit tests will:
26+
1. Check that the XAML page can be created/inflated
27+
2. Perform some assertions on the created page
28+
3. Apply to all `[XamlInflator]` test variations (runtime, XamlC, SourceGen)
29+
30+
**XAML file (Maui12345.xaml):**
31+
```xaml
32+
<?xml version="1.0" encoding="utf-8" ?>
33+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
34+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
35+
x:Class="Microsoft.Maui.Controls.Xaml.UnitTests.Maui12345">
36+
<!-- Your test content -->
37+
</ContentPage>
38+
```
39+
40+
**Code-behind (Maui12345.xaml.cs):**
41+
```csharp
42+
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
43+
44+
public partial class Maui12345 : ContentPage
45+
{
46+
public Maui12345()
47+
{
48+
InitializeComponent();
49+
}
50+
51+
[TestFixture]
52+
class Tests
53+
{
54+
[Test]
55+
public void MyTest([Values] XamlInflator inflator)
56+
{
57+
var page = new Maui12345(inflator);
58+
Assert.That(page, Is.Not.Null);
59+
// Additional assertions
60+
}
61+
}
62+
}
63+
```
64+
65+
**Note**: Only add `[SetUp]` and `[TearDown]` methods if your test requires special initialization (e.g., setting up `DispatcherProvider` or `Application.Current`). Most tests don't need them.
66+
67+
## 3. Testing IL Correctness (XamlC) or Source Generation
68+
69+
When the test specifically validates compile-time behavior for a specific inflator:
70+
71+
**XamlC (IL generation):**
72+
```csharp
73+
[Test]
74+
public void MyTest([Values] XamlInflator inflator)
75+
{
76+
if (inflator == XamlInflator.XamlC)
77+
Assert.Throws<BuildException>(() => MockCompiler.Compile(typeof(Maui12345)));
78+
else
79+
{
80+
var page = new Maui12345(inflator);
81+
Assert.That(page, Is.Not.Null);
82+
}
83+
}
84+
```
85+
86+
**Source Generation:**
87+
```csharp
88+
using static Microsoft.Maui.Controls.Xaml.UnitTests.MockSourceGenerator;
89+
90+
[Test]
91+
public void MyTest([Values] XamlInflator inflator)
92+
{
93+
if (inflator == XamlInflator.SourceGen)
94+
{
95+
var result = CreateMauiCompilation()
96+
.WithAdditionalSource(
97+
"""
98+
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
99+
100+
[XamlProcessing(XamlInflator.Runtime, true)]
101+
public partial class Maui12345 : ContentPage
102+
{
103+
public Maui12345() => InitializeComponent();
104+
}
105+
""")
106+
.RunMauiSourceGenerator(typeof(Maui12345));
107+
Assert.That(result.Diagnostics, Is.Empty); // or Is.Not.Empty for error cases
108+
}
109+
else
110+
{
111+
var page = new Maui12345(inflator);
112+
Assert.That(page, Is.Not.Null);
113+
}
114+
}
115+
```
116+
117+
## 4. Handling Invalid Code Generation
118+
119+
When testing scenarios where code generation is **expected to fail** or produce invalid code, use special file extensions to prevent build failures:
120+
121+
| Extension | Behavior | Use Case |
122+
|-----------|----------|----------|
123+
| `.rt.xaml` | Runtime inflation only | XamlC/SourceGen should fail, but runtime should work |
124+
| `.rtsg.xaml` | Runtime + SourceGen only | XamlC should fail |
125+
| `.rtxc.xaml` | Runtime + XamlC only | SourceGen should fail |
126+
127+
**Why?** These extensions prevent the compiler and build tasks from processing the XAML file, allowing your test to execute and verify the expected behavior.
128+
129+
**Example:**
130+
```
131+
Issues/
132+
├── Maui12345.rt.xaml # Only inflated at runtime (compiler/sourcegen skip)
133+
└── Maui12345.xaml.cs
134+
```
135+
136+
## Quick Reference
137+
138+
| Scenario | Location | Naming | Special Extension |
139+
|----------|----------|--------|-------------------|
140+
| Issue test | `Issues/` | `MauiXXXXX.*` | None (unless invalid codegen) |
141+
| Invalid XamlC | `Issues/` | `MauiXXXXX.rt.xaml` | `.rt.xaml` |
142+
| Invalid SourceGen | `Issues/` | `MauiXXXXX.rt.xaml` or `.rtxc.xaml` | Depends on what should fail |
143+
| Test XamlC IL | Anywhere | Any | Use `MockCompiler` |
144+
| Test SourceGen | Anywhere | Any | Use `MockSourceGenerator` |
145+
146+
## Related Documentation
147+
148+
- `.github/copilot-instructions.md` - General MAUI development guidelines
149+
- `.github/instructions/uitests.instructions.md` - UI testing guidelines (different from XAML unit tests)

0 commit comments

Comments
 (0)