Unit testing continues
Unit testing continues; I've added tests for more than half the code now.
I'm actually only testing methods containing stored procedure calls since that is the current point of unit testing - I want to exercise every sproc to ensure that my latest unicode changes are working. Even without testing every method, it's a lot of work to add tests after the fact, just as I knew it would be.
But some neat stuff has come out of it, and not just in my new Context classes.
How about this property to use in those rare places where you want your real code to do something different when unit testing1:
public static bool IsUnitTesting
{
get
{
for (;;)
{
if (nUnitTesting == 0)
return false;
if (nUnitTesting == 1)
return true;
nUnitTesting = 0;
System.Diagnostics.StackTrace trace =
new System.Diagnostics.StackTrace();
for(int i=1;i<trace.FrameCount;i++)
{
System.Reflection.MethodBase methodBase =
trace.GetFrame(i).GetMethod();
if(methodBase.IsDefined(
typeof(NUnit.Framework.TestAttribute), true) ||
methodBase.IsDefined(
typeof(NUnit.Framework.SetUpAttribute), true) ||
methodBase.IsDefined(
typeof(NUnit.Framework.TearDownAttribute), true) ||
methodBase.IsDefined(
typeof(NUnit.Framework.TestFixtureAttribute), true) ||
methodBase.IsDefined(
typeof(NUnit.Framework.TestFixtureSetUpAttribute), true) ||
methodBase.IsDefined(
typeof(NUnit.Framework.TestFixtureTearDownAttribute), true))
{
nUnitTesting = 1;
break;
}
}
}
}
}
1 Code purists begone. I'm living in the real world here, and if I don't want notification emails sent during unit testing, then I'm going to add an:
if (Context.IsUnitTesting)
return;
Sue me.
Another interesting thing I did was in the Content assembly. There are a dozen or so classes in there, but most of them need a piece of content to work on and manipulate in some way. So I added code in the methods marked with [TestFixtureSetup] and [TestFixtureTearDown] to create and delete some content. Then I derived all my other unit test classes in that assembly from this initial one and Hey Presto they all get a piece of content to play with:
[TestFixture]
public class BaseContentTests
{
public Content content;
public Member member;
[TestFixtureSetUp]
public virtual void FixtureInit()
{
member = (Member)Context.Items["Member"];
if (!member.GetUserInfo("unittesting@unittesting.com"))
member.UserID = CreateMember();
Assert.IsTrue(member.UserID > 0);
content = (Content)Context.Items["Content"];
content.PageName = "UnitTestingTemporaryContent";
if (!content.IsReal)
content.PageID = CreateContent();
}
[TestFixtureTearDown]
public virtual void FixtureDispose()
{
Content.DeleteContent(content.PageID);
}
[Test]
public void TestContent()
{
Assert.IsTrue(content.IsReal);
}
}
[TestFixture]
public class ContentTests : BaseContentTests
{
// inherits setup/teardown from BaseContentTests
[Test]
public void TestComments()
{
Assert.IsNotNull(content.GetComments());
}
}
Then I can just override the setup/teardown methods in my derived classes if I want to add something else special - like my EventsTest class wants to work with content specialized as an event.
[TestFixtureSetUp]
public override void FixtureInit()
{
base.FixtureInit();
Events.MakeEvent(content.PageID);
content.Refresh(); // flush cache
Assert.IsTrue(content.IsEvent);
}
Nothing earth shattering, but posted in case it helps anyone - or prods them into writing some unit tests!