This question concerns a general unit test technique with a potentially very useful wide range of applicable scenarios. But it is easier to understand with an example to illustr
Using VS 2010 I am not seeing the same behavior as you are. When I copied your 2 classes into a test project and compiled it I got the output:
UTA004: Illegal use of attribute...The TestMethodAttribute can be
defined only inside a class marked with the TestClass attribute
So I marked EqualsFixutureBase:
[TestClass]
public abstract class EqualsFixtureBase<T>
{
...
}
Now it compiles without warning and when I select run tests for ExampleOfAnEqualsTestFixture it runs Foo and all 5 of the inherited equals tests. Also when I copy the ExampleOfAnEqualsTestFixture and use it for int and run the tests for the solution I see all 5 inherited tests running (and passing) for the example string class and the example int class.
Are you doing something in addition to your example which might be causing your problem?
The TestClassAttribute allows you to put methods in the abstract base. The IgnoreAttribute excludes the base class from the list of tests. Without the IgnoreAttribute attribute methods within base are executed for both the base class and in subclasses marked with the TestClassAttribute, .
[TestClass][Ignore]
public abstract class EqualsFixtureBase<T>
{
....
Out of the box, it looks like unit test inheritance only works if the base test class is in the same assembly as the derived classes. For me, this usually defeats the purpose of having the base class. I, too, wonder why there isn't more posted about this on blogs, and if I might be missing something.
You might be able to work around the problem by linking the base class into every project where you want to use it. Maybe mark it as internal so the multiple copies don't interfere with each other.
There's also the TestClassExtensionAttribute
that you can extend to hook into the test execution engine. I tried using it to reflect over the test classes and load the base class's tests, but a lot of the classes are undocumented, and I couldn't get it to work.