VideoBar

This content is not yet available over encrypted connections.

Saturday, April 14, 2012

Dart Preview: Platform Independent Unit Testing

I’ve been working on a patch for Dart’s html unit testing output recently, and as a result have become quite familiar with the latest changes to unit testing in the bleeding_edge branch.  In this post, I will demonstrate how unit test results can now be redirected to the platform of your choice, including your own customized platforms.

The most significant change is the notion of platform independence, meaning that by default, Dart’s unit test will render output to the console, but you can redirect that output to any other presentation platform – like HTML.

NOTE: As I mentioned, this is all in the bleeding edge branch at the moment, so you won’t find this stuff in the SDK.  Furthermore, some or all of this is subject to change at any time.

How It Works
If you want to use the default platform (console) then all you have to do is import unittest.dart

#import('my/path/to/unittest.dart');

Then write some unit tests using the API

group('My Test Group', () {

    test('fail test', () => Expect.fail('fail test'));
    
    test('pass test', () => Expect.isTrue(true));

    asyncTest('async test', 1, (){
        Expect.isTrue(true);
        //some async code that finishes with...
        callbackDone();
    });

});

Above, I am demonstrating the current API for declaring test groups (which can be nested), tests, and async tests.

Async tests currently use a message pump to to determine completion, so you pass in how many times the pump will be, well pumped, and then you make the same number of calls to callbackDone() so that test harness knows when the async operation is complete.  This API is likely to change a bit in the future.

Now run the app.  If you work within the Dart editor and have Dartium running, you will see the output rendered into the editor’s console window.

FAIL: My Test Group fail test
  Expect.fail('fail test')
PASS: My Test Group pass test
PASS: My Test Group async test

2 PASSED, 1 FAILED, 0 ERRORS

Redirecting To Another Platform
Outputting to the console is nice and all, but can be a bit tedious when dealing with a large number of tests.  Fortunately, the unit test framework supports platform redirection.

The current browser platform output is basically a static dump of the unit test results into a HTML Table, but lets say we wanted to have something a bit more interactive, we can write this by extending a new class that comes with the framework:  Configuration.  Any class that extends configuration can then be passed to the test harness prior to the test run like so:

configure(new MyUnitTestExtension());

As I mentioned at the beginning of this post, I’ve written a patch that provides a richer UI experience for the browser platform.  In order to use it we need to import the library that contains the extension, assuming my patch is accepted, it would be this:

#import('my/path/to/html_enhanced_config.dart');

Then we can use the helper method included with that import to set the configuration. This helper essentially makes the call to configure() for us:

useHtmlEnhancedConfiguration();

And now the output looks like this (in Dartium):



As you can see we get an HTML output to the browser that shows our test group, along with the tests, and all kinds of bells & whistles.  Lets see how this looks with something more complex:


The test groups are collapsible, allowing for easy at-a-glance browsing of the test results.  Don’t like this?  Want to output your test results to your fancy new Google glasses instead of the browser?  Cool!  Roll your own by extending from Configuration class and you’re all set.

Summary
The revised unit test framework that is coming soon will provide an extensible, platform-independent solution for Dart programmers.

If you’re interested in taking a look at my patch, it can be found here: https://github.com/dart-lang/dart/pull/3

The source code for my enhanced html output is here: html_enhanced_config.dart

3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi,
    Great work.
    I had changed the CSS to fix the padding on the right.
    .unittest-group
    {
    width:100%;
    padding: 6px 0px;
    }
    I also had to put the following on a single line because the group statuses were broken:
    div class='unittest-group-status unittest-group-status-${groupPassFail ? 'pass' : 'fail'}'></div

    ReplyDelete
  3. @Jan

    Thanks! I'm admittedly not a CSS pro - more like a semi-pro. My solution also uses flexbox for horizontal layouts, which may break once the new flexbox standard comes into the retail browsers.

    I have a little note in the back of my mind to submit another patch about this at some point.
    If you feel up to submitting a patch into Dart for this stuff, you are very welcome! I'd love to see more folks listed in the Dart AUTHORS file. :)

    ReplyDelete