Question

I want to reuse generic tests, but how can I get generic test data?


I wrote my own IReadOnlyCollection<T> interface, and wrote some classes that use it.

Since the methods and properties (e.g. Contains, CopyTo) of that interface should always work exactly the same regardless of the class that implements it, I want to write generic tests that I can apply to any implementation. Using the approach suggested in this post, I now have the following:

// Tests that must work for any type T:
public abstract class IReadOnlyCollectionTests<T>
{
    protected abstract IReadOnlyCollection<T> CreateInstance(params T[] data);

    [Test]
    public void Contains_GivenExistingValue_ReturnsTrue()
    {
        // Given
        T[] data;   // <-- Get some data?
        T value = data[1];
        var sut = CreateInstance(data);

        // When
        bool result = sut.Contains(value);

        // Then
        Assert.IsTrue(result);
    }

    // 40 more such tests...
}

Now I need some data to test with. Type T may be boolean, or string, or anything. How do I get some generic data in there that works for any type T?


By the way: I'll run this generic test by deriving a test class for each implementation, like this one for my BitArray implementation (a collection of booleans):

[TestFixture]
public class BitArrayROC : IReadOnlyCollectionTests<bool>
{
    protected override IReadOnlyCollection<bool> CreateInstance(params bool[] data)
    {
        return new BitArray(data);
    }
}

Similar to BitArray, I have a StringCollection class (among others) for which I want to test the IReadOnlyCollection<T> implementation.

Was it helpful?

Solution

Create data provider which return data by parameter, and let parameter be the type of the data you need. You could set the type of data you need in implementation of your generic test.

OTHER TIPS

You can create abstract method which returns data in IReadOnlyCollection<T> class. Then in derived classes you can write type-specific implementations.

See example:

public abstract class IReadOnlyCollectionTests<T>
{
    protected abstract IReadOnlyCollection<T> CreateInstance(params T[] data);

    protected abstract T[] GetData();

    [Test]
    public void Contains_GivenExistingValue_ReturnsTrue()
    {
        // Given
        T[] data = GetData();
        T value = data[1];
        var sut = CreateInstance(data);

        ...
    }
}

[TestFixture]
public class BitArrayROC : IReadOnlyCollectionTests<bool>
{
    protected override bool[] GetData()
    {
        return new[] { true, false };
    }

    ...
}

Actually, the idea is the same as you've implemented for collection instance creation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top