Classes to randomly generate data for unit tests. Powered by AutoFixture.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
TestHelperSupport
TestHelpers
.gitignore
LICENSE
README.md

README.md

TestHelpers

A class to randomly generate values. Useful for unit tests. Powered by AutoFixture.

Install-Package ConnelHooley.TestHelpers

Methods

Generate

Returns a value created by AutoFixture.

var randomMailAddress = TestHelper.Generate<MailAddress>();

To find out how to configure the AutoFixture instance inside the TestHelper please go the Configuration section.

GenerateException

Returns an exception with a randomly generated message.

var randomException = TestHelper.GenerateException();

GenerateBool

Returns a random boolean.

var randomBool = TestHelper.GenerateBool();

GenerateDateTime

Returns a random date between 1000 days in the past and 1000 days in the future.

var randomDate = TestHelper.GenerateDateTime();

GenerateDateTimeByWeekDay

Returns a random date between 1000 days in the past and 1007 days in the future on a certain day.

var randomMonday = TestHelper.GenerateDateTimeByWeekDay(DayOfWeek.Monday);

GenerateNumber

Returns a random number. Includes negative values.

var randomNumber = TestHelper.GenerateNumber();

GenerateNumberBelow

Returns a random number below a certain value. Includes negative values.

var randomNumberBelow100 = TestHelper.GenerateNumberBelow(100);

GenerateNumberAbove

Returns a random number above a certain value. Includes negative values.

var randomNumberAbove100 = TestHelper.GenerateNumberAbove(100);

GenerateNumberBetween

Returns a random number between two values. Both the lower and upper bounds are inclusive.

var randomNumberBetween50and100 = TestHelper.GenerateNumberBetween(50, 100);

ChooseRandomItem

Returns a random item from an IEnumerable.

var items = new[] {"hello", "world"};
var helloOrWorld = TestHelper.ChooseRandomItem(items);

It is also exposed as an extension method.

var items = new[] {"hello", "world"};
var helloOrWorld = items.ChooseRandomItem();

TakeRandomItem

Removes a random item from a List and returns the removed item.

var items = new[] {"hello", "world"};
var helloOrWorld = TestHelper.TakeRandomItem(items);

It is also exposed as an extension method.

var items = new[] {"hello", "world"};
var helloOrWorld = items.TakeRandomItem();

RandomCaseString

Randomly mix-cases a string so that some of its letters are uppercase and some are lowercase.

var randomMixedCase = TestHelper.RandomCaseString("hello world");

It is also exposed as an extension method.

var x = "hello world";
var randomMixedCase = x.ToRandomCase();

GenerateString

Returns a random string made up of letters from the alphabet (uppercase and lowercase), numbers and some special characters.

var randomString = TestHelper.GenerateString();

GenerateStringFrom

Returns a random string made up of the chars in the given string.

var randomStringMadeUpOfNumbers = TestHelper.GenerateStringFrom(TestHelper.Numbers);

GenerateWhitespaceString

Returns a string containing 1 to 50 spaces.

var randomWhitespace = TestHelper.GenerateWhitespaceString();

WrapStringInWhitespace

Returns the given string with 1 to 50 spaces prepended and appended to it.

var helloWorldWrappedInRandomWhitespace = TestHelper.WrapStringInWhitespace("helloworld");

It is also exposed as an extension method.

var x = "helloworld";
var helloWorldWrappedInRandomWhitespace = x.WrapStringInWhitespace();

GenerateMany

Runs the creator function between 2 and 100 times and returns the results in an IEnummerable.

var randomStrings = TestHelper.GenerateMany(TestHelper.GenerateString);

You can also specify how many times to run the creator:

var fiftyRandomStrings = TestHelper.GenerateMany(50, TestHelper.GenerateString);

GenerateEnum

Returns a random enum.

var randomDayOfWeek = TestHelper.GenerateEnum<DayOfWeek>();

You can also specify values to exclude:

var randomWeekDay = TestHelper.GenerateEnum(DayOfWeek.Saturday, DayOfWeek.Sunday);

GenerateGuid

Returns a random GUID.

var randomGuid = TestHelper.GenerateGuid();

GetRandomTypeGenerator

Returns a function that in turn returns random types.

var typeGenerator = TestHelper.GetRandomTypeGenerator();
var type1 = typeGenerator();
var type2 = typeGenerator();

The method works by getting the assembly of the Type type in the System namespace. It then gets all the exported types for that assembly. The returned Func randomly selects items from the exported types when it is ran. It removes items from the list as it goes to prevent duplicates. The Func will throw when there are no more types to pick from.

Configuration

There are two ways of configuring the TestHelper.

Test Helper Instances

So far, we have seen usage of the static TestHelper class. It is also possible to create a TestHelperInstance class that contains its own configuration.

For example:

public class Program
{
    public static void Main()
    {
        var testHelper = new TestHelperInstance(x =>
        {
            x.Register<User>(() => new User
            {
                Id = TestHelper.GenerateNumber(),
                Username = "ExampleUserName"
            });
        });
        var user = testHelper.Generate<User>();
        Console.WriteLine(user.Username); // Prints "ExampleUserName"
        Console.WriteLine(user.Id); // Prints random ID
        Console.ReadLine();
    }
}

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
}

This is useful for when a group of tests needs a particular configuration. The TestHelperInstance class has all the same methods as the static TestHelper class, although apart from the Generate<T>() method, they all just call the static TestHelper under the hood.

Configurators

Sometimes you always want to create a specified type the same way throughout a test project, or even all your test projects. To do this both the static TestHelper class and the TestHelperInstance scan for an interface called ITestHelperConfigurator:

  • The test helpers load any DLLs that end with .TestHelperSupport.dll.
  • They then query all the currently loaded assemblies for implementations of ITestHelperConfigurator.
  • These Configurators are then run to configure the test helpers.

An example of what using a Configurator would like:

public class Program
{
    public static void Main()
    {
        Console.WriteLine(TestHelper.Generate<string>()); // Prints "hello"
        Console.WriteLine(TestHelper.Generate<int>()); // Prints 5
        Console.ReadLine();
    }
}

public class TestHelperConfigurator : ITestHelperConfigurator
{
    public void Configure(ITestHelperContext x)
    {
        x.Register(() => "hello");
        x.Register(() => 5);
    }
}

The TestHelperInstance loads in any ITestHelperConfigurator implementations and then loads in its own configuration. This means that if a TestHelperInstance registers a type in the action passed into its constructor, this registration will be used instead of any found in any Configurators.

For example:

public class Program
{
    public static void Main()
    {
        var testHelper = new TestHelperInstance(x =>
        {
            x.Register(() => "world");
        });
        Console.WriteLine(testHelper.Generate<string>()); // Prints "world"
        Console.ReadLine();
    }
}

public class TestHelperConfigurator : ITestHelperConfigurator
{
    public void Configure(ITestHelperContext x)
    {
        x.Register(() => "hello");
    }
}

Authoring a Configurator

If you create a type that should always be created in a certain way, you can create a NuGet package that references your type and includes an ITestHelperConfigurator implementation.

Below is an example type I could publish as a NuGet package called UpperCaseString:

public class UpperCaseString
{
    private readonly string _value;

    public UpperCaseString(string x)
    {
        if(x != x.ToUpperInvariant()) throw new ArgumentException("String must be uppercase");
        _value = x;
    }

    public static implicit operator string(UpperCaseString d) => d._value;
}

I could then publish the following Configurator as a separate NuGet package called UpperCaseString.TestHelperSupport:

public class UpperCaseStringTestHelperConfigurator : ITestHelperConfigurator
{
    public void Configure(ITestHelperContext x)
    {
        x.Register(() => new UpperCaseString(x.Generate<string>().ToUpperInvariant()));
    }
}

Calling it UpperCaseString.TestHelperSupport ensures that the test helper classes load in the assembly even if no other code references it.

The test helper support package only needs to reference the ConnelHooley.TestHelpers.Abstractions package. Then when anyone uses UpperCaseString in their project, they only need to install the support package and the test helper classes will pick up the configurator and successfully generate UpperCaseString types.