Wednesday, October 8, 2014

Custom reporting engine with Mustache

In addition to previous post based on Velocity, I'd like to create some useful notes about another interesting template engine - Mustache. Let's take a look at its syntax to understand how easy is to inject different kinds of objects into template's context.

In this article we will create a simple test results overview template based on TestNG statistics.

To start with templates development using Mustache, first you need to include appropriate dependency, based on Mustache.java project. As we will also use TestNG, let's add it to our root pom either.


To add *.mustache templates' syntax support to IntelliJ IDEA, you can install Handlebars/Mustache plugin:


Let's create report.mustache file in resources folder.
To refer some java object, that you want to inject into template, use the following syntax:


Where reportTitle is a name of declared java variable. So we should use {{varName}} syntax for simple objects.

As Mustache is a logic-less template engine, it means that there're no loops and conditional statements available in its syntax scope. So how we can refer collections then?


Where suites and testResults is a list of java objects. Mustache automatically resolves such construction, as an iterative section. Everything located between {{#listName}} and {{/listName}} will appear N times in output report, where N = listName.size().

In the above example you can also see some new definition that differs from common variable syntax: {{#translate}}some text{{/translate}}. This particular object stores resource bundle to get locale depending properties' values by putting appropriate keys between above constructions. Such syntax reserved for Mustache functions. Among them there's a BundleFunctions class you can use for loading needed resources.

So how could we override default TestNG report with our custom one using Mustache?

First we need to create a custom listener, that will implement IReporter interface. When we override generateReport method, we will get access to test results context.


To create a report from Mustache template, first we need to compile it and then execute with some obvious parameters. FileWriter points to output report file. getScope method just returns a map of objects, where keys reflect template variables we discussed above, and values - appropriate objects we want to display in report. Note that all these objects should have public getters to let Mustashe engine getting appropriate access to their values.

Now we need to add a custom listener to maven-surefire-plugin configuration:


As you see, default TestNG listeners are disabled. Also there were added 2 custom properties: report.title and locale to make our example more realistic. Finally, to scale our test examples, there was added a composite base.suite.xml.

Sample source code also contains 2 entities: Suites and TestResults - classes to parse ISuite list given by overridden generateReport method. Note that we could use this list directly in Mustache template without creating additional wrappers. But in such case template's structure would be more complicated due to TestNG internal objects' depth.

You can pull sources from GitHub. And output report will look like the following:


No comments:

Post a Comment