Introduction
Many of us know we should be using test first development, however it is hard to break old habits. I have to admit, I started to solve this particular problem I’m going to use an an example first without test first, then realized what a pickle I was going to be in proving to myself it worked. So, I thought, why not blog my experience as I do it. Using Visual Studio unit testing makes this pretty easy.
The Problem
I’m currently building a multithreaded email processor and part of that process is I have to figure out, for any given use whether they are supposed to have there email server checked. So, the way I look at it, I need a method that takes in the following parameter.
- Now – This is actually todays date and time in UTC, but since this method need to be tested, I’m going to pass in now rather just use it directly.
- LastActivityOfUserDateTime – This is the last time we saw any activity for this user.
- LastEmailSession – This is when the email session was last run (server check).
- DefaultSecondsForLastActivityTreshold – This is used to determine weather the user last activity makes that user considered active or inactive. That is, say this is 60 seconds. Then, if the user has been active in the last 60 seconds, then this user is considered active.
- DefaultSecondsBetweenEmailRetryOutsideThreshold – If the user is not active (as defined by DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait before we should try and contact the users email server again.
- DefaultSecondsBetweenEmailRetryInsideThreshold – If the user is active (as defined by DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait before we should try and contact the users email server again.
Given these 4 parameters, we should write a method that returns a Boolean indicating weather the mail server needs to be rechecked for a given user.
The Method To Test
So, let’s write a method signature. We will use this in our real project, then write some tests to see if it works correctly. We have not written the actual method yet, we are just defining what it does, then first, very important, writing the tests to prove it will work. This way, as we add all the corner cases, we can keep making sure the original cases we programmed have not broken.
So, here is how I see the class definition:
public bool IsUserReadyToContactEmailServer(DateTime currentDateTime, DateTime lastActivityOfUserDateTime, DateTime lastEmailSession, int defaultSecondsForLastActivityTreshold, int defaultSecondsBetweenEmailRetryOutsideThreshold, int defaultSecondsBetweenEmailRetryInsideThreshold) { bool activeUser = IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); int thresholdForRetrySeconds = activeUser ? defaultSecondsBetweenEmailRetryInsideThreshold : defaultSecondsBetweenEmailRetryOutsideThreshold;<span class="rem">// this has to be a double because could be huge number if last email send very long ago</span> <span class="kwrd">double</span> timeSinceLastEmailSessionSeconds = currentDateTime.Subtract(lastEmailSession).TotalSeconds; <span class="kwrd">return</span> timeSinceLastEmailSessionSeconds > thresholdForRetrySeconds; }</pre>
Creating a Test Project In Visual Studio 2011 Preview
Now that we have our method we want to test, let’s create a test project. This is very straight forward. We first just say “File/New Project” then choose “Unit Test Project”.
I’m going to simply create a method called TestMethodIsUserReadyToContactEmailServer().
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;namespace AEWeb.Tests { [TestClass] public class UnitTest1 { [TestMethod] public void TestMethodIsUserReadyToContactEmailServer() { } } }
Now, we need to add some guts. There is an automated way to create the actual test stubs, but at the moment I can’t seem to find it. In this case, we really just need to test a bunch of corner cases so let’s code the tests up. Below are the tests I’ve come up with including comments that make them self explanatory.
So, as I’m creating my tests, I realize I need to create an extra class to help this one. That is specifically, I need to add a method that simply determines if the user is currently active. I’m going to call that IsCurrentlyActive and have it take three paramaters. currentDateTime, DefaultSecondsForLastActivityThreshold and usersLastActivityDate. I realized this because solving the full problem of figuring out if the user is ready to sync email is to complex in one step.
If I were developing this without unit tests, I would have figured the same thing out, but then as I built it, I would not be verifying it’s correctness with testing.
Creating Stub Classes
So, my new class I want to test will be this:
/// <summary> /// This really just a supporting method for the above IsUserReadyToContactEmailServer call /// </summary> /// <param name="currentDateTime">Current datetime (for testing can be anything)</param> /// <param name="usersLastActivityDate">time user was last seen </param> /// <param name="defaultSecondsForLastActivityTreshold">our definition of what makes a user currently active</param> /// <returns></returns> public bool IsUserCurrentlyActive(DateTime currentDateTime, DateTime usersLastActivityDate, int defaultSecondsForLastActivityTreshold ) {<span class="kwrd">return</span> <span class="kwrd">true</span>; }</pre>
The Unit Tests Themselves
So, now is time to actually write the tests. I’m not going to explain here all the mechanics of testing. I assume you understand the basics are you right calls to methods, then make assertions for correctness. If the assertion is wrong, then print that message and of course the test fails.
So, Here are my test cases for just the helper method (IsUserCurrentlyActive).
using System; using AELib; using Microsoft.VisualStudio.TestTools.UnitTesting;namespace AEWeb.Tests { [TestClass] public class UnitTestEmailReadyCheck {
[TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestRecentActivity() { { <span class="rem">// a long time ago</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 2, 1, 12, 0, 0); <span class="rem">// last activity was a month ago, 2/1/2012 at noon</span> <span class="rem">// threshhold for calling a user active</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60*15; <span class="rem">// let's call this 15 minute threshhold</span> <span class="kwrd">bool</span> isActive = <span class="kwrd">new</span> MailServerReadyCheck(). IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); Assert.IsFalse(isActive, <span class="str">"User Should Be Inactive because last activity was 1 month ago and threshhold is 15 minutes"</span>); } } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestNoRecentActivity() { <span class="rem">// a just inside threshold</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 11, 55, 0); <span class="rem">// last activity was 5 minutes before noon on 2/1/2012</span> <span class="rem">// threshhold for calling a user active</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60*15; <span class="rem">// let's call this 15 minute threshhold</span> <span class="kwrd">bool</span> isActive = <span class="kwrd">new</span> MailServerReadyCheck(). IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); Assert.IsTrue(isActive, <span class="str">"User Should Be active because last activity was 5 minutes ago and threshhold is 15 minutes"</span>); } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestCurrentDateBehindActivity() { <span class="rem">// impossible cause of last activity being after current time. just need to</span> <span class="rem">// make sure it returns true and does not crash</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 18, 0, 0); <span class="rem">// last activity was 5 minutes after noon on 2/1/2012</span> <span class="rem">// threshhold for calling a user active</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60*15; <span class="rem">// let's call this 15 minute threshhold</span> <span class="kwrd">bool</span> isActive = <span class="kwrd">new</span> MailServerReadyCheck(). IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); Assert.IsTrue(isActive, <span class="str">"User Should Be active because last activity was 5 minutes after current time"</span>); } }
}
Then, I write the actual method:
/// <summary> /// This really just a supporting method for the above IsUserReadyToContactEmailServer call /// </summary> /// <param name="currentDateTime">Current datetime (for testing can be anything)</param> /// <param name="usersLastActivityDate">time user was last seen </param> /// <param name="defaultSecondsForLastActivityTreshold">our definition of what makes a user currently active</param> /// <returns></returns> public bool IsUserCurrentlyActive(DateTime currentDateTime, DateTime usersLastActivityDate, int defaultSecondsForLastActivityTreshold ) { int secondsSinceLastActivity = Convert.ToInt32(currentDateTime.Subtract(usersLastActivityDate).TotalSeconds); bool activeStatus = defaultSecondsForLastActivityTreshold > secondsSinceLastActivity; return activeStatus; }And finally, run the test (skipping a little debugging to make them all work)
Presto!
For completeness, I’m pasting the full unit test for the other main class I’m interested in testing below (as well as the class itself), however I won’t go into all the details. Everything is basically the same, just more of it
Conclusions and Observations
Turns out, this was quite a bit of work to generate all these tests. At first pass, I can hear someone saying it seems like a lot to do just for two fairly simple methods. My answer is that I struggled trying to get it right until I finally decided to write the tests. Now, I’m confident it works correctly. What is more, if there is a bug in my algorithm, or something else comes up I need to include (which is very likely) I now have a great way to prove to myself (and others) that my class works. Also, this serves as great documentation for what expectations are for this very important function.
Appendex – Full Unit Test And Class Source
using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace AELib { public class MailServerReadyCheck { /// <summary> /// /// </summary> /// <param name=“currentDateTime”>This is actually todays date and time in UTC, but since /// this method need to be tested, I’m going to pass in now rather just use it directly</param> /// <param name=“lastActivityOfUserDateTime”> This is used to determine weather the user last activity /// makes that user considered active or inactive. That is, say this is 60 seconds. /// Then, if the user has been active in the last 60 seconds, then this user is considered active.</param> /// <param name=“lastEmailSession”>When the last email completed for this user</param> /// <param name=“defaultSecondsForLastActivityTreshold”>This is used to determine weather the user last activity makes that /// user considered active or inactive. That is, say this is 60 seconds. Then, if the user has /// been active in the last 60 seconds, then this user is considered active.</param> /// <param name=“defaultSecondsBetweenEmailRetryOutsideThreshold”> If the user is not active (as defined by /// DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait before /// we should try and contact the users email server again.</param> /// <param name=“defaultSecondsBetweenEmailRetryInsideThreshold”>If the user is active (as defined by /// DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait /// before we should try and contact the users email server again.</param> /// <returns>returns a boolean indicating weather the mail server needs to be rechecked for a given user.</returns> public bool IsUserReadyToContactEmailServer(DateTime currentDateTime, DateTime lastActivityOfUserDateTime, DateTime lastEmailSession, int defaultSecondsForLastActivityTreshold, int defaultSecondsBetweenEmailRetryOutsideThreshold, int defaultSecondsBetweenEmailRetryInsideThreshold) { bool activeUser = IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); int thresholdForRetrySeconds = activeUser ? defaultSecondsBetweenEmailRetryInsideThreshold : defaultSecondsBetweenEmailRetryOutsideThreshold;
<span class="rem">// this has to be a double because could be huge number if last email send very long ago</span> <span class="kwrd">double</span> timeSinceLastEmailSessionSeconds = currentDateTime.Subtract(lastEmailSession).TotalSeconds; <span class="kwrd">return</span> timeSinceLastEmailSessionSeconds > thresholdForRetrySeconds; } <span class="rem">/// <summary></span> <span class="rem">/// This really just a supporting method for the above IsUserReadyToContactEmailServer call</span> <span class="rem">/// </summary></span> <span class="rem">/// <param name="currentDateTime">Current datetime (for testing can be anything)</param></span> <span class="rem">/// <param name="usersLastActivityDate">time user was last seen </param></span> <span class="rem">/// <param name="defaultSecondsForLastActivityTreshold">our definition of what makes a user currently active</param></span> <span class="rem">/// <returns></returns></span> <span class="kwrd">public</span> <span class="kwrd">bool</span> IsUserCurrentlyActive(DateTime currentDateTime, DateTime usersLastActivityDate, <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold ) { <span class="kwrd">int</span> secondsSinceLastActivity = Convert.ToInt32(currentDateTime.Subtract(usersLastActivityDate).TotalSeconds); <span class="kwrd">bool</span> activeStatus = defaultSecondsForLastActivityTreshold > secondsSinceLastActivity; <span class="kwrd">return</span> activeStatus; } }
}
And the tests…
using System; using AELib; using Microsoft.VisualStudio.TestTools.UnitTesting;namespace AEWeb.Tests { [TestClass] public class UnitTestEmailReadyCheck {
<span class="rem">///////////////////// IsUserCurrentlyActive follows</span> [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestRecentActivity() { { <span class="rem">// a long time ago</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 2, 1, 12, 0, 0); <span class="rem">// last activity was a month ago, 2/1/2012 at noon</span> <span class="rem">// threshhold for calling a user active</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60*15; <span class="rem">// let's call this 15 minute threshhold</span> <span class="kwrd">bool</span> isActive = <span class="kwrd">new</span> MailServerReadyCheck(). IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); Assert.IsFalse(isActive, <span class="str">"User Should Be Inactive because last activity was 1 month ago and threshhold is 15 minutes"</span>); } } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestNoRecentActivity() { <span class="rem">// a just inside threshold</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 11, 55, 0); <span class="rem">// last activity was 5 minutes before noon on 2/1/2012</span> <span class="rem">// threshhold for calling a user active</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60*15; <span class="rem">// let's call this 15 minute threshhold</span> <span class="kwrd">bool</span> isActive = <span class="kwrd">new</span> MailServerReadyCheck(). IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); Assert.IsTrue(isActive, <span class="str">"User Should Be active because last activity was 5 minutes ago and threshhold is 15 minutes"</span>); } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestCurrentDateBehindActivity() { <span class="rem">// impossible cause of last activity being after current time. just need to</span> <span class="rem">// make sure it returns true and does not crash</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 18, 0, 0); <span class="rem">// last activity was 5 minutes after noon on 2/1/2012</span> <span class="rem">// threshhold for calling a user active</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60*15; <span class="rem">// let's call this 15 minute threshhold</span> <span class="kwrd">bool</span> isActive = <span class="kwrd">new</span> MailServerReadyCheck(). IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime, defaultSecondsForLastActivityTreshold); Assert.IsTrue(isActive, <span class="str">"User Should Be active because last activity was 5 minutes after current time"</span>); } <span class="rem">///////////////////// IsUserReadyToContactEmailServer follows</span> [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestIsUserReadyToContactEmailServerLongTimeAgoUserInActive() { <span class="rem">// let's use these parameters for every test</span> <span class="rem">// let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60 * 30; <span class="rem">// if active user, check email every 2 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2; <span class="rem">// if inactive user, check email every 20 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20; <span class="rem">// user checked email 5 hours ago and email has not been run for 3 hours</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastEmailSessionDateTime = <span class="kwrd">new</span> DateTime(2011,3,1,2, 0, 0); <span class="rem">// email session 2am of 1 year ago (very long ago)</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2011, 3, 1, 7, 0, 0); <span class="rem">// user checked email at 7am a year ago</span> <span class="kwrd">bool</span> emailSessionNeeded = <span class="kwrd">new</span> MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime, lastActivityOfUserDateTime,lastEmailSessionDateTime,defaultSecondsForLastActivityTreshold, defaultSecondsBetweenEmailRetryOutsideThreshold, defaultSecondsBetweenEmailRetryInsideThreshold); Assert.IsTrue(emailSessionNeeded, <span class="str">"user checked email 5 hours ago and email has not been run for 3 hours. Should have needed email session"</span>); } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestIsUserReadyToContactEmailServerLongTimeAgoUserActive() { <span class="rem">// let's use these parameters for every test</span> <span class="rem">// let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60 * 30; <span class="rem">// if active user, check email every 2 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2; <span class="rem">// if inactive user, check email every 20 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20; <span class="rem">// user checked email 1 minute ago and email has not been run for 3 hours</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastEmailSessionDateTime = <span class="kwrd">new</span> DateTime(2011, 3, 1, 2, 0, 0); <span class="rem">// email session 2am of 1 year ago (very long ago)</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 11, 59, 0); <span class="rem">// user checked email 1 minute ago</span> <span class="kwrd">bool</span> emailSessionNeeded = <span class="kwrd">new</span> MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime, lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold, defaultSecondsBetweenEmailRetryOutsideThreshold, defaultSecondsBetweenEmailRetryInsideThreshold); Assert.IsTrue(emailSessionNeeded, <span class="str">"user checked email 1 minute ago and email not been run for 1 year. should have run email again"</span>); } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestIsUserReadyToContactEmailServerRecentlyUserActive() { <span class="rem">// let's use these parameters for every test</span> <span class="rem">// let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60 * 30; <span class="rem">// if active user, check email every 2 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2; <span class="rem">// if inactive user, check email every 20 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20; <span class="rem">// user checked email 1 minute ago and email has not been run for 3 hours</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastEmailSessionDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 11, 50, 0); <span class="rem">// email session 10 minutes ago</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 11, 59, 0); <span class="rem">// user checked email 1 minute ago</span> <span class="kwrd">bool</span> emailSessionNeeded = <span class="kwrd">new</span> MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime, lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold, defaultSecondsBetweenEmailRetryOutsideThreshold, defaultSecondsBetweenEmailRetryInsideThreshold); Assert.IsTrue(emailSessionNeeded, <span class="str">"active user, email checked 10 minutes ago but since active should check again"</span>); } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestIsUserReadyToContactEmailServerRecentlyUserInActive() { <span class="rem">// let's use these parameters for every test</span> <span class="rem">// let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60 * 30; <span class="rem">// if active user, check email every 2 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2; <span class="rem">// if inactive user, check email every 20 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20; <span class="rem">// user checked email 1 minute ago and email has not been run for 3 hours</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastEmailSessionDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 11, 50, 0); <span class="rem">// email session 10 minutes ago</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2011, 3, 1, 11, 59, 0); <span class="rem">// user checked email 1 year ago</span> <span class="kwrd">bool</span> emailSessionNeeded = <span class="kwrd">new</span> MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime, lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold, defaultSecondsBetweenEmailRetryOutsideThreshold, defaultSecondsBetweenEmailRetryInsideThreshold); Assert.IsFalse(emailSessionNeeded, <span class="str">"inactive user, but email checked very recently so should not be checking again"</span>); } [TestMethod] <span class="kwrd">public</span> <span class="kwrd">void</span> UnitTestIsUserReadyToContactEmailServerEmailLastSession10MinutesagoActive() { <span class="rem">// let's use these parameters for every test</span> <span class="rem">// let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsForLastActivityTreshold = 60 * 30; <span class="rem">// if active user, check email every 2 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2; <span class="rem">// if inactive user, check email every 20 minutes</span> <span class="kwrd">const</span> <span class="kwrd">int</span> defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20; <span class="rem">// user checked email 1 minute ago and email has not been run for 3 hours</span> var currentDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 12, 0, 0); <span class="rem">// assume current time is 3/1/2012 at noon</span> var lastEmailSessionDateTime = <span class="kwrd">new</span> DateTime(2012, 3, 1, 1, 11, 50); <span class="rem">// email session 10 minutes ago</span> var lastActivityOfUserDateTime = <span class="kwrd">new</span> DateTime(2011, 3, 1, 11, 59, 0); <span class="rem">// user checked email 5 minutes ago</span> <span class="kwrd">bool</span> emailSessionNeeded = <span class="kwrd">new</span> MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime, lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold, defaultSecondsBetweenEmailRetryOutsideThreshold, defaultSecondsBetweenEmailRetryInsideThreshold); Assert.IsTrue(emailSessionNeeded, <span class="str">"active user, but email checked very recently so should be checking again"</span>); } }
}
And the results of all tests running
And, if you are still reading, I’ve got 100% of these two methods covered from these unit tests using Code Coverage.