The RapidPM Blog

We are speaking Java, because it is a great pleasure for us.

Introducing TinkerForge-Fluent

Having engaged myself in contributing to AssertJ i stumbled over the idea of making the Tinkerforge API more fluent. So this short article represents a first approach of a fluent Java-Tinkerforge API which uses all the advantages of fluent interfaces.

Consider the following example which connects to a temperature, a ambientlight, a barometer and a humdity sensor and prints all changes on the System.out.
IPConnection ipcon = new IPConnection();
BrickletTemperature brickletTemperature = new BrickletTemperature("dXj", ipcon);
BrickletAmbientLight brickletAmbientLight = new BrickletAmbientLight("jy2", ipcon);
BrickletBarometer brickletBarometer = new BrickletBarometer("jY4", ipcon);
BrickletHumidity brickletHumidity = new BrickletHumidity("kfd", ipcon);

ipcon.connect("localhost", 4223);

brickletTemperature.setTemperatureCallbackPeriod(100);
brickletTemperature.addTemperatureListener(temperature -> System.out.println("temperature: " + temperature));

brickletAmbientLight.setIlluminanceCallbackPeriod(100);
brickletAmbientLight.addIlluminanceListener(ambientLight -> System.out.println("ambientLight: " + ambientLight));

brickletBarometer.setAirPressureCallbackPeriod(100);
brickletBarometer.addAirPressureListener(airpressure -> System.out.println("airpressure: " + airpressure));

brickletHumidity.setHumidityCallbackPeriod(100);
brickletHumidity.addHumidityListener(humidity -> System.out.println("humidity: " + humidity));

System.out.println("Press key to exit");
System.in.read();
ipcon.disconnect();
And now look at this one: ;)
IPConnection ipcon = Tinkerforges.connectTo("localhost")
 .withSensor(temperature("dXj").temperaturListener(e -> System.out.println("temperature: " + e)))
 .withSensor(ambientLight("jy2").illuminanceListener(e -> System.out.println("ambientLight: " + e)))
 .withSensor(barometer("jY4").airPressureListener(e -> System.out.println("airpressure: " + e)))
 .withSensor(humidity("kfd").humidityListener(e -> System.out.println("humidity: " + e)))
 .build();

 System.out.println("Press key to exit");
 System.in.read();
 ipcon.disconnect();
You are probably miss the port and callbackperiod which i have defaulted (ala configuration over convention) with reasonable values. With that you have to write less repititve code which makes the code more compact and therefore more readable.

The snippet itself could be compacted more with the use of java.lang.Closable on the internal IPConnectionBase class. Unfortunately the tinkerforge source is still on JDK5.

Have a look at my repository and feel free to contribute. Currently it only contains the bricklets mentioned above.

Is your JUnit KnowHow up to date? - Part 2

This time i want to cover the topic of aggregating JUnit tests which is also part of my blog series Is your JUnit knowhow up to date? The last article can be found here. So let us get started.

Suites

A JUnit Suite is the simplest and oldest way to aggregate JUnit tests. You can use it by annotating your test suite with @Suite as you can see in the following code snippet:
@RunWith(Suite.class)
@Suite.SuiteClasses({CalculatorSimpleTest.class, CalculatorPerformanceTest.class})
public class CalculatorSuite {
}
Basically you tell JUnit to look out for the class array of the @Suite.SuiteClasses which contains all the classes of the suite. But there is a little bit more. Suite itself inherits from ParentRunner which i covered in the last article. Therefore Suites have a lifecycle but in comparison to the default runner only include the Class Ready lifecycle methods which are:
  • @BeforeClass
  • @AfterClass
  • Class Rules (i have not covered it yet)
But although it is technically possible to used them it does not mean that it is good. In general a suite class should only act as an aggregation container. One reason for that is that suite classes can be listed in suites and categories itself so that you can build up hierarchical test structures. If you now use lifecycle methods in your suites you probably decrease understandability and your isolation between your suites.

I also took a deep look at the Suite.SuiteClasses annotation which i considered at first as a bad solution to the problem of aggregating test classes and suites. The reason for that was the declarative nature of it which means that you have to declare every single class or suite. Even with IDE support nowadays this could lead to some work if you have many classes. Considering bug fixes or enhancements of a system there is also the problem that those new tests maybe do not make it in the test suites and therefore could lead to bad reports about the health or quality of the aggregation part.
On the second look i changed my mind. The first reason for that was that there are already some libraries with whom you can overcome the declarative nature problem. The two most promising ones should be:
  • ClasspathSuite - As the name suggests this library extends the suite idea for classpaths.
  • JUnit Toolbox - A JUnit extension library which provides among other things a WildcardPatternSuite which extends the suite idea for wildcards.
The second reason came after thinking about when aggregate tests anyway which i would do for the following topics:
  • by domain or package
  • by test stage (for example component, integration or performance tests)
There are probably more topics by which you can aggregate your tests. The point is that in such cases you explicitly want to declare which tests are in that suite and which are not.

FYI: In the old days of JUnit 3 suites were recognized by a public static Test suite() method in which you had to add the test classes.

Categories

A more flexible way to aggregate tests are Categories which were introduced with JUnit 4.8 and strangely enough are still in the experimental package. The basic concept is similar to suites which means that there is a Categories class which is a JUnit runner (in detail inherits from Suite) and has to be declared with @RunWith(Categories.class) on top of your aggregation container. You also have to declare your test classes with @Suite.SuiteClasses.
The new part is that you can mark your test classes and/or test methods with @Category and a marker class which is used as a filter in your test aggregation container. For that there are two more annotations @Categories.IncludeCategory and @Categories.ExcludeCategory which take a category filter class (the default behavior, without any include or exclude, includes all test methods). The only limitation i found so far is that you can use only one category marker class on the test aggregation container and that you can not repeat those annotations.
An example of an aggregate container would be look like this:
@RunWith(Categories.class)
@Categories.IncludeCategory(SlowTests.class)
@Suite.SuiteClasses( { CalculatorSimpleTest.class, CalculatorPerformanceTest.class})
public class OnlySlowTestSuite {}

public interface SlowTests{}
In this example i had declared a category suite which uses the test classes CalculatorSimpleTest and CalculatorPerformanceTest and include from that classes only the test methods which are annotated with @Category(SlowTests.class). A @Category annotation can be used on class and/or on method level and expects an array of classes. In general it is recommended to use only one class because otherwise it could be really difficult to understand your suite filters considering including and excluding.
In the example above i declare the SlowTests category class marker.
public class CalculatorSimpleTest {

    //snip..

    @Category(SlowTests.class)
    @Test
    public void testSubstract() {
        for (int i = 0; i < 10000; i++) {
            try {Thread.sleep(10l);} catch (InterruptedException e) {
                e.printStackTrace();
            }

            String errorMessage = "Substracting failed";
            int expected = 1;
            int add = calculator.substract(i + 1, i);
            assertEquals(errorMessage, expected, add);
        }
    }
}
If you want to skip all slowtests you would exchange IncludeCategory with ExcludeCategory.

At the time of writing this article JUnit 4.12 beta3 is released which already denotes a little change in the lifecycle handling considering categories. Until now it was possible to use @Category on lifecycle methods like @Before which made those tests very hard to understand. Therefore JUnit introduced a validation handling which prohibits this usage.

AngularJS directives put to use - Part 1

Introduction

AngularJS is a JavaScript framework that greatly assists in building rich client-side web applications. It pushes techniques well known among backend developers to the frontend, for instance dependency injection (DI) or expression binding (more precisely two-way-binding).

Another truly helpful element of AngularJS are directives. You can think of directives as your own means of extending HTML. Or consider it as a means to reduce repetitive code in HTML and therefore making it more readable and improving maintainability.

This blog entry assumes a basic knowledge of AngularJS' controller concept and how to bind to bind a value of the controller with {{}}.

A Nav-Bar with Bootstrap

Initial Situation

For a little app I currently develop, I copied the basic nav bar example from the Bootstrap example and extended it with a some behaviour:

<li class="dropdown" ng-class="{
    active: isActive('/categories') || isActive('/fortune') ||
    isActive('/entry-report') || isActive('/savings') || isActive('/audit')
    }">

    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
        <span class="glyphicon glyphicon-stats"></span> Reports <b class="caret"></b>
    </a>
    <ul class="dropdown-menu">
        <li ng-class="{active: isActive('/categories')}">
            <a href="#/categories">Categories</a>
        </li>

        <li ng-class="{active: isActive('/entry-report')}">
            <a href="#/entry-report">Entries</a>
        </li>

        <li ng-class="{active: isActive('/savings')}">
            <a href="#/savings">Savings</a>
        </li>

        <li ng-class="{active: isActive('/fortune')}">
            <a href="#/fortune">Fortune</a>
        </li>

        <li ng-class="{active: isActive('/audit')}">
            <a href="#/audit">Audit</a>
        </li>

    </ul>
</li>

ng-class is used to add a CSS classes to the element if the specified condition is met. isActive is a method of the corresponding AngularJS controller, which simply returns true if the currently active URI of the application ends with the provided string. This way an item is highlighted if the respective link is displayed.

As you can see, there is some repetition if you want to add another entry to the nav bar. You always have to specify the URI for isActive and the href attribute. Additionally every nav bar entry mostly looks the same, except for the URI and the title of the link.

There is a better way: an AngularJS directive helps us to remove the repetition with both of the above mentioned problems.

The solution

We create a directive:

var myDirectives = angular.module('myApp.directives', []);

myDirectives.directive('navEntry', ['$location', function ($location) {

    function link(scope, element, attrs) {

        function setSafeLink(element) {

            var link = element.find('a');
            link.attr('href', '#' + attrs.path);
        }

        setSafeLink(element);

        scope.$watch(function () {
            return $location.path();
        }, function (newLocation) {

            if (attrs.path === newLocation) {
                element.addClass('active');
            } else {
                element.removeClass('active');
            }
        });
    }

    return {
        replace: true,
        restrict: 'E',
        scope: {
            path: '@',
            title: '@'
        },
        templateUrl: '/js/directives/navEntry/nav-entry.html',
        link: link
    };


}]);
Folder Structure

This is the template, that the directives links to:

<li>
    <a >{{title}}</a>
</li>

Here are the core explanations

  • the name of the directive is navEntry, which means it can be used as <nav-entry> in the HTML. This is Angulars standard way of using directives.
  • we depend on $location being injected (for checking which URI is currently active)
  • the function link(scope, element, attrs) is executed once for each actual usage (instance) of the directive
    • the link of our navigation entry is set with setSafeLink() to the value of the path attribute and the title of the title attribute of the directive instance
    • a listener, which triggers when the URI changes, is registered
    • if the URI changes, we check whether the currently active URI matches the path attribute of the directive instance (which governs whether or not the navigation entry is active)
  • restrict: 'E': the directive is used like a separate element
  • templateUrl: the path of content of the directive
  • scope:
    • this defines an own scope for each directive instance, isolated from the scope of the controller actually being responsible (isolate scope)
    • path: '@' the directive element shall have an attribute path, which value is mapped to the scope property path (<nav-bar path="/mypath">)
    • shorthand notation for path: '@path'
  • replace: true: means that the directive usage in the HTML is replaced by content of the template of the directive when building the final DOM

Actually I wanted to set the href attribute in the template, but AngularJS has some security mechanism that prevents us from using something like

    <a href="#{{path}}">...</a>

That's why setSafeLink() adds href instead.

The Result

<li class="dropdown" ng-class="{
    active: isActive('/categories') || isActive('/fortune') ||
    isActive('/entry-report') || isActive('/savings') || isActive('/audit')
    }">

    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
        <span class="glyphicon glyphicon-stats"></span> Reports <b class="caret"></b>
    </a>
    <ul class="dropdown-menu">

        <nav-entry path="/categories" title="Category Overview"></nav-entry>

        <nav-entry path="/category" title="Category"></nav-entry>

        <nav-entry path="/entry-report" title="Entries"></nav-entry>

        <nav-entry path="/savings" title="Savings"></nav-entry>

        <nav-entry path="/fortune" title="Fortune"></nav-entry>

        <nav-entry path="/audit" title="Balance Audit"></nav-entry>

    </ul>
</li>

Conclusion

This is a lot less code than in the initial setup and adding a new navigation entry is pretty easy now. We removed the duplication of the URI string, which is a little less error prone. Moreover, we now could the change the template in one place instead of touching all navigation entries, which makes it DRY.

The idea could even be taken a little further. A potential next step is to make the whole dropdown element a separate directive, which could lift the need to separately list each isActive('/...') branch for the contained <nav-bar>.

Outlook

Stay tuned for another example of what you can do with directives in part 2. Next time we'll have a look into how to format currency values.