This article is about Amway to develop a WPF UI unit testing framework that supports using Chinese as use case names
selling point
Do you find naming too difficult? Do you find the naming of unit tests more difficult? Yes, this is a big problem in the industry. Many teams do not like to write unit tests because it is too difficult to name the use case functions of unit tests, or they feel that the unit test case names written by the other party have syntax errors during code review, or when they change to unit tests, they find that the function names cannot be understood because their English ability is limited
This article is from Amway to dotnetcampus UITest. WPF unit test framework will be used to solve this problem. Using it, you can describe one test case after another by contract. These test cases will be displayed in the unit test console or GUI window after the unit test run is completed. Throughout the process, you don't need to name any unit test methods at all - you focus on the test case itself
Now, your unit test can be written as follows:
[TestClass] public class DemoTest { [UIContractTestCase] public void TestAsyncLoad() { "The wait window is displayed. You can successfully wait asynchronously without locking the main thread".Test(async () => { var mainWindow = new MainWindow(); var taskCompletionSource = new TaskCompletionSource(); mainWindow.Loaded += (sender, args) => taskCompletionSource.SetResult(); await mainWindow.Dispatcher.InvokeAsync(mainWindow.Show); await taskCompletionSource.Task; }); } }
Then, running the unit test will see the following result view:
The UI unit Test framework only provides that you can write UI Test code in the CUint(Chinese Unit Test) style. All the code placed in the Test will be executed in the UI thread. This UI unit Test framework does not provide Test oriented auxiliary type methods, such as simulating mouse click and other functions. If these functions are required, please also use the library of a third party for assistance
usage method
This unit testing framework is based on MIT's most friendly open source protocol and is completely open source on GitHub. Please see https://github.com/dotnet-campus/CUnit/
This unit test framework is an extension of MSTest v2. When using it, you need to create a MSTest unit test project and install it additionally in this unit test project dotnetCampus.UITest.WPF Library. For csproj files in the new SDK style, you can edit and add the following code to install the library
<PackageReference Include="dotnetCampus.UITest.WPF" Version="2.2.0" />
If your unit test project contains WPF app Xaml file. In order to fix the problem of multiple entry Main functions when building unit tests, you need to add the following code to fix this problem
<ItemGroup> <ApplicationDefinition Remove="App.xaml" /> </ItemGroup> <ItemGroup> <Page Include="App.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> </ItemGroup>
The above is for app Xaml repair is not necessary. Only your unit test project contains app Xaml has this requirement. This problem is not dotnetCampus.UITest.WPF Library, but the problem of general unit testing. Most UI unit test projects will not and should not include App Xaml file, unless this is a unit test for WPF's UI class library. For the UI unit test of the application itself, the App class of the application should be passed in
After the change, the content of csproj is as follows
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>exe</OutputType> <DisableWinExeOutputInference>true</DisableWinExeOutputInference> <TargetFramework>net6.0-windows</TargetFramework> <Nullable>enable</Nullable> <UseWPF>true</UseWPF> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <ApplicationDefinition Remove="App.xaml" /> </ItemGroup> <ItemGroup> <Page Include="App.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> </ItemGroup> <ItemGroup> <PackageReference Include="Moq" Version="4.16.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.2.8" /> <PackageReference Include="MSTest.TestFramework" Version="2.2.8" /> <PackageReference Include="coverlet.collector" Version="3.1.0" /> <PackageReference Include="dotnetCampus.UITest.WPF" Version="2.2.0" /> </ItemGroup> </Project>
Before writing the actual UI unit test, you need to initialize the UI test engine because WPF needs to give a specified App entry function to find assembly resources. The code is as follows
[TestClass] public class FooTest { [AssemblyInitialize] public static void InitializeApplication(TestContext testContext) { UITestManager.InitializeApplication(() => new App()); } }
In WPF, there are concepts such as resource assembly, which can be automatically set by initializing the engine through the above code. In an open test type marked with TestClassAttribute attribute, a static method with TestContext parameter marked with AssemblyInitializeAttribute attribute will be executed before starting the unit test. In this function, you need to call the UITestManager initialization engine to pass in the App class of the WPF application entry in the project you are testing
Next, you can start writing business unit test code, as shown in the following example
[TestClass] public class FooTest { [AssemblyInitialize] public static void InitializeApplication(TestContext testContext) { UITestManager.InitializeApplication(() => new App()); } [UIContractTestCase] public void TestAsyncLoad() { "The wait window is displayed. You can successfully wait asynchronously without locking the main thread".Test(async () => { var mainWindow = new MainWindow(); var taskCompletionSource = new TaskCompletionSource(); mainWindow.Loaded += (sender, args) => taskCompletionSource.SetResult(); await mainWindow.Dispatcher.InvokeAsync(mainWindow.Show); await taskCompletionSource.Task; }); } [UIContractTestCase] public void TestMainWindow() { "open MainWindow Window, the window can be opened successfully".Test(() => { Assert.AreEqual(Application.Current.Dispatcher, Dispatcher.CurrentDispatcher); var mainWindow = new MainWindow(); bool isMainWindowLoaded = false; mainWindow.Loaded += (sender, args) => isMainWindowLoaded = true; mainWindow.Show(); Assert.AreEqual(true, isMainWindowLoaded); }); "close MainWindow Window, you can successfully close the window and receive the window closing event".Test(() => { var window = Application.Current.MainWindow; Assert.AreEqual(true, window is MainWindow); bool isMainWindowClosed = false; Assert.IsNotNull(window); window.Closed += (sender, args) => isMainWindowClosed = true; window.Close(); Assert.AreEqual(true, isMainWindowClosed); }); } }
Each incoming function is executed in the UI thread, so you can safely call any UI resource
code
All the code in this article github and gitee Welcome to visit
You can obtain the source code of this article in the following ways. First create an empty folder, then use the command line cd command to enter this empty folder, and enter the following code on the command line to obtain the code of this article
git init git remote add origin https://gitee.com/lindexi/lindexi_gd.git git pull origin 5d83d18e3f369c36759e1b3d1b6afc1a1c3cac30
The above uses the source of gitee. If gitee cannot access it, please replace it with the source of github
git remote remove origin git remote add origin https://github.com/lindexi/lindexi_gd.git
After obtaining the code, enter dotnetcampus UITest. WPF. Demo folder