Public bug reported:

Ran across this interesting presentation:

    http://www.infoq.com/presentations/integration-tests-scam

It suggested having "Contract" and "Collaboration" tests.  "Contract"
tests are tests that validate an interface implementation, thus
enforcing (and checking) all "assumptions" that mock objects may make
use of.

For example, a Collaboration test may make the assumption that for an
ICollection<T> implementation, if you call ICollection<T>.Add() then
ICollection<T>.Count will be incremented.

The Contract test would thus create an ICollection<T> implementation and
actually assert that if you call ICollection<T>.Add(T) then
ICollection<T>.Count will be incremented.

Of course, the "obvious" way to do this would be to use abstract classes
for the tests themselves:

    [TestFixture]
    public abstract class CollectionContract {
        protected abstract ICollection<T> CreateCollection();

        [Test]
        public void DoesAddIncrementCount()
        {
            var list = CreateCollection<int>();
            var c = list.Count;
            list.Add(1);
            Assert.AreEqual(c+1, list.Count);
        }
    }

Of course, an abstract type isn't very useful, so for EACH
implementation we'd provide an additional test fixture:

    [TestFixture]
    public class ListCollectionContract : CollectionContract {
        protected override ICollection<T> CreateCollection<T>()
        {
            return new List<T>();
        }
    }

All well and good...except it doesn't work (in NUnit 2.4.8; haven't
tested other versions).

The intention here is that the CollectionContract tests will be skipped
(abstract type can't be instantiated), BUT that ALL of the
CollectionContract tests will be executed AS PART OF
ListCollectionContract (and ALL other CollectionContract subclasses).

This allows us to trivially test new interface implementations (in the
above case, write one new class + one new method to get all
ICollection<T> tests contained within CollectionContract).

The only alternative (that I can currently think of) is for
ListCollectionContract to duplicate all of the test declarations within
CollectionContract, and delegating them to an internal instance.  This
makes test maintenance annoying (and less flexible than what it could
be).

** Affects: nunit-3.0
     Importance: Undecided
         Status: New

-- 
Please support abstract base types
https://bugs.launchpad.net/bugs/462896
You received this bug notification because you are a member of NUnit
Core Developers, which is the registrant for NUnit Framework.

Status in NUnit Test Framework: New

Bug description:
Ran across this interesting presentation:

    http://www.infoq.com/presentations/integration-tests-scam

It suggested having "Contract" and "Collaboration" tests.  "Contract" tests are 
tests that validate an interface implementation, thus enforcing (and checking) 
all "assumptions" that mock objects may make use of.

For example, a Collaboration test may make the assumption that for an 
ICollection<T> implementation, if you call ICollection<T>.Add() then 
ICollection<T>.Count will be incremented.

The Contract test would thus create an ICollection<T> implementation and 
actually assert that if you call ICollection<T>.Add(T) then 
ICollection<T>.Count will be incremented.

Of course, the "obvious" way to do this would be to use abstract classes for 
the tests themselves:

    [TestFixture]
    public abstract class CollectionContract {
        protected abstract ICollection<T> CreateCollection();

        [Test]
        public void DoesAddIncrementCount()
        {
            var list = CreateCollection<int>();
            var c = list.Count;
            list.Add(1);
            Assert.AreEqual(c+1, list.Count);
        }
    }

Of course, an abstract type isn't very useful, so for EACH implementation we'd 
provide an additional test fixture:

    [TestFixture]
    public class ListCollectionContract : CollectionContract {
        protected override ICollection<T> CreateCollection<T>()
        {
            return new List<T>();
        }
    }

All well and good...except it doesn't work (in NUnit 2.4.8; haven't tested 
other versions).

The intention here is that the CollectionContract tests will be skipped 
(abstract type can't be instantiated), BUT that ALL of the CollectionContract 
tests will be executed AS PART OF ListCollectionContract (and ALL other 
CollectionContract subclasses).

This allows us to trivially test new interface implementations (in the above 
case, write one new class + one new method to get all ICollection<T> tests 
contained within CollectionContract).

The only alternative (that I can currently think of) is for 
ListCollectionContract to duplicate all of the test declarations within 
CollectionContract, and delegating them to an internal instance.  This makes 
test maintenance annoying (and less flexible than what it could be).

_______________________________________________
Mailing list: https://launchpad.net/~nunit-core
Post to     : nunit-core@lists.launchpad.net
Unsubscribe : https://launchpad.net/~nunit-core
More help   : https://help.launchpad.net/ListHelp

Reply via email to