No More Updates to ReportNG

Posted in Java by Dan on December 3rd, 2015

About 8 years ago I made the decision to use TestNG for unit testing a Java project at work because it offered a much neater approach to the problem than JUnit 3.x. The only problem was that the HTML reports it generated were ugly. So I quickly hacked together a plug-in using Apache Velocity that would present the information in a way that I preferred and called it ReportNG. There was nothing elegant about the solution and the reports were functional but not particularly attractive, but it scratched an itch. It seemed to be an itch that irritated a lot of other developers because it attracted probably more users than any other, better written code that I’ve open-sourced before or since. I have made no substantial changes to it in years but there are still people using it.

I don’t do nearly as much Java as I used to and where I do I am either not using ReportNG or it is sufficient as it is. For these reasons, and because it ought to be replaced by something better (which probably already exists somewhere – I haven’t looked), I wanted to make it explicit to people still relying on it that there will be no further updates to ReportNG. You have three options:

  1. Continue using version 1.1.4 and accept that it will never get any better.
  2. Fork it on GitHub and make whatever changes you like. The Apache licence is permissive enough to allow most things.
  3. Stop using ReportNG and find something better.

ReportNG 1.1.4

Posted in Java by Dan on June 11th, 2013

It’s been a couple of years since the last release of ReportNG, my cobbled together alternative reporting plug-in for TestNG. In the time since I’ve done nothing but a few users have submitted useful improvements. So, after some prompting, I’ve released version 1.1.4 (download zip, tgz).

Thanks to Kayla Nimis, criccio, Arcadie, and Nalin Makar the new version has the following improvements:

  • The report now shows the reason for skipping a test.
  • You can specify the org.uncommons.reportng.failures-only property to generate a more minimal report.
  • ReportNG will now create any missing parent directories of the report directory rather than failing if they are absent.

Android ListView – Fixing Missing/Blank Dividers

Posted in Android, Java by Dan on January 24th, 2013

A post with code in it. Because it’s been a long time since the last one.

If you work with ListViews in Android, as all Android developers will do at some point, you may notice that if you set your list items to be non-selectable the dividers that are drawn between each cell disappear. In the Holo Light theme you would normally get a thin light grey dividing line between cells. Depending on how you’ve implemented your adapter, you may find that these dividers become white/transparent when the cells are not selectable. According to Android framework engineer Romain Guy, this is the intended behaviour.

As Haythem Souissi points out in this Stack Overflow answer, you can work around this by ensuring that the areAllItemsEnabled method returns true, even though all items are not enabled (maybe none of them are). The isEnabled method will take care of actually disabling the cells and the dividers will be drawn between each of them.

All very straightforward so far but it all goes wrong again when you try to add a non-selectable header view to the list. The way that ListView deals with headers and footers is that it creates its own adapter to wrap/decorate yours and insert the header/footer views in the appropriate places. This is fine but it’s not delegating the areAllItemsEnabled method, so our above fix no longer works.

Fortunately, and unusually for Android, everything we need to resolve this issue is part of the public API. The adapter decorator class is android.widget.HeaderViewListAdapter. We just need to create our own instance, wrapping our own adapter, and override areAllItemsEnabled as above. There’s a slight complication in that we have to wrap the header view in an instance of ListView.FixedViewInfo and this is a non-static inner class of ListView, but we can reach into our bag of obscure Java tricks to create an instance from outside the enclosing class.

// I assume you know how get a reference to the ListView and create your own adapter.
ListView listView = (ListView) view.findViewById(android.R.id.list);
CustomAdapter adapter = new CustomAdapter(context, listOfItems);
 
// You can create any view you like for the header.
TextView listHeader = (TextView) inflater.inflate(R.layout.list_header, null);
listHeader.setText("My Header Text");
 
// This is how you create an instance of the non-static nested class, providing
// it with a reference to an instance of the containing class (ListView).
ListView.FixedViewInfo headerInfo = listView.new FixedViewInfo();
 
headerInfo.view = listHeader;
headerInfo.isSelectable = false;
 
// HeaderViewListAdapter insists on concrete ArrayLists.
ArrayList headers = new ArrayList(1);
headerInfoList.add(headerInfo);
ArrayList footers = new ArrayList(0);
 
HeaderViewListAdapter wrapper = new HeaderViewListAdapter(headers, footers, adapter)
{
    @Override
    public boolean areAllItemsEnabled()
    {
        return true;
    }
};
listView.setAdapter(wrapper);

Uncommons Maths 1.2.3

Posted in Java by Dan on November 22nd, 2012

It’s five years ago this week that I first released Uncommons Maths as a standalone project spun-off from an early version of the Watchmaker Framework. Uncommons Maths is a Java library that provides, among other things, various classes for working with random numbers, probability distributions and combinatorics. There hasn’t been a release in over two years so today I’ve published a maintenance release, version 1.2.3, on GitHub.

There are two main changes in this version. Firstly, thanks to a contribution from Dave LeBlanc, the Uncommons Maths JAR file is now a valid OSGi bundle. Secondly, I found and fixed a pretty fundamental bug in the convertBytesToLong method of BinaryUtils. The fact this bug went undetected for so long suggests that nobody is actually using this method. It also reinforces that full test coverage is worthless if you don’t select your test inputs carefully.

Finally, the documentation has been updated to make it clear that none of the RNG implementations support the seeding mechanism inherited from the java.util.Random base class. The reason for this is that the setSeed method only takes a single long argument. This means it’s not possible to provide more than 64 bits of entropy, which is insufficient for most of the Uncommons Maths RNGs. In practice calling this method on an RNG instance has no effect. Ideally the method would be over-ridden to throw UnsupportedOperationException but to do so is not possible because setSeed is invoked internally by the java.util.Random constructors. If it threw an exception it would not be possible to create an instance of an object that inherits from java.util.Random.

Watchmaker Framework at JavaOne – Using Java and Genetic Algorithms to Beat the Market

Posted in Evolutionary Computation, Java by Dan on July 29th, 2011

Those of you who will be attending JavaOne this year (2nd – 6th October in San Francisco) might be interested in Matthew Ring’s BoF session on genetic algorithms in Java. Matthew tells me that he will be presenting his software that uses my Watchmaker Framework for Evolutionary Computation as part of his session Using Java and Genetic Algorithms to Beat the Market. Here’s the abstract:

Predicting the future is dangerous business. Is Java up to the task? This session discusses and demonstrates a fun and understandable stock-picking system built with Java 6 and various Java-based open source projects. The discussion ranges from machine learning concepts (specifically genetic algorithms) and core Java development with specific code examples to trading system back-testing. Attendees are sure to come away excited, ready to tackle that next hard big-money problem, and confident that Java is a capable partner.

ReportNG 1.1.3

Posted in Java by Dan on February 14th, 2011

I’ve just pushed a new version of ReportNG (an HTML reporting plug-in for TestNG) to GitHub. This is a minor enhancement release that incorporates a few patches submitted by users. Thanks to Jeff Weiss, ReportNG should now load custom stylesheets from the classpath as well as the file system and it should have less broken dependencies if you are using it with Maven. By default ReportNG will now also not generate the annoying Velocity log file (if you want the log file you can re-enable it via a system property). This change is thanks to C. Baldwin.

Using ReportNG with Maven

Posted in Java by Dan on January 23rd, 2011

I’m not a Maven user, so I’ve never made any effort to use ReportNG from Maven. Maven users were left to figure it out for themselves. Well, Marcin Zajączkowski has figured it out for himself and has documented what’s involved.

Uncommons Maths 1.2.2

Posted in Java by Dan on October 20th, 2010

Yesterday I moved Uncommons Maths (random number generators, probability distributions, combinatorics and a few other numbery type things) from Java.net to GitHub. My other projects have been on GitHub for a while but this one hadn’t been moved mostly because it hasn’t seen any recent activity. I also took this opportunity to push out another release incorporating a couple minor fixes (serialisation and thread safety issues) that have been sitting in the Subversion repository for almost a year.

Download version 1.2.2, or get it from Java.net’s Maven repository.

Android LVL Obfuscation Pitfalls

Posted in Android, Java by Dan on September 13th, 2010

The recently-introduced Android License Verification Library (LVL) survived a disappointingly short time in the wild before somebody figured out how to circumvent its protection. Google responded to this development by stating that it was the lack of obfuscation that had made the crack so straightforward and then followed up with further advice on achieving security through obscurity, effectively acknowledging that there is no robust way of doing licence verification that can’t be bypassed.

Unfortunately, the LVL is pretty much the only option for protecting apps sold via the Android Market (other app stores have their own protection mechanisms). The choice for Android developers is mediocre protection or no protection at all (Google apparently intends to withdraw its previous copy protection mechanism).  You can thwart the most casual Android pirates and make things harder for the determined but that’s about as good as it gets.

Obfuscating LVL-protected Apps with Proguard

Assuming that you choose to add the LVL to your app, you’ll no doubt want to follow Google’s advice and obfuscate your code, probably using Proguard. If you do, you might hit a couple of problems that prevent the LVL from working properly.

I added the LVL source to my application and built it as a single entity but it is also possible to incorporate the LVL as a library project.

Disable Aggressive Overloading

The first problem I encountered was a limitation in the Dalvik VM. Unlike the JVM, it does not (did not?) permit static fields of different types to have the same name.  In normal Java development this situation never arises but Proguard has an option to aggressively overload names to make decompilation more difficult. For Android development this option should not be used otherwise you will get VerifyErrors.

Avoid Renaming the ILicensingService Intent

The checkAccess method of the LVL’s LicenseChecker class binds to the licensing service as follows:

boolean bindResult = mContext.bindService(
    new Intent(ILicensingService.class.getName()),
    this,  // ServiceConnection.
    Context.BIND_AUTO_CREATE);

The problem with calling ILicensingService.class.getName() is that, after obfuscation, the class has a different name and therefore the wrong intent is created. This will show up in the log as an error with the message “Could not bind to service” and the licence check will always fail.

You could fix this by modifying the Proguard configuration to avoid renaming the ILicensingService interface or, even more straightforwardly, you could just modify the code in LicenseChecker and hard-code the appropriate action:

boolean bindResult = mContext.bindService(
    new Intent("com.android.vending.licensing.ILicensingService",
    this,  // ServiceConnection.
    Context.BIND_AUTO_CREATE);

ReportNG 1.1.2

Posted in Java by Dan on August 4th, 2010

ReportNG version 1.1.2 is available for download. ReportNG is an HTML/XML reporting plugin for TestNG.

There are only two small changes in this release.  The first is a fix for an avoidable NullPointerException if the target directory does not exist. The second updates ReportNG to work with this change in TestNG 5.13.1. Thanks to Nalin for providing a patch for this issue.

« Older Posts