Writing Pentaho Reporting Engine UnitTest Case

Welcome

This document provides you with a process for creating reporting engine unit tests. The purpose of this document is:

  • To help you understand the framework for creating a simple unit test for Pentaho Reporting Engine
  • To help us create unit tests that use this existing framework
  • To provide you an example of a unit test and drill down deeper into each part of the test case

Assumptions

It is assumed that you, the reader, are familiar with Junit framework. This guide does not include:

  • General information about Junit and how it works

Introduction

There are two way to write a good unit test for the Pentaho Reporting Engine. First, is to write a unit test to test a particular fragment of code and the second is to use the reporting definition xml to execute certain pieces of the code. The good thing about using the latter is that you don't require extensive understanding of the reporting engine code. All you need to know is how to construct a report definition and how to feed this document to the reporting engine. Both unit tests differ greatly in style, although they each have the same end goal, which is verification of a unit of code.  This document is more about explaining how to write a unit test using the report definition. Report definition is an xml file containing the layout details of a report. This report is usually created using the Pentaho Report Designer and can be hand created if you know the structure of the xml. One thing to remember about creating these report definitions for the purpose of this testing is not to have any current date information on it. Most of the report has a report run date. This will always be different so the report will not be the same. So to avoid this issue, remove any report run date from the report definition. If you need more information about the structure of the report definition read the advance reporting guide.

Unit Testing Framework

There are two base test which a unit test class should extends are

  1. XMLBaseTest   -   Used for only testing the xml. This base test inherits XMLTestCase which is a open souce API to comparing XMLs in a unit test.  For details on this open source project please read XMLUnit
  2. BaseTest         -   Used for testing report in pdf, xls, csv,  html formats.

Testing Report in XML Format

All the generated reports are compared with a golden version of reports which have been generated using a latest stable version of Pentaho Reporting Engine. Before testing a new report definition, a golden report needs to be generated and placed in the golden report path.  The golden report path can be retrieved by using a parent class variable reportInputPath. Every unit test generates a report which is stored in a report output path. The report output path can be accessed by using a parent class variable reportOutputPath.

In order to create a report you must first create an object of type JFreeReport. JFreeReport object can be created by passing in the report definition file to a base method parseReport. After creating the JFreeReport object you need to map the data which will be used by the JFreeReport to generate this report. JFreeReport uses the Swing table model structure to accept the data for the Report. The report data is created by using the SQL query in class which extends JdbcTableModel. The JdbcTableModel  converts the IPentahoResultSet to a AbstractTableModel. Below is an example as to how to create a Report Data.

Once the report data is created we will create a TableDataFactory and set the data factory in the JFreeReport object
 

Now you are ready to generate the report in a XML format. XMLDebugReportUtil is a new utility which creates the xml representation of the report data and structure before it is being rendered to a specific format. This seems to be a decent format to compare the output of a layoutter before it render it in a specific format.  XMLDebugReportUtil  generates the xml in pageable, flow table and stream table format. Pageable format contains more details for the report then the other, but it is a good idea to test all.
 

Once the report is created you can then compare the generated report with a golden version of this report. This comparison is basically checking for the layout of the report. For this comparison an open source XML comparator API has been used which is called XMLUnit. This APU can only be applied to the unit test. Use a method compareXML in this class to compare two reports.

                                                                     compareXML(readFileAsString(inputFileName), readFileAsString(outputFilename))

The above method returns a Diff object which is used by the DetailedDiff method to return all the differences in the two reports. Using a method getAllDifferences() in the DetailedDiff class will return a list of differences. If there are differences then these difference are written to a output stream as a log file and unit test fails otherwise it is a successful unit test. In cases of differences we can review them and if they are valid differences then we can make the generated report a golden report and the unit test will pass from now onwards. This is currently a manual process as we have no way of know whether the difference a valid or not.

Testing Report in Other(pdf, xls, csv, html) Formats

If you are writing a test case to compare the reports in formats other than xml you need to extend BaseTest. Instead of using the XMLDebugReportUtil for generate the report, you need to use the following classes

  • PdfReportUtil        - Generating report in PDF format
  • ExcelReportUtil    -  Generating report in Excel format
  • CSVReportUtil     -  Generating report in CSV format
  • HtmlReportUtil     -  Generating report in html format 

Once the report are generated we can compare them by using the following methods from the base class

  • comparePdf - comparing two PDF documents.
  • compareXls - compare two excel documents.
  • contentsEqual - compare csv and html file using binary comparison