DRN.Framework.Testing 0.1.0-preview011

Prefix Reserved
This is a prerelease version of DRN.Framework.Testing.
There is a newer version of this package available.
See the version list below for details.
dotnet add package DRN.Framework.Testing --version 0.1.0-preview011                
NuGet\Install-Package DRN.Framework.Testing -Version 0.1.0-preview011                
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="DRN.Framework.Testing" Version="0.1.0-preview011" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DRN.Framework.Testing --version 0.1.0-preview011                
#r "nuget: DRN.Framework.Testing, 0.1.0-preview011"                
#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.
// Install DRN.Framework.Testing as a Cake Addin
#addin nuget:?package=DRN.Framework.Testing&version=0.1.0-preview011&prerelease

// Install DRN.Framework.Testing as a Cake Tool
#tool nuget:?package=DRN.Framework.Testing&version=0.1.0-preview011&prerelease                

master develop Quality Gate Status

Security Rating Maintainability Rating Reliability Rating Vulnerabilities Bugs Lines of Code Coverage

Introduction

DRN.Framework.Testing package provides practical, effective helpers such as resourceful data attributes and test context.

This package enables a new encouraging testing technique called as DTT(Duran's Testing Technique). With DTT, any developer can write clean and hassle-free unit and integration tests without complexity.

Encapsulated Packages

You no longer need to be reference followings in your test project:

  • AutoFixture.AutoNSubstitute
  • AutoFixture.Xunit2
  • DRN.Framework.Utils
  • FluentAssertions
  • NSubstitute
  • xunit

QuickStart: Basics

Here's a basic test demonstration to take your attention and get you started:

    [Theory]
    [DataInlineContext]
    public void DataInlineContextDemonstration(TestContext context, IMockable autoInlinedDependency)
    {
        context.ServiceCollection.AddApplicationServices();
        //Context wraps service provider and automagically replaces actual dependencies with auto inlined dependencies
        var dependentService = context.GetRequiredService<DependentService>();
        
        autoInlinedDependency.Max.Returns(int.MaxValue); //dependency is mocked by NSubstitute
        dependentService.Max.Should().Be(int.MaxValue); //That is all. It is clean and effective 
    }

Table of Contents

  • Introduction
  • TestContext
  • DataAttributes
  • DebugOnly Tests
  • Settings and Data Providers
  • Global Usings
  • Example Test Project

Testing models used in the QuickStart


public static class ApplicationModule //Can be defined in Application Layer or in Hosted App
{
    public static void AddApplicationServices(this IServiceCollection serviceCollection)
    {
        serviceCollection.AddTransient<IMockable, ToBeRemovedService>(); //will be removed by test context because test method requested mocked interface
        serviceCollection.AddTransient<DependentService>(); //dependent service uses IMockable and Max property returns dependency's Max value
    }
}

public interface IMockable
{
    public int Max { get; }
}

public class ToBeRemovedService : IMockable
{
    public int Max { get; set; }
}

public class DependentService : IMockable
{
    private readonly IMockable _mockable;

    public DependentService(IMockable mockable)
    {
        _mockable = mockable;
    }

    public int Max => _mockable.Max;
}

QuickStart: Advanced Data Inline

  • DataInlineContext will provide TestContext as first parameter.
  • Then it will provide inlined values.
  • Then it will provide auto inline missing values with AutoFixture.
  • AutoFixture will mock any interface requested with NSubstitute.
/// <param name="context"> Provided by DataInlineContext even if it is not a compile time constant</param>
/// <param name="inlineData">Provided by DataInlineContext</param>
/// <param name="autoInlinedData">DataInlineContext will provide missing data with the help of AutoFixture</param>
/// <param name="autoInlinedMockable">DataInlineContext will provide implementation mocked by NSubstitute</param>
[Theory]
[DataInlineContext(99)]
public void TextContext_Should_Be_Created_From_TestContextData(TestContext context, int inlineData, Guid autoInlinedData, IMockable autoInlinedMockable)
{
    inlineData.Should().Be(99);
    autoInlinedData.Should().NotBeEmpty(); //guid generated by AutoFixture
    autoInlinedMockable.Max.Returns(int.MaxValue); //dependency mocked by NSubstitute

    context.ServiceCollection.AddApplicationServices(); //you can add services, modules defined in hosted app, application, infrastructure layer etc..
    var serviceProvider = context.BuildServiceProvider(); //appsettings.json added by convention. Context and service provider will be disposed by xunit
    serviceProvider.GetService<ToBeRemovedService>().Should().BeNull(); //Service provider behaviour demonstration

    var dependentService = serviceProvider.GetRequiredService<DependentService>();
    dependentService.Max.Should().Be(int.MaxValue);
}

TestContext

TestContext has following properties:

  • captures values provided to running test method and its method info.
  • provides ServiceCollection so that to be tested services and dependencies can be added before building ServiceProvider.
  • provides lightweight ServiceProvider that contains default logging without any provider
    • ServiceProvider can provide services that depends like ILogger<DefaultService>
    • logged data will not be leaked to anywhere since it has no logging provider.
  • ServiceProvider provides IConfiguration and IAppSettings with SettingsProvider.
    • SettingsProvider reads json settings files that can be found in the settings folder of the test project
    • Make sure file is copied to output directory
    • If no settings file is specified while calling BuildServiceProvider. appsettings.json file be searched by convention.
  • ServiceProvider provides utils provided with DRN.Framework.Utils' UtilsModule
  • BuildServiceProvider replaces dependencies that can be replaced with inlined interfaces.
  • ServiceProvider and TestContext will be disposed by xunit when test finishes

Data Attributes

DRN.Framework.Testing provides following data attributes that can provide data to tests:

  • DataInlineAutoAttribute
  • DataInlineContextAttribute
  • DataMemberAutoAttribute
  • DataMemberContextAttribute
  • DataSelfAutoAttribute
  • DataSelfContextAttribute

Following design principle is used for these attributes

  • All attributes has data prefix to benefit from autocomplete
  • Inline attributes works like xunit InlineData except they try to provide missing values with AutoFixture and NSubstitute
  • Member attributes works like xunit MemberData except they try to provide missing values with AutoFixture and NSubstitute
  • Self attributes needs to be inherited by another class and should call AddRow method in constructor to provide data
  • Context attributes provide TestContext as first parameter

Member Attributes

Example usages for member attributes

[Theory]
[DataMemberAuto(nameof(DataMemberAutoData))]
public void AutoMember_Should_Inline_And_Auto_Generate_Missing_Test_Data(int inline, ComplexInline complexInline, Guid autoGenerate, IMockable mock)
{
    inline.Should().BeGreaterThan(10);
    complexInline.Count.Should().BeLessThan(10);
    autoGenerate.Should().NotBeEmpty();
    mock.Max.Returns(75);
    mock.Max.Should().Be(75);
}

public static IEnumerable<object[]> DataMemberAutoData => new List<object[]>
{
    new object[] { 11, new ComplexInline(8) },
    new object[] { int.MaxValue, new ComplexInline(-1) }
};
[Theory]
[DataMemberContext(nameof(TestContextInlineMemberData))]
public void TestContextMember_Should_Inline_And_Auto_Generate_Missing_Test_Data(TestContext testContext,
    int inline, ComplexInline complexInline, Guid autoGenerate, IMockable mock)
{
    testContext.Should().NotBeNull();
    testContext.TestMethod.Name.Should().Be(nameof(TestContextMember_Should_Inline_And_Auto_Generate_Missing_Test_Data));
    inline.Should().BeGreaterThan(10);
    complexInline.Count.Should().BeLessThan(10);
    autoGenerate.Should().NotBeEmpty();
    mock.Max.Returns(75);
    mock.Max.Should().Be(75);
}

public static IEnumerable<object[]> TestContextInlineMemberData => new List<object[]>
{
    new object[] { 11, new ComplexInline(8) },
    new object[] { int.MaxValue, new ComplexInline(-1) }
};

Self Attributes

Example usages for self attributes

public class DataSelfAutoAttributeTests
{
    [Theory]
    [DataSelfAutoTestData]
    public void AutoClass_Should_Inline_And_Auto_Generate_Missing_Test_Data(int inline, ComplexInline complexInline, Guid autoGenerate, IMockable mock)
    {
        inline.Should().BeGreaterThan(10);
        complexInline.Count.Should().BeLessThan(10);
        autoGenerate.Should().NotBeEmpty();
        mock.Max.Returns(75);
        mock.Max.Should().Be(75);
    }
}

public class DataSelfAutoTestData : DataSelfAutoAttribute
{
    public DataSelfAutoTestData()
    {
        AddRow(200, new ComplexInline(9));
        AddRow(300, new ComplexInline(int.MinValue));
    }
}
public class DataSelfContextAttributeTests
{
    [Theory]
    [DataSelfContextTestData]
    public void TestContextClassData_Should_Inline_And_Auto_Generate_Missing_Test_Data(TestContext testContext,
        int inline, ComplexInline complexInline, Guid autoGenerate, IMockable mock)
    {
        testContext.Should().NotBeNull();
        testContext.TestMethod.Name.Should().Be(nameof(TestContextClassData_Should_Inline_And_Auto_Generate_Missing_Test_Data));
        inline.Should().BeGreaterThan(98);
        complexInline.Count.Should().BeLessThan(1001);
        autoGenerate.Should().NotBeEmpty();
        mock.Max.Returns(44);
        mock.Max.Should().Be(44);
    }
}

public class DataSelfContextTestData : DataSelfContextAttribute
{
    public DataSelfContextTestData1()
    {
        AddRow(99,new ComplexInline(100));
        AddRow(199,new ComplexInline(1000));
    }
}

Inline Attributes

Example usages for inline attributes

[Theory]
[DataInlineAuto(10)]
public void AutoInline_Should_Inline_And_Auto_Generate_Missing_Test_Data(int inline, Guid autoGenerate, IMockable mock)
{
    inline.Should().Be(10);
    autoGenerate.Should().NotBeEmpty();
    mock.Max.Returns(65);
    mock.Max.Should().Be(65);
}
[Theory]
[DataInlineContext(99)]
public void TextContext_Should_Be_Created_From_TestContextData(TestContext context, int inlineData, Guid autoInlinedData, IMockable autoInlinedMockable)
{
    inlineData.Should().Be(99);
    autoInlinedData.Should().NotBeEmpty(); //guid generated by AutoFixture
    autoInlinedMockable.Max.Returns(int.MaxValue); //dependency mocked by NSubstitute

    context.ServiceCollection.AddApplicationServices(); //you can add services, modules defined in hosted app, application, infrastructure layer etc..
    var serviceProvider = context.BuildServiceProvider(); //appsettings.json added by convention. Context and service provider will be disposed by xunit
    serviceProvider.GetService<ToBeRemovedService>().Should().BeNull(); //Service provider behaviour demonstration

    var dependentService = serviceProvider.GetRequiredService<DependentService>();
    dependentService.Max.Should().Be(int.MaxValue);
}

DebugOnly Tests

Following attributes can be used to run test only when the debugger is attached. These attributes does respect the attached debugger, not debug or release configuration.

  • FactDebuggerOnly
  • TheoryDebuggerOnly

Providers

SettingsProvider

SettingsProvider gets the settings from Settings folder. Settings file path is relative Settings folder. Settings folder must be created in the root of the test Project. Make sure the settings file is copied to output directory.

    [Fact]
    public void SettingsProvider_Should_Return_IAppSettings_Instance()
    {
        var appSettings = SettingsProvider.GetAppSettings();

        appSettings.GetRequiredSection("AllowedHosts").Value.Should().Be("*");
        appSettings.TryGetSection("Bar", out _).Should().BeTrue();
        appSettings.TryGetSection("Foo", out _).Should().BeFalse();
        appSettings.GetRequiredConnectionString("Foo").Should().Be("Bar");
        appSettings.TryGetConnectionString("Bar", out _).Should().BeFalse();
    }

    [Fact]
    public void SettingsProvider_Should_Return_IConfiguration_Instance()
    {
        var configuration = SettingsProvider.GetConfiguration("secondaryAppSettings");

        configuration.GetRequiredSection("AllowedHosts").Value.Should().Be("*");
        configuration.GetSection("Foo").Exists().Should().BeTrue();
        configuration.GetSection("Bar").Exists().Should().BeFalse();
        configuration.GetConnectionString("Bar").Should().Be("Foo");
    }

DataProvider

DataProvider gets the content of specified data file in the Data folder. Data file path is relative Data folder including file extension. Data folder must be created in the root of the test Project. Make sure the data file is copied to output directory.

    [Fact]
    public void DataProvider_Should_Return_Data_From_Test_File()
    {
        DataProvider.Get("Test.txt").Should().Be("Foo");
    }

Global Usings

Following global usings can be used in a Usings.cs file in test projects to reduce line of code in test files

global using Xunit;
global using AutoFixture;
global using AutoFixture.AutoNSubstitute;
global using AutoFixture.Xunit2;
global using DRN.Framework.Utils.Extensions;
global using DRN.Framework.SharedKernel;
global using DRN.Framework.Utils.Settings;
global using DRN.Framework.Testing;
global using DRN.Framework.Testing.DataAttributes;
global using DRN.Framework.Testing.Providers;
global using DRN.Framework.Testing.TestAttributes;
global using DRN.Framework.Testing.Contexts;
global using FluentAssertions;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Configuration;
global using NSubstitute;
global using System.Reflection;
global using System.IO;
global using System.Linq;
global using System.Collections;

Example Test Project .csproj File

Don't forget to replace DRN.Framework.Testing project reference with its nuget package reference

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <IsPackable>false</IsPackable>
        <IsTestProject>true</IsTestProject>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2"/>
    </ItemGroup>

    <ItemGroup>
        <ProjectReference Include="..\DRN.Framework.Testing\DRN.Framework.Testing.csproj"/>
    </ItemGroup>

    <ItemGroup>
        <None Update="Settings\defaultAppSettings.json">
            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
        <None Update="Data\Test.txt">
            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
        <None Update="Settings\secondaryAppSettings.json">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
    </ItemGroup>

</Project>

Commit Info

Author: Duran Serkan KILIÇ
Date: 2023-11-19 18:54:26 +0300
Hash: 3615f3baa7e429be0e5f51526ce9434ecb4c1826

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.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
0.7.0-preview005 67 11/27/2024
0.7.0-preview004 66 11/23/2024
0.7.0-preview003 67 11/20/2024
0.7.0-preview002 66 11/17/2024
0.7.0-preview001 73 11/14/2024
0.6.0 97 11/10/2024
0.6.0-preview002 73 11/10/2024
0.6.0-preview001 75 11/10/2024
0.5.1-preview002 82 9/30/2024
0.5.1-preview001 82 9/22/2024
0.5.0 109 8/30/2024
0.5.0-preview011 71 8/30/2024
0.5.0-preview010 110 8/25/2024
0.5.0-preview009 96 8/8/2024
0.5.0-preview008 80 8/7/2024
0.5.0-preview007 68 8/2/2024
0.5.0-preview006 62 7/30/2024
0.5.0-preview005 89 7/27/2024
0.5.0-preview004 86 7/15/2024
0.5.0-preview003 102 6/6/2024
0.5.0-preview002 102 6/5/2024
0.5.0-preview001 103 6/4/2024
0.4.0 101 5/19/2024
0.4.0-preview006 72 5/19/2024
0.4.0-preview005 95 5/12/2024
0.4.0-preview004 94 5/12/2024
0.4.0-preview003 100 5/11/2024
0.4.0-preview002 100 5/8/2024
0.4.0-preview001 103 5/5/2024
0.3.1-preview001 97 4/26/2024
0.3.0 105 4/23/2024
0.3.0-preview002 80 4/23/2024
0.3.0-preview001 93 4/23/2024
0.2.2-preview010 103 4/11/2024
0.2.2-preview009 102 3/18/2024
0.2.2-preview008 107 3/18/2024
0.2.2-preview007 97 3/16/2024
0.2.2-preview006 81 3/11/2024
0.2.2-preview005 92 3/10/2024
0.2.2-preview004 90 3/10/2024
0.2.2-preview003 125 1/22/2024
0.2.2-preview002 103 1/18/2024
0.2.2-preview001 113 1/14/2024
0.2.1 184 1/7/2024
0.2.0 149 12/31/2023
0.2.0-preview009 120 12/31/2023
0.2.0-preview008 111 12/30/2023
0.2.0-preview007 125 12/28/2023
0.2.0-preview006 116 12/27/2023
0.2.0-preview005 119 12/25/2023
0.2.0-preview004 109 12/23/2023
0.2.0-preview003 128 12/20/2023
0.2.0-preview002 115 12/19/2023
0.2.0-preview001 112 12/18/2023
0.1.0 187 11/26/2023
0.1.0-preview013 129 11/26/2023
0.1.0-preview012 109 11/20/2023
0.1.0-preview011 122 11/19/2023
0.1.0-preview010 143 10/30/2023
0.1.0-preview009 99 10/29/2023
0.1.0-preview008 118 10/27/2023
0.1.0-preview007 112 10/11/2023
0.1.0-preview006 112 10/9/2023
0.1.0-preview005 115 10/8/2023
0.1.0-preview004 114 10/8/2023
0.1.0-preview003 100 10/3/2023
0.1.0-preview002 127 10/3/2023
0.1.0-preview001 130 10/2/2023

Not every version includes changes, features or bug fixes. This project can increment version to keep consistency with other DRN.Framework projects.

## Version 0.1.0

### Breaking Changes

### New Features

* TestContext added
* FactDebuggerOnly and TheoryDebuggerOnly test attributes added
* Following data attributes added:
 * DataInlineAutoAttribute
 * DataInlineContextAttribute
 * DataMemberAutoAttribute
 * DataMemberContextAttribute
 * DataSelfAutoAttribute
 * DataSelfContextAttribute
* SettingsProvider added
* DataProvider added

### Bug Fixes  
 
## Commit Info  
Author: Duran Serkan KILIÇ  
Date: 2023-11-19 18:54:26 +0300  
Hash: 3615f3baa7e429be0e5f51526ce9434ecb4c1826