Giter VIP home page Giter VIP logo

exude's Introduction

#Exude

An extension to xUnit.net, providing support for test cases as First-Class, programmatic citizens.

First-Class Test Cases

Sometimes, writing Parameterized Tests using xUnit.net's [Theory] attribute can be troublesome, because the various options aren't compile-time safe, and it can be difficult to supply test case values that aren't constants (strings, integers, booleans, etc.)

Exude enables you to write test cases as First-Class Citizens by using the [FirstClassTests] attribute on a method that returns IEnumerable<ITestCase>:

[FirstClassTests]
public static IEnumerable<ITestCase> YieldFirstClassTests()
{
    yield return new TestCase(_ => Assert.Equal(1, 1));
    yield return new TestCase(_ => Assert.Equal(2, 2));
    yield return new TestCase(_ => Assert.Equal(3, 3));
}

In the above, very trivial example, three test cases are created and returned from the test method. When you run the tests, all three tests are executed and (in this case) pass:

3 passed, 0 failed, 0 skipped, took 0,06 seconds (xUnit.net 1.9.2 build 1705).

The flexible design of Exude gives you many opportunities for organising your test cases.

Generic Test Cases

If you need to access the test class that contains the test methods, you can use the TestCase<T> class, which also implements ITestCase. The object passed into each TestCase instance's Action is an instance of the containing test class. If you use TestCase<T>, you don't have to perform the cast yourself.

Here's an example which is difficult to write with xUnit.net's built-in data sources:

public void AParameterizedTest(DateTimeOffset x, DateTimeOffset y)
{
    Assert.True(x < y);
}

The problem is that DateTimeOffset is a complex datatype, which has no representation through a constant, so you can't use the [InlineData] attribute. With the built-in data sources from xUnit.net, you'll have to use either [ClassData] or [PropertyData], but it's easy to make mistakes with those, because they aren't type-safe, and have a weird API.

Instead, you can supply the data for the test method by simply invoking it:

[FirstClassTests]
public static TestCase<Scenario>[] RunAParameterizedTest()
{
    var testCases = new[] 
    {
        new 
        {
            x = new DateTimeOffset(2002, 10, 12, 18, 15, 0, TimeSpan.FromHours(1)),
            y = new DateTimeOffset(2007,  4, 21, 18, 15, 0, TimeSpan.FromHours(1))
        },
        new
        {
            x = new DateTimeOffset(1970, 11, 25, 16, 10, 0, TimeSpan.FromHours(1)),
            y = new DateTimeOffset(1972,  6,  6,  8,  5, 0, TimeSpan.FromHours(1))
        },
        new
        {
            x = new DateTimeOffset(2014, 3, 2, 17, 18, 45, TimeSpan.FromHours(1)),
            y = new DateTimeOffset(2014, 3, 2, 17, 18, 45, TimeSpan.FromHours(0))
        }
    };
    return testCases
        .Select(tc =>
            new TestCase<Scenario>(
                s => s.AParameterizedTest(tc.x, tc.y)))
        .ToArray();
}

In this example, notice that the Parameterized Test itself is an instance method, which doesn't have any attributes. Instead, the RunAParameterizedTest method creates three test cases, and converts them to an array of TestCase<Scenario> instances.

Each TestCase<Scenario> instance adapts an Action<Scenario>, which invokes the AParameterizedTest method in a type-safe manner.

Get Exude

Obviously, the source code is available here on GitHub, but you can download the compiled library with NuGet.

Versioning

Exude follows Semantic Versioning 2.0.0.

Credits

Exude was inspired by Mauricio Scheffer's blog post First-class tests in MbUnit.

exude's People

Contributors

moodmosaic avatar ploeh avatar sgryt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

lumirris

exude's Issues

Logo

Exude should have a logo, to be used as icon for its NuGet package, etc.

Support for parameterized TestCase methods

Would it make sense to support parameterized TestCase<T> methods where the values can be supplied by an external data source?

Such data sources could be:

  • Hard coded values
  • Arbitrary values generated by FsCheck
  • Constrained non-deterministic values generated by AutoFixture
  • A Composite of the above similar to CompositeDataAttribute for data theories

Each data source would plug into the FirstClassTestsAttribute in a similar fashion as with the xUnit.net data theories.

Minimum required xUnit.net version (in .nuspec file)

I am about to use Exude in a project named Idioms.FsCheck which uses xUnit 1.8.0.1549.

Exude is not published on NuGet Gallery (yet) so I setup a local package source to install it.

However, Grean.Exude.nuspec file doesn't currently include a dependency element (as described here) to also pull and install xUnit.


On my machine all tests passed with xUnit 1.8.0.1549, so I was wondering if it makes sense to require >= xUnit 1.8.0.1549 in the .nuspec as the lowest common denominator.

Support for static classes

The support for Action delegates in TestCase class (#16, #17) now allows the following syntax in static classes:

public static class Module
{
    [FirstClassTests]
    public static IEnumerable<ITestCase> YieldFirstClassTestsInModule()
    {
        yield return new TestCase(() => Assert.Equal(1, 1));
        yield return new TestCase(() => Assert.Equal(2, 2));
        yield return new TestCase(() => Assert.Equal(3, 3));
    }
}

At run time an exception is thrown because internally Action is adapted to Action<object>.

That's because the FirstClassTestsAttribute attempts to create an instance of the object's type (a behaviour which could be branched now).

In this case, the TestCase class should also use a different ITestCommand command instance, as suggested by @ploeh in the last paragraph of #16.

TestCase adapting Action

The TestCase class currently adapts an Action<object>. The object supplied to the delegate is an instance of the test class that contains the test method adorned with the [FirstClassTests] attribute.

However, in some cases, the test writer may not care about this instance, so it would be appropriate that he or she could also supply an Action:

yield return new TestCase(() => Assert.Equal(1, 1));

When that's the case, perhaps TestCase.ConvertToTestCommand should return an ITestCommand instance (which could still be FirstClassCommand) with ShouldCreateInstance returning false instead of true.

I want to use this package with latest XUnit from NuGet.

It is good package, I tried, it works with XUnit 1.9.2 but not works with 2.0.0 or 2.1.0. I want to control tests output by using Xunit.Abstractions.ITestOutputHelper from xunit.abstractions dll. But it seems that type missing in xunit version 1.9.2 dll.

Upgrade to xUnit.net 2

Now that xUnit.net 2 is out, we should consider upgrading Exude to xUnit.net 2.

As far as I can tell from the NuGet download statistics, it doesn't look like a lot of people are using Exude. Version 0.2.1 has 345 downloads as I'm writing this. Additionally, that version is more than a year old, so if anyone uses it for serious work, we must assume that that version works for them.

Since Semantic Versioning allows breaking changes when the major version is 0, we can upgrade to xUnit.net 2 without worrying too much about compatibility. Per the above argument, people already on Exude 0.2.1 can stay on that version if they're unable to upgrade to xUnit.net 2.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.