Hei Hei Grensesnitt

So just what the hell is grensesnitt anyways?

Let’s start with the name. Grensesnitt means interface in Norwegian. The direct translation however would be “boundary cut” which is exactly what grensesnitt does. Grensesnitt is an nunit plugin I wrote a while ago while in Norway. It allows me to write tests in a style that I have been writing them in for a few years now while removing the pain of doing so. You can grab grensesnitt on mygithub , to install just copy it into the addins folder of your particular nunit installation. If you want to just test it out, its installed in the nunit installation included in the /lib folder (you can run the tests in the sample project).

Many of our tests should not be written against classes but should instead be written against interfaces. They represent the invariants of the given interface. Consider as an example IList, I don’t care how you implement IList but if I call add and you return to me without an error, count needs to increment and I need to be able to get the item back. If you cannot do this in my eyes you are not really an IList as I cannot use you. Seriously, can you imagine someone passing you an IList that when you added stuff to it, you couldn’t get it back out? Right now we tend to have all of these assumptions implicitly, grensesnitt allows you to make them explicit.

nunit allows you to do some things like this using Generic Test Fixtures such as

[TestFixture(typeof(ArrayList))]
[TestFixture(typeof(List<int>))]
public class IList_Tests<TList> where TList : IList, new()

but there are some drawbacks to this. First I need to actually add the type to the test manually, what if I forget? manual steps suck. The second is that the test assembly needs references to all of the implementers which can be problematic.

With grensesnitt:

public interface ICanAdd {
    int Add(int i, int j);
}

[InterfaceSpecification]
public class ICanAddTests : AppliesTo<ICanAdd>{

    [Test]
    public void can_add_two_numbers() {
          Assert.AreEqual(5, sut.Add(2,3));
    }
}

This would be the code that you would write. Grensesnitt will then automatically find any class that implements ICanAdd and these tests will be run against it. This automation of the process is very important. Said simply as soon as you implement ICanAdd you have N failing tests. Grensesnitt is capable of running either explicit interfaces or class interfaces (i.e. inheritance)

When you run grensesnitt, it will automatically find these implementers and you will see your tests show up as a test suite per implementer. As you can see in the image below. Adder1, Adder2, Adder3 etc are all implementers of the adder interface.

image

You can also control where grensenitt searches for implementers by using the [assembly: GrensesnittSearchLocation("../plugins")] attribute on your test assembly. By default it will search in all the assemblies in the directory.

Grensesnitt also plays nice with other nUnit plugins. As an example here is a test (shown above in runner) that also uses TestCase for parameterized tests.

    [InterfaceSpecification]
    public class WithOtherPlugins : AppliesToAll<ICanAdd>
    {
        [TestCase(1, 2, 3)]
        [TestCase(-1, 2, 1)]
        [TestCase(0, 0, 0)]
        public void CanAddOrSomething(int x, int y, int r)
        {
            Assert.AreEqual(subject.Add(x, y), r);
        }
       
        [TestCase(1, 2, Result = 3)]
        [TestCase(-1, 2, Result = 1)]
        [TestCase(0, 0, Result = 0)]
        public int CannAddOrSomethingWithReturn(int x, int y) {
            return subject.Add(x, y);
        }
    }

Now ask yourself, how many times have you implemented an interface out of some library, then passed your implementer in and gotten some really weird bug happening 65 levels down the call stack in their code? Its because of something in your implementer but you don’t know what? Grensesnitt is a way to allow a framework developer to document their needs. They release the grensesnitt tests with their code. When you implement their interface, their context specifications get run automatically against you (it’s a form of documentation), and it works very very well with BDD style tests.

Grensesnitt is also fairly opinionated and its hard to do bad things. Grensesnitt does not as an example require default constructors on objects. Instead there is a hookable object creator. GrensesnittObjectLocator that you can hook all or specific calls to a factory method. Its like this by design, if your test depends on something being passed to a constructor eg: if I pass 5 to the constructor this property should return 5 that is *not* an interface test, it is a class test.

Anyways it makes this testing style easier for me so maybe it will benefit others.

Special thanks to Svein, Morten, and Einar who all helped with the creation of grensesnitt. Oh and nevermind all the dead bodies in the plugin itself (copy/pasted private code from nunit with internal calls replaced with reflections) those were just casualties from fighting the dragons that be in nUnit.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

7 Responses to Hei Hei Grensesnitt

  1. Pingback: mookid on code » Contract testing with NUnit

  2. Jonathan says:

    This is good stuff Greg, thanks for sharing. I came across a need for something similar last year when publishing an SPI for a Java library. When I get a chance, I’ll see if I can come up with a decent Java variation of grensesnitt.

  3. Greg says:

    Scooletz if you would need different constructed objects for different tests those tests should not be interface tests they should be class tests. The locator allows you to specify to always call a given factory for a given type or to hook all creations to your own method (eg: container).

  4. Scooletz says:

    It’s been a while since your last post Greg;-) I’ve got one question about GrensesnittObjectLocator. Does it uses some kind of conventions, or configuration to resolve how create objects injected in constructor? I can imagine tests, where in one case I pass one stub to the constructor, while when running other, another, both implementing the same interface.

  5. Greg says:

    Yes similar, I believe the big difference is it automatically finds anything that the specification can map to.

  6. Paco says:

    This [InterfaceSpecification] looks like the same as [Behavior] in mspec.

  7. Chris Martin says:

    Excellent. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>