patterncsharpMinor
Unit Tests for getting the first Monday of the month
Viewed 0 times
thetestsgettingfirstformonthmondayunit
Problem
I have an application that runs hourly, and I want to use it to also send an email at the start of the day of the first Monday of the month. I searched and found information to help me code what I needed, and all my tests pass, but I want to make sure that I am testing for all edge cases and that I am also being a good little programmer and writing good code.
I have the application being called from a task scheduler on the hour, sometimes some of the code doesn't get called right on the hour.
My Code for checking the date:
I hate to admit this, but I am pretty much a beginner when it comes to Unit Tests, and I think that my life would be much easier with them, so I want to make sure that I am starting out with good habits.
Some of these tests were written before and after reading some articles about naming tests, hence the reason for the bad naming consistency
So here are my tests:
```
[TestMethod]
public void CheckSendNewEvent_Test()
{
var program = new Program();
var checker = program.CheckSendNewEvent();
Assert.AreEqual(false, checker);
}
[TestMethod]
public void CheckSendNewEvent_MinDate()
{
var checker =
I have the application being called from a task scheduler on the hour, sometimes some of the code doesn't get called right on the hour.
My Code for checking the date:
public bool CheckSendNewEvent()
{
var now = DateTime.Now;
const int SendTime = 8;
var firstMonday = GetFirstMondayofMonth(now);
var timeToSendOnFirstMonday = new DateTime(firstMonday.Year, firstMonday.Month, firstMonday.Day, SendTime, 0, 0);
return now > timeToSendOnFirstMonday && now timeToSendOnFirstMonday && now Gets the first week day following a date.
///The date.
///The day of week to return.
///The first dayOfWeek day following date, or date if it is on dayOfWeek.
public static DateTime Next(DateTime date, DayOfWeek dayOfWeek)
{
return date.AddDays((dayOfWeek < date.DayOfWeek ? 7 : 0) + dayOfWeek - date.DayOfWeek);
}
public static DateTime GetFirstMondayofMonth(DateTime now)
{
var monday = new DateTime(now.Year, now.Month, 1);
monday = Next(monday, DayOfWeek.Monday);
return monday;
}I hate to admit this, but I am pretty much a beginner when it comes to Unit Tests, and I think that my life would be much easier with them, so I want to make sure that I am starting out with good habits.
Some of these tests were written before and after reading some articles about naming tests, hence the reason for the bad naming consistency
So here are my tests:
```
[TestMethod]
public void CheckSendNewEvent_Test()
{
var program = new Program();
var checker = program.CheckSendNewEvent();
Assert.AreEqual(false, checker);
}
[TestMethod]
public void CheckSendNewEvent_MinDate()
{
var checker =
Solution
public bool CheckSendNewEvent()
{
var now = DateTime.Now;
const int SendTime = 8;
var firstMonday = GetFirstMondayofMonth(now);
var timeToSendOnFirstMonday = new DateTime(firstMonday.Year, firstMonday.Month, firstMonday.Day, SendTime, 0, 0);
return now > timeToSendOnFirstMonday && now timeToSendOnFirstMonday && now < (timeToSendOnFirstMonday.AddHours(1));
}This is basically one method where you provide a standard option. There are two choice you have here: either put the implementation in one method and create an overload like this:
public static bool CheckSendNewEvent(DateTime now)
{
// Implementation
}
public static bool CheckSendNewEvent()
{
return CheckSendNewEvent(DateTime.Now);
}Or use a default value. However since
DateTime.Now is not a constant, you'll have to use a little trick:public static bool CheckSendNewEvent(DateTime? now = null)
{
now = now ?? DateTime.Now;
// rest of method
}public static DateTime Next(DateTime date, DayOfWeek dayOfWeek)I'd name it
GetNextWeekDay or something like that.public static DateTime GetFirstMondayofMonth(DateTime now)
{
var monday = new DateTime(now.Year, now.Month, 1);
monday = Next(monday, DayOfWeek.Monday);
return monday;
}You can shorten this to
public static DateTime GetFirstMondayofMonth(DateTime now)
{
return Next(new DateTime(now.Year, now.Month, 1), DayOfWeek.Monday);
}Perhaps it's worth considering making
Next an extension method?const int SendTime = 8;I don't know what that means from just looking at it. I'd suggest a comment
// 8 am to avoid confusion.Assert.AreEqual(false, checker);Use the appropriate methods:
Assert.IsFalse(checker) -- this way you don't throw away information that might help you diagnose a failed test.Assert.AreEqual(testResult, firstMonday);The first argument is the expected value, the second is the result.
The DateTime API is an external system, just like a database, the filesystem or a network operation. In unit testing these are typically stubbed out so you work with data entirely under your control. In your case this isn't a problem because the only DateTime used is the one you pass in. However should this not be the case, you should inject a proper datetime service which you can stub from your tests (if you're following along: this will be part of post 3 of my blogseries).
In (unit) testing there is the Arrange, Act, Assert approach to each test. I prefer to explicitly separate these parts with a newline and even a comment.
The naming of the tests.. I wouldn't put the [ExpectedResult] part as a DateTime since it just forces you to compare it to the [Scenario]. I think plain English "ShouldReturnSameDate" will be more effective.
Code Snippets
public bool CheckSendNewEvent()
{
var now = DateTime.Now;
const int SendTime = 8;
var firstMonday = GetFirstMondayofMonth(now);
var timeToSendOnFirstMonday = new DateTime(firstMonday.Year, firstMonday.Month, firstMonday.Day, SendTime, 0, 0);
return now > timeToSendOnFirstMonday && now < (timeToSendOnFirstMonday.AddHours(1));
}
public static bool CheckSendNewEvent(DateTime now)
{
const int SendTime = 8;
var firstMonday = GetFirstMondayofMonth(now);
var timeToSendOnFirstMonday = new DateTime(firstMonday.Year, firstMonday.Month, firstMonday.Day, SendTime, 0, 0);
return now > timeToSendOnFirstMonday && now < (timeToSendOnFirstMonday.AddHours(1));
}public static bool CheckSendNewEvent(DateTime now)
{
// Implementation
}
public static bool CheckSendNewEvent()
{
return CheckSendNewEvent(DateTime.Now);
}public static bool CheckSendNewEvent(DateTime? now = null)
{
now = now ?? DateTime.Now;
// rest of method
}public static DateTime Next(DateTime date, DayOfWeek dayOfWeek)public static DateTime GetFirstMondayofMonth(DateTime now)
{
var monday = new DateTime(now.Year, now.Month, 1);
monday = Next(monday, DayOfWeek.Monday);
return monday;
}Context
StackExchange Code Review Q#85618, answer score: 4
Revisions (0)
No revisions yet.