Utilizing your .NET Project's Automated Acceptance Tests on Crystal Reports - Part 2
 
Published: 29 May 2008
Abstract
In the second part of this series, Eric shows how to automatically incorporate testing report output from your crystal reports using Fitnesse and Visual Studio 2008. After providing a short overview, he examines the need for testing values and outlines the required steps to build a Fitnesse test. He also deeply analyzes the code sample along with the screenshot of the final output.
by Eric Landes
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 27114/ 40

Introduction

As we mentioned in Part 1 of this series, the impetus for this series came about because I want to incorporate agile methods into the reporting modules of projects.  After reviewing the different practices that can be found in agile projects, the focus of this series is on how to create automated acceptance tests for the Crystal Reports part of your project. 

That first article showed how to write an 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 downside of testing for values is that this has to be done against a data source.  When we test the format, as we did in the first article, there is not a lot performance issues.  But when we need to go against a data source, then our automated tests don't perform quickly.  For this reason, this article doesn't recommend that the test referenced in Part 2 be included with your continuous integration builds.  But any builds that go to your testing environments are good candidates to put this in.

Also keep in mind that we need to make sure the data that the report uses is consistent.  We'll talk about techniques to do that.

The Fitnesse test

As mentioned in earlier, for our automated acceptance tests, we use the open source software Fitnesse.  Part 1 had a quick overview of how to use Fitnesse, but for more extensive information on how to use Fitnesse, I recommend going to the Fitnesse website.

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.  Also, there do not have to be leading digits.  So if today is November 1st, 2008, the test writer would expect 11/1/2008.

The last column, ok expects that a true will be returned.  Now let's look at the code we used to write this test.

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. 

Once we have the report in a string, it's trivial to run the tests.  This simple test shows you how to accomplish this, by using the indexof property.  We are assuming that if the value is present in the report, this is true.  You can create more complex testing if you want, and test that this is after a heading or something.  But that is beyond the scope of this article. 

Once you run this test, your Fitnesse test should run green. Just like the one in Figure 1. And you now have a test to run in your QA build script!

Figure 1

Summary

In Part 1 and Part 2 of this series, we have seen how you can use automated acceptance testing to validate your reports.  Specifically we have run Fitnesse against Crystal Reports to validate that the report contains what the customer specified.  As mentioned earlier, having executable requirements is a weapon in your arsenal that can help keep the quality of your custom solutions high.  I highly recommend using this in your next project.  Using the techniques should help you to have a happy coding experience!



User Comments

No comments posted yet.

Product Spotlight
Product Spotlight 



Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-05-02 6:27:55 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search