0

Being new to unit testing and test driven development, I'm having difficulty with unit testing a new function I just wrote for the project I'm working on. I need to parse data from a webpage and store key pieces of data for storage later in the database. I created a struct to hold the individual records I will need and I created a list of the struct to hold all of the collected data and then pass back the said List when the data is parsed. Everything works as expected but the unit test fails?? I can't figure out why...Please help!!

Here is the struct and function:

//===================================================================================================================
    /// lsBuildInstalData
    /// <summary> 
    ///                    This function will parse out the required data from the input list and store it in a private struct.
    ///                    Year (allowing up to 10) : Instalment Amount (pick up the first 4 and skip the rest) : Values (3 values; Year/InstalAmt/Due)
    /// </summary>
    /// 
    /// Parameters
    /// <param name="sTaxDataLine">   Data to parse the values out of.</param>
    /// 
    /// <returns>          Struct List<> of the parsed values.</returns>
    ///
    /// DataBase Use       N/A
    ///                                    
    /// Change Log         04/23/14   MS   Initial development.
    ///                                    
    //===================================================================================================================
    public struct InstalData
    {
        // -- Set the properties... 
        private string sDueAmt, sInstalAmt, sYear;
        public string DueAmt
        {
            get
            {
                return sDueAmt;
            }
            set
            {
                if (value.IsNotNullOrEmpty())
                    sDueAmt = value;
            }
        }
        public string InstalAmt
        {
            get
            {
                return sInstalAmt;
            }
            set
            {
                if (value.IsNotNullOrEmpty())
                    sInstalAmt = value;
            }
        }
        public string Year
        {
            get
            {
                return sYear;
            }
            set
            {
                if (value.IsNotNullOrEmpty())
                    sYear = value;
            }
        }
    }
    private List<InstalData> lsBuildInstalDataArray(List<string> lsTaxDataLine)
    {
        // -- Create the struct and list to pick up all the install data so we can store it correctly later...
        InstalData sID                = new InstalData();
        List<InstalData> lsInstalData = new List<InstalData>();

        // -- Loop through the data, pull what we need, and build the array...
        foreach (string sLine in lsTaxDataLine)
        {
            sID.Year      = sGetParsedValue("Year", sLine);
            sID.InstalAmt = sGetParsedValue("Instal", sLine);
            sID.DueAmt    = sGetParsedValue("Due", sLine);

            // -- ONLY pick up data when there is 'Prinicipal' or 'Surchareg'...
            if ((FSH.Pos("Principal", sLine) > 0 || FSH.Pos("Surcharge", sLine) > 0) && sID.DueAmt != "0.00")
                lsInstalData.Add(sID);
        }   

        // -- Return the final array...
        return lsInstalData;
    }

Here is the unit test with the commented out code of writing the list to a file for my own debugging purposes to show that the data is the same.

[TestClass]
public class OR_CK_WTax_Tests
{
    // -- Create the instance of the Scrape for the public function(s)...
    OR_CK_WTax _Scrape;

    // -- Create the instance of the main class to create a link to the targeted private function(s)...
    PrivateObject poScrape = new PrivateObject(typeof(OR_CK_WTax));

    [TestInitialize]
    public void InitializeScript()
    {
        _Scrape = new OR_CK_WTax();
    }

    [TestMethod]
    public void OR_CK_WTax_lsBuildInstalDataArray_Success()
    {
        // -- Arrange...
        List<string> lsRecordList              = new List<string>();
        lsRecordList.Add("<TR><TD class=GridField>1993</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>2,502.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/1993</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>1994</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>3,148.75</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>200.00</TD><TD class=GridField>11/15/1994</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>1995</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>2,753.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>200.00</TD><TD class=GridField>11/15/1995</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>1996</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>2,925.70</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>200.00</TD><TD class=GridField>11/15/1996</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>1997</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>2,691.46</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>200.00</TD><TD class=GridField>11/15/1997</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>1998</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>2,745.44</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>200.00</TD><TD class=GridField>11/15/1998</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>1999</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-002</TD><TD class=GridFieldNumeric>2,773.58</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>200.00</TD><TD class=GridField>11/15/1999</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2000</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,125.79</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2000</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2001</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,243.49</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2001</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2002</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,349.15</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2002</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2003</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,471.05</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2003</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2004</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,556.47</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2004</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2005</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,609.72</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2005</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2006</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,591.16</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2006</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2007</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,737.88</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2007</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2008</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,827.12</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2008</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2009</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,124.05</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2009</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2010</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,233.20</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2010</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2010</TD><TD class=GridField>Fire Patrol District Surcharge</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,333.20</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2010</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2011</TD><TD class=GridField>Fire Patrol District Surcharge</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,352.73</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2011</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2011</TD><TD class=GridField>Property Tax Interest</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>2,534.73</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2011</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2012</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,483.61</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2012</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2013</TD><TD class=GridField>Fire Patrol District Principal</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,630.42</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2013</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2013</TD><TD class=GridField>Fire Patrol District Surcharge</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>4,666.42</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>666.00</TD><TD class=GridField>11/15/2013</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2013</TD><TD class=GridField>Income Tax Principal</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>5,643.42</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2013</TD></TR><TR");
        lsRecordList.Add("R><TD class=GridField>2013</TD><TD class=GridField>Property Tax Principal</TD><TD class=GridField>086-042</TD><TD class=GridFieldNumeric>3,639.42</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridFieldNumeric>0.00</TD><TD class=GridField>11/15/2013</TD></TR><TR");
        List<OR_CK_WTax.InstalData> lsExpected = new List<OR_CK_WTax.InstalData>();
        OR_CK_WTax.InstalData sID              = new OR_CK_WTax.InstalData();
        sID.Year                               = "1994";
        sID.InstalAmt                          = "3,148.75";
        sID.DueAmt                             = "200.00";
        lsExpected.Add(sID);
        sID.Year                               = "1995";
        sID.InstalAmt                          = "2,753.00";
        sID.DueAmt                             = "200.00";
        lsExpected.Add(sID);
        sID.Year                               = "1996";
        sID.InstalAmt                          = "2,925.70";
        sID.DueAmt                             = "200.00";
        lsExpected.Add(sID);
        sID.Year                               = "1997";
        sID.InstalAmt                          = "2,691.46";
        sID.DueAmt                             = "200.00";
        lsExpected.Add(sID);
        sID.Year                               = "1998";
        sID.InstalAmt                          = "2,745.44";
        sID.DueAmt                             = "200.00";
        lsExpected.Add(sID);
        sID.Year                               = "1999";
        sID.InstalAmt                          = "2,773.58";
        sID.DueAmt                             = "200.00";
        lsExpected.Add(sID);
        sID.Year                               = "2013";
        sID.InstalAmt                          = "4,666.42";
        sID.DueAmt                             = "666.00";
        lsExpected.Add(sID);

        // -- Act...
        List<OR_CK_WTax.InstalData> lsActual = (List<OR_CK_WTax.InstalData>)poScrape.Invoke("lsBuildInstalDataArray", lsRecordList);   // -- Private

        // -- Assert...
        Assert.AreEqual(lsExpected, lsActual);
    }

}

Thanks for any help you can provide!!

Mack
  • 33
  • 5
  • 1
    Side note - why you have this huge scaring comments before functions? – Sergey Berezovskiy Apr 28 '14 at 19:10
  • 6
    Your `struct` doesn't represent a single value, and doesn't meet pretty much any of the guidelines for what makes a suitable struct. It should be a `class`. – Servy Apr 28 '14 at 19:11
  • If you're using NUnit, I'd refactor that gnarly setup to leverage a [TestCase](http://nunit.org/?p=testCase&r=2.5). As a rule of thumb, assert one thing per test method. – 48klocs Apr 28 '14 at 19:13
  • 2
    If you're doing "test driven development", there is no such thing as "unit testing a new function I just wrote". Test-driven development requires that testing come first: you write the failing tests first, and the functions to make it pass second. Now, you can do "unit testing" without doing "test driven development"... but know the difference. – Joel Coehoorn Apr 28 '14 at 19:15
  • 2
    A mutable `struct`? Burn it. [Burn it with fire.](http://stackoverflow.com/a/441323/781792) – Tim S. Apr 28 '14 at 19:15
  • @ Sergey Berezovskiy, the comment is the header for the function that we use in our code for the next developer to know what it does without having to read and figure it out. – Mack Apr 28 '14 at 20:26
  • @ Joel Coehoorn, I do know the difference. We are just starting to implement TDD and old habbits die hard with deadlines. Since the unit test did not 'Assert.AreEqual', but the values are when I compared them manually, I moved on with my work in the hope an answer would be forth comming from the 'experts' here. – Mack Apr 28 '14 at 20:32
  • @ Servy and 48klocks, thanks for the tips. – Mack Apr 28 '14 at 20:33

1 Answers1

4

You're asking MSTest to assert whether two lists are reference equal, which they are not, by using Assert.AreEqual(object, object).

Considering using the CollectionAssert class' methods, but you may need to individually test each item in your list as well as compare the sizes etc.

There's no magic "test that these two collections and their elements are exactly the same using the logical comparison a human would use" functionality, as it were.

Martin Costello
  • 9,672
  • 5
  • 60
  • 72
  • Thanks for the suggestions and help. I ended up writing the values in the struct to a string and then comparing the strings as I'm only concerned with the data values. – Mack Apr 30 '14 at 12:57