hw.UnitTest 25.0.1

dotnet add package hw.UnitTest --version 25.0.1
                    
NuGet\Install-Package hw.UnitTest -Version 25.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="hw.UnitTest" Version="25.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="hw.UnitTest" Version="25.0.1" />
                    
Directory.Packages.props
<PackageReference Include="hw.UnitTest" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add hw.UnitTest --version 25.0.1
                    
#r "nuget: hw.UnitTest, 25.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=hw.UnitTest&version=25.0.1
                    
Install hw.UnitTest as a Cake Addin
#tool nuget:?package=hw.UnitTest&version=25.0.1
                    
Install hw.UnitTest as a Cake Tool

Overview

Provides some support for unit-testing. It is comapatible to nunit and MSTest although is provides some more features.

Supports:

  • almost any public non-abstract class can be a test class
  • supports dependencies between tests
  • supports tagging tests as low-priority
  • supports pending-tests file as editable code file

Restrictions:

  • No gui or automatic IDE-integration available
  • Startup and teardown concepts are not supported. Use constructor and dispose if required.

Getting started

  • Mark classes and their methods with the attribute UnitTest to define them as unit test.
  • classes must be:
    • public
    • static or sealed
    • have no template parameters (although their base classes may have them)
    • classes can be toplevel or nested
  • methods must be
    • public
    • non-abstract
    • static or not
    • without parameters and return values
  • include at least Assembly.GetExecutingAssembly().RunTests() in Main-function of your test-executable

With default configuration when executed it will create and update a file that contains the prograss of the testrun. The file is named Test.HW.config and is located at working directory of test run. It is also used as input for subsequent runs by not re-running successful tests. To completely rerun all tests just delete it.

Features

Test Selection

The testrunner is responsible for selecting the test to execute. It is done at different stages.

  1. For starting it accepts a list of assemblies.
  2. For each assembly it searches all public classes that are marked as test.
  3. For each such class it searches for public methods that are marked as test.
  4. For any such method it checks if all run-conditions are met (see below)

Run-conditions are:

  • Test is not marked as sussessful by Test.HW.config
  • All dependencies are marked as successful
  • Test has correct priority

#Test execution

Important: Each test (on method-level) is executed in its own environment. Even for excuting methods of the same class a new class instances is created for each method.

There are the following variants for executing a test:

Default

If the class is not static then an instance of it is created (by use of the default constructor). This instance (or null for static classes) is used for invoking the the method.

By Action

Only for debug purposes this test infrastructure can be used by providing a System.Action to test runner.

Example:

[UnitTest]
public sealed class ExampleTest
{
    [UnitTest]
    public void ExampleMethod()
    {
        "BlaBlaBla".AssertValid()
    }
}
 
void Main()
{
    ...

    TestRunner.RunTest(new ExampleTest().ExampleMethod);
}

By Interface ITestFixture

Your test class can implement the interface ITestFixture. There you have to provide a method Run which serves a the method to execute. It gets a freshly created instance of the class and is executed with it. As in the default case. Although the class still has to be provided with the UnitTest attribute, this can be omitted from the method in this case. The default variant and the ITestFixture variant can be used in the same class.

Custom Test Selection

By default the methods to execute are selected by attribute UnitTest. This can be extended by registering test frameworks. You should provide an class derived from IFramework and register an instance to test runner.

Here is an example (AttributedFramework is implementing IFramework):

sealed class NunitFramework : AttributedFramework<TestFixtureAttribute,TestAttribute>
{
    public static readonly NunitFramework Instance = new();
}


void RegisterIt()
{
    TestRunner.RegisteredFrameworks.Add(NunitFramework.Instance);
}

The registration should take place before running any test.

The above example registers all tests from the ever-famous NUnit test suite. To implement even more advanced test selection you can implement the IFramework-interface. Look at the source code if you need to achieve this. It should be easy.

Dependencies

You may derive your test class from class DependenceProvider. DependenceProvider is an abstract class derived from System.Attribute. Thus you can use your test class as attribute. When you use this attributes on other test classes you definded a dependency. TestRunner.RunTests will use this information as run-condition (see above). It has no effect on TestRunner.RunTest.

Priorities

A class can be flagged with the attribute LowPriority. In this case the tests contained in this class are only executed by TestRunner.RunTests when all other tests are successful. This will also prevent dependant test from beeing executed. It has no effect on TestRunner.RunTest.

Configuration

The testrunner can be configured. This can be done according to the following example:

TestRunner.Configuration.IsBreakEnabled = Debugger.IsAttached;

The following options are available:

IsBreakEnabled

This boolean is controlling the function Tracer.TraceBreak of hw.Helper.Core.

SaveResults

This boolean controlls if Test.HW.config is written each time a method is going to be executed by TestRunner.RunTests. It has no effect on TestRunner.RunTest.

SkipSuccessfulMethods

This boolean controlls if Test.HW.config is used to skip tests that have already been successful in a previous run. Affects only TestRunner.RunTests.

TestsFileName

This string may contain a path to a C# file. TestRunner.RunTests will write this file between each excution of a test-method. This file will be a valid C#-file. It will contain a line for each method that has not been executed successfully.

Thus it will shrink (hopefully) during test run whenever a test method executed successfully.

The file is looking like this example:

namespace hw.UnitTest;
public static class PendingTests
{
    public static void Run()
    {
    
    // notrun 
    TestRunner.RunTest(new MyNameSpace.ExampleTestClass().TestMethod);
    ...
    }
}

It is recommended to include this file into your C#-project. Furthermore it is recommended to call the method PendingTests.Run during your debug session.

This has the following very nice effects:

  • You can easily watch the progress when you run the test outside the debugger
  • You can easily switch to debug mode after a (partly) unsuccessful test run.
  • In debug mode you are free to remove lines from this file that belong to tests fixed.
  • In debug mode you are free to add lines to this file for newly created tests.

In your executable you should call a function that is looking like the following example:

static void RunAllTests()
{
    var configuration = TestRunner.Configuration;

    if(Debugger.IsAttached)
    {
        configuration.IsBreakEnabled = true;
        configuration.SkipSuccessfulMethods = true;
        configuration.SaveResults = false;
        hw.UnitTest.PendingTests.Run();
    }
    else
    {
        configuration.IsBreakEnabled = false;
        configuration.SkipSuccessfulMethods = false;
        configuration.SaveResults = true;
        configuration.TestsFileName = SmbFile.SourcePath.PathCombine("PendingTests.cs");
        Assembly.GetExecutingAssembly().RunTests();
    }
}

Issues and Co.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
25.0.1 121 1/22/2025
25.0.0.8 97 1/13/2025
24.0.1 135 9/20/2024
24.0.0 134 9/4/2024
23.0.3 443 1/19/2023
23.0.2 402 1/6/2023
23.0.1 321 1/5/2023
23.0.0 397 1/5/2023
22.0.2 367 12/16/2022
22.0.1 363 12/8/2022
22.0.0 606 2/2/2022
21.1.2 359 12/17/2021
21.1.1 390 12/7/2021
21.1.0 397 12/3/2021
21.0.0 340 11/30/2021
20.0.6 614 10/19/2020
20.0.5 597 10/7/2020
20.0.3 618 10/4/2020
20.0.2 615 10/4/2020
20.0.1 500 10/4/2020
20.0.0.3 572 10/2/2020
20.0.0.2 551 9/30/2020
20.0.0.1 598 9/30/2020
20.0.0 603 9/30/2020
17.1.0 1,342 9/26/2017
15.1.0 1,532 12/11/2015
15.0.2 1,473 4/3/2015
15.0.1 1,327 4/3/2015
15.0.0 1,300 3/31/2015
14.1.4 1,340 3/4/2015
14.1.3 1,341 10/30/2014
14.1.2.1 1,316 10/17/2014
14.1.2.1-alpha 1,100 10/17/2014
14.1.2-alpha 1,071 10/17/2014
14.1.1-alpha 1,086 10/17/2014
14.1.0-alpha 1,146 10/17/2014
14.0.0 1,454 1/14/2014
0.2.2-alpha 1,105 10/18/2013
0.2.1-alpha 1,110 9/16/2013
0.2.0-alpha 1,105 9/15/2013
0.1.0 1,452 9/15/2013

Upgrade hw core
           25.0.0.8
           bugfix: use DeclaringType for actions with static methods
           bugfix: pending test file generation respects static methods
           refactor: upgrade C#, .net9
           24.0.1
           refactor: upgrade C#
           23.0.3
           admin: Fix for use with .net6
           23.0.2
           Readme added
           22.0.2
           admin: dependency fixed
           refactor: Upgrade C#
           22.0.1
           Wrong version of dependency
           22.0
           refactor: escalating statements of deprecation
           refactor: upgrade C#
           21.1.2
           change: IsSuccessful for methods introduced
           change: PendingTests: No line is generated under error tag for successful methods
           refactor: upgrade C#
           21.1.1
           refactor: warnings fixed
           21.1
           refactor: escalating statements of deprecation
           21.0
           refactor: Upgrade C#
           20.0.6
           bug: Static test methods are disabled
           20.0.5
           change: Trace improved
           change: TestRunner configuration
           20.0.4
           new: Sample test file generation improved
           20.0.3
           new: TextPart/TextPosition
           20.0.2
           new: Support generation of a cs file with sample tests
           20.0.0.3
           new: IsBreakDisabled: debug is more convenient
           Upgrade: new style
           17.1
           Upgrade: File to SmbFile
           15.1
           Use Breaking changes of hw.Helper.Core
           15.0.2
           New: Ability to register other test frameworks
           15.0.1
           Change: Test runner returns false when any test has failed
           15.0
           Breaking Change: Attributes TestFixture and Test renamed to UnitTest