I always thought that the NUnit test runners and the test assemblies need to reference the same NUnit.Framework version. I wanted to be able to run my test assemblies with the newest GUI runner (currently 2.5.3). Ok so all I need to do is to reference both NUnit versions the newest one and the official for the current project. There is a nice article form Kent Bogart online how to reference the same assembly multiple times with different versions. The magic works by referencing one NUnit assembly with an alias which does prefix all types inside it. Then I could decorate my tests with the TestFixture and Test attribute from both NUnit versions and everything worked fine except that this was ugly. After playing a little bit around to make it simpler I found that I did not need to reference both NUnit.Framework assemblies. The test runners do not require the TestFixture and Test attribute in their specific version. That is really neat since the test runners are instructed by attributes what to do in a declarative way there is really no need to tie the runners to a specific version. At its core NUnit has this little method hidden to find matching TestFixtures and Tests public bool CanBuildFrom(Type type)
{
if (!(!type.IsAbstract || type.IsSealed))
{
return false;
}
return (((Reflect.HasAttribute(type, "NUnit.Framework.TestFixtureAttribute", true) || Reflect.HasMethodWithAttribute(type, "NUnit.Framework.TestAttribute" , true)) || Reflect.HasMethodWithAttribute(type, "NUnit.Framework.TestCaseAttribute" , true)) || Reflect.HasMethodWithAttribute(type, "NUnit.Framework.TheoryAttribute" , true));
}That is versioning and backwards compatibility at its best. I tell NUnit what to do by decorating my tests classes with NUnit Attributes and the runner executes my intent without the need to bind me to a specific version. The contract between NUnit versions is actually a bit more complex (think of AssertExceptions) but this is also handled nicely by using not the concrete type but simply to check for the catched exception type by string. Read more: Alois Kraus
{
if (!(!type.IsAbstract || type.IsSealed))
{
return false;
}
return (((Reflect.HasAttribute(type, "NUnit.Framework.TestFixtureAttribute", true) || Reflect.HasMethodWithAttribute(type, "NUnit.Framework.TestAttribute" , true)) || Reflect.HasMethodWithAttribute(type, "NUnit.Framework.TestCaseAttribute" , true)) || Reflect.HasMethodWithAttribute(type, "NUnit.Framework.TheoryAttribute" , true));
}That is versioning and backwards compatibility at its best. I tell NUnit what to do by decorating my tests classes with NUnit Attributes and the runner executes my intent without the need to bind me to a specific version. The contract between NUnit versions is actually a bit more complex (think of AssertExceptions) but this is also handled nicely by using not the concrete type but simply to check for the catched exception type by string. Read more: Alois Kraus
0 comments:
Post a Comment