Browse Source

Merge pull request #345 from Eideren/unit_tests

Add documentation covering how one writes unit tests
Vaclav Elias 1 year ago
parent
commit
1dd9adcdd8
3 changed files with 92 additions and 0 deletions
  1. 2 0
      en/manual/toc.yml
  2. 1 0
      en/manual/troubleshooting/index.md
  3. 89 0
      en/manual/troubleshooting/unit-tests.md

+ 2 - 0
en/manual/toc.yml

@@ -570,6 +570,8 @@ items:
         href: troubleshooting/debug-text.md
         href: troubleshooting/debug-text.md
       - name: Profiling
       - name: Profiling
         href: troubleshooting/profiling.md
         href: troubleshooting/profiling.md
+      - name: Unit Tests
+        href: troubleshooting/unit-tests.md
       - name: Stride doesn't run
       - name: Stride doesn't run
         href: troubleshooting/stride-doesnt-run.md
         href: troubleshooting/stride-doesnt-run.md
       - name: Default value changes ignored at runtime
       - name: Default value changes ignored at runtime

+ 1 - 0
en/manual/troubleshooting/index.md

@@ -7,6 +7,7 @@ These pages describe how to fix problems with Stride.
 * [Logging](logging.md)
 * [Logging](logging.md)
 * [Debug text](debug-text.md)
 * [Debug text](debug-text.md)
 * [Profiling](profiling.md)
 * [Profiling](profiling.md)
+* [Unit Tests](unit-tests.md)
 * [Stride doesn't run](stride-doesnt-run.md)
 * [Stride doesn't run](stride-doesnt-run.md)
 * [Default value changes ignored at runtime](default-value-changes-ignored-at-runtime.md)
 * [Default value changes ignored at runtime](default-value-changes-ignored-at-runtime.md)
 * [Lights don't cast shadows](lights-dont-cast-shadows.md)
 * [Lights don't cast shadows](lights-dont-cast-shadows.md)

+ 89 - 0
en/manual/troubleshooting/unit-tests.md

@@ -0,0 +1,89 @@
+# Unit Tests
+Unit tests in Stride are set up like any other unit tests in dotnet, 
+you create a new project specifically for unit tests, then write your tests in different C# files.
+
+Here's a bare-bone project to get you started:
+`YOUR_PROJECT_NAME.Windows.Tests.csproj`
+```xml
+<Project Sdk="Microsoft.NET.Sdk">
+    <PropertyGroup>
+        <!-- Change this framework to match the one specified in your *.Windows.csproj -->
+        <TargetFramework>net8.0-windows</TargetFramework>
+        <RuntimeIdentifier>win-x64</RuntimeIdentifier>
+        <OutputType>WinExe</OutputType>
+
+        <OutputPath>..\Bin\Tests\Windows\$(Configuration)\</OutputPath>
+        <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+
+        <!-- Force msbuild to check to rebuild this assembly instead of letting VS IDE guess -->
+        <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+        
+        <ImplicitUsings>enable</ImplicitUsings>
+        <Nullable>enable</Nullable>
+
+        <IsPackable>false</IsPackable>
+        <IsTestProject>true</IsTestProject>
+    </PropertyGroup>
+    <ItemGroup>
+        <!-- Add a reference to your game project here, do not reference the windows project here -->
+        <PackageReference Include="coverlet.collector" Version="6.0.0"/>
+        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
+        <PackageReference Include="xunit" Version="2.5.3"/>
+        <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
+    </ItemGroup>
+    <ItemGroup>
+        <Using Include="Xunit"/>
+    </ItemGroup>
+</Project>
+```
+And an example C# file:
+```cs
+using Stride.Engine;
+
+public class Tests
+{
+    [Fact]
+    public void MyBareboneTest()
+    {
+        Assert.NotEqual(1, 2);
+    }
+    
+    [Fact]
+    public void MyGameTest()
+    {
+        RunGameTest(async (game, scene) =>
+        {
+            var myEntity = new Entity();
+            scene.Entities.Add(myEntity);
+
+            Assert.NotEmpty(scene.Entities);
+
+            await game.Script.NextFrame(); // Wait one frame if you need to
+
+            myEntity.Scene = null;
+
+            Assert.Empty(scene.Entities);
+        });
+    }
+
+    /// <summary>
+    /// Run the given function within a game, providing support for tests requiring ECS, physics simulation, graphics and others.
+    /// </summary>
+    private static void RunGameTest(Func<Game, Scene, Task> asyncFunction)
+    {
+        using var game = new Game();
+        
+        // Fixed time step to reduce framerate discrepancies
+        game.IsFixedTimeStep = true;
+        game.IsDrawDesynchronized = false;
+        game.TargetElapsedTime = TimeSpan.FromTicks(10000000 / 60); // 60hz, 60fps
+        
+        game.Script.AddTask(async () =>
+        {
+            await asyncFunction(game, game.SceneSystem.SceneInstance.RootScene);
+            game.Exit();
+        });
+        game.Run();
+    }
+}
+```