I’m novice in unit testing field, so I have some questions:
Is it a good practice to make method that returns a DataTable? If yes, how could I test it then?
This is a function that they ask me to test:
public static DataTable GeneratePeriods(DateTime startDate, DateTime endDate, string periodicity)
{
try
{
using (DataTable periods = new DataTable())
{
periods.Columns.Add(new DataColumn("Dates", typeof(DateTime)));
int startYear = startDate.Year;
int endYear = endDate.Year;
int Diff = endYear - startYear + 1;
int LoopYear;
/* This generates all regular periods from the begin date to the end date */
switch (periodicity)
{
//monthly
case "Mensuelle":
for (int j = 0; j < Diff; j++)
{
LoopYear = startYear + j;
for (int i = 1; i <= 12; i++)
if (i != 12)
periods.Rows.Add(new DateTime(LoopYear, i + 1, 1).AddDays(-1));
else
periods.Rows.Add(new DateTime(LoopYear, 12, 31));
}
break;
//quarterly
case "Trimestrielle":
for (int j = 0; j < Diff; j++)
{
LoopYear = startYear + j;
for (int i = 1; i <= 4; i++)
if (i != 4)
periods.Rows.Add(new DateTime(LoopYear, (i * 3) + 1, 1).AddDays(-1));
else
periods.Rows.Add(new DateTime(LoopYear, 12, 31));
}
break;
//biannual
case "Semestrielle":
for (int j = 0; j < Diff; j++)
{
LoopYear = startYear + j;
for (int i = 1; i <= 2; i++)
if (i != 2)
periods.Rows.Add(new DateTime(LoopYear, (i * 6) + 1, 1).AddDays(-1));
else
periods.Rows.Add(new DateTime(LoopYear, 12, 31));
}
break;
//annual
case "Annuelle":
for (int j = 0; j < Diff; j++)
{
LoopYear = startYear + j;
for (int i = 1; i <= 1; i++)
periods.Rows.Add(new DateTime(LoopYear, 12, 31));
}
break;
}
//this adds startDate in periods datatable if it doesn't exist
if (periods.Select(String.Format("Dates = '{0}'", startDate)).Length == 0)
periods.Rows.Add(startDate);
//this adds endDate date in periods datatable if it doesn't exist
if (periods.Select(String.Format("Dates = '{0}'", endDate.AddDays(-1))).Length == 0)
periods.Rows.Add(endDate);
//this removes all date ranges below the startDate
DataRow[] dr = periods.Select(String.Format("Dates < '{0}'", startDate));
foreach (DataRow row in dr)
periods.Rows.Remove(row);
//this removes all date ranges above the endDate
DataRow[] dr1 = periods.Select(String.Format("Dates >'{0}'", endDate.AddDays(-1)));
foreach (DataRow row in dr1)
periods.Rows.Remove(row);
//this adds endDate date in periods datatable if it doesn't exist for the second time ! (I personnaly don't know why it's duplicated but it dosen't work without this =) )
if (periods.Select(String.Format("Dates = '{0}'", endDate.AddDays(-1))).Length == 0)
periods.Rows.Add(endDate);
DataView dv = new DataView(periods) { Sort = "Dates ASC" };
// this initialize a new datatable with sorted dates
DataTable dt_dates = dv.ToTable();
// this initialize a new datatable
DataTable dt_periods = new DataTable();
dt_periods.Columns.Add("Periods", typeof(string));
dt_periods.Columns.Add("NombreJours", typeof(int));
// this loop creates period ranges shown to the user (Du startDate au endDate)
DateTime dateDebutPeriode;
DateTime dateFinPeriode;
int NombreJours;
for (int i = 0; i < dv.Table.Rows.Count - 1; i++)
if (i == 0)
{
dateDebutPeriode = DateTime.Parse(dt_dates.Rows[i]["Dates"].ToString());
dateFinPeriode = DateTime.Parse(dt_dates.Rows[i + 1]["Dates"].ToString());
NombreJours = dateFinPeriode.Subtract(dateDebutPeriode).Days + 1;
dt_periods.Rows.Add(String.Format("Du {0} au {1}", dateDebutPeriode.ToShortDateString(), dateFinPeriode.ToShortDateString()), NombreJours);
}
else
if (i == dv.Table.Rows.Count - 2)
{
dateDebutPeriode = DateTime.Parse(dt_dates.Rows[i]["Dates"].ToString()).AddDays(1);
dateFinPeriode = DateTime.Parse(dt_dates.Rows[i + 1]["Dates"].ToString()).AddDays(-1);
NombreJours = dateFinPeriode.Subtract(dateDebutPeriode).Days + 1;
dt_periods.Rows.Add(String.Format("Du {0} au {1}", dateDebutPeriode.ToShortDateString(), dateFinPeriode.ToShortDateString()), NombreJours);
}
else
{
dateDebutPeriode = DateTime.Parse(dt_dates.Rows[i]["Dates"].ToString()).AddDays(1);
dateFinPeriode = DateTime.Parse(dt_dates.Rows[i + 1]["Dates"].ToString());
NombreJours = dateFinPeriode.Subtract(dateDebutPeriode).Days + 1;
dt_periods.Rows.Add(String.Format("Du {0} au {1}", dateDebutPeriode.ToShortDateString(), dateFinPeriode.ToShortDateString()), NombreJours);
}
return dt_periods;
}
}
catch (InvalidOperationException)
{
throw;
}
}
What you can test here, is whether returned
DataTablestructure is indeed what you expect. Those are plain and simple unit tests. Determine what is expected fromGeneratePeriodsmethod (as in, what do you want it to do?), and write tests checking that it is in fact what method does. For example:On a side note, there’s nothing wrong with returning
DataTablefrom function.