Automated Acceptance Tests on Crystal Reports

Started by dhilipkumar, May 20, 2009, 08:04 PM

Previous topic - Next topic

dhilipkumar

Automated Acceptance Tests on Crystal Reports

automated acceptance test using the open source Fitnesse framework to write your tests.  The article went over why we might want automated acceptance tests for our reports, mentioning benefits like executable requirements and the ability to include your tests in your continuous integration builds.

Also in part 1, we had a brief overview of Fitnesse, and then showed how to write a test that would verify the layout of your report.  There are many parts of the format that can be tested using Fitnesse and crystal, and I feel this is the best place to include tests for continuous integration.

In the second part of this series, we are going to go over how to test the actual values of the report using automated acceptance tests.  Let's look into why we want to test values first. 

System Requirements

·         Crystal Reports .NET

·         Fitnesse

·         Visual Studio 2008


Why test Values?

Since values change constantly in reports, your first question may be "why write tests against values".  This article presents the idea that in cases where you are calculating fields, or doing data dictionary lookups for fields, testing the values can validate the reports internal "code".


The Fitnesse test


As mentioned previously, Fitnesse organizes tests into a spreadsheet like manner.  In fact you can create tests in Excel, and then export them into Fitnesse.  For our test we are going to keep it simple.  We are going to check that a formula field contains the correct date.  Below is a sample of the Fitnesse test:

Fitnesse Test 1
Values In Report


field name                 value                   ok()

Changeset                 today                   TRUE

This simple test first checks the field name, and then the value.  Notice in the value column there is the word today.  For this test, the test writer and the developer have agreed that today means something.  What they agreed on is that it means today's date in the format mm/dd/yyyy.


source : aspalliance

dhilipkumar

Writing the code for the Fitnesse test

Now we need to write our code for testing this.  To refresh your memory, we can use different Fitnesse fixtures to run our tests.  In this case as in part 1, we utilize a columnfixture.  In this test, we cannot analyze using the reportdocument object.  We need to analyze the reports contents once it's rendered.  The reportdocument object can export the contents, but we cannot use the reportdocument object directly to test for values.

To get our values for the test we will export the report to a stream, and then read the stream as a string.  Below is the code for doing this:

Listing 1

public class valuesinreport: ColumnFixture
{
  public string fieldname;
  public string value;
  public Boolean ok()
  {
    CrystalReport1 report = new CrystalReport1();
    MemoryStream memReport = (MemoryStream)report.ExportToStream
      (CrystalDecisions.Shared.ExportFormatType.HTML40);
    memReport.Position = 0;
    byte[]byteArray = new byte[memReport.Length];
    int count = memReport.Read(byteArray, 0, (int)memReport.Length);
    String strReport = Encoding.ASCII.GetString(byteArray);
    if (strReport.IndexOf(fieldname) >  - 1)
    {
      //Check if date value
      if (value == "today")
      {
        if (strReport.IndexOf(DateTime.Now.ToShortDateString()) >  - 1)
        {
          return true;
        }
      }
      else
      {
        if (strReport.IndexOf(value) >  - 1)
        {
          return true;
        }
      }
    }
    return false;
  }
}


In this code, we first set the fields for the fieldname, and value.  And as in part 1, we create a method called OK that returns a Boolean.  Fitnesse will pass the fieldname and value to the OK method.  Within the OK method, we get our report (CrystalReport1) named report.  We then need to get the report results back in a stream.  To do that we use the ExportToStream method found in the ReportDocument object.  Here we cast it to a MemoryStream, but it can be cast to any valid Stream type.

We then get the string value of the report, by reading the Stream.  Then we cast the resulting byte array into an ASCII value, pushing into a string variable. In the if statements, this particular test is checking for the presence of the value "today".  That way we know to test against the DateTime.Now value.