Saturday, February 11, 2012

Readable Unit Tests

So I wanted to write a bit about unit testing... in *ghasp* Java. Obviously unit tests in java are nothing new, but I find that there are many techniques for making it very readable and useful.

I use Mockito for mocking and TestNG for the actual testing framework. This makes a big impact on the usefulness of tests.

First on TestNG. Number one is the testng.xml which is a really nice way to list your groups of tests. This is great for organizing -- fast tests vs "slow" tests like integration.

Then is @DataProvider. This is in my opinion TestNG's biggest strength. Makes writing multiple scenarios simple as a test becomes the wiring, the data provider is the scenarios. This is one thing I will focus on in this post. While I will assume you are familiar with DataProvider (just read the docs if not) there are some tricks to it. In order for it to be useful you want the scenarios to be readable and to really drive your tests.




@DataProvider(name = "traderAlertScenarios")
public Object[][] traderAlertScenarios() {
    return new Object[][] {
        {true, true, true, Category.JTT, times(1)},
        {true, false, true, Category.JTT, times(1)},
        {true, true, false, Category.JTT, never()},
    };
}


@Test(dataProvider = "traderAlertScenarios")
public void trader_alert_scenarios(
    final boolean entitledToTrade,
    final boolean preferenceEnabled,
    final boolean workspaceVisible,
    final Category sessionType,
    final VerificationMode expectedResult
) {
    mockUserAsTrader();
    setEntitledToTrade(entitledToTrade);
    setPreferenceEnabled(preferenceEnabled);
    setWorkspaceVisible(workspaceVisible);
    Event e = buildEvent(sessionType);


    toTest.handle(e);


    expect(mockMessageGenerator, expectedResult).generate(e);
}


Now, this unit test sets up the environment and tests that the many levels of the handler are invoked depending on the logic, in the end a message is generated and goes somewhere. This will test that the generation happened, which means all the branching logic passed. However, look at the data provider. It is incomprehensable. You need a reference every time you stare at those boolean flags, even writing more is painful.

So I cleaned it up a bit.


@DataProvider(name = "traderAlertScenarios")
public Object[][] traderAlertScenarios() {
    return new Object[][] {
        {ENTITLED_TO_TRADE | PREFERENCE_ENABLED | WORKSPACE_VISIBLE, Category.Auction, times(1)},
        {ENTITLED_TO_TRADE | WORKSPACE_VISIBLE , Category.Auction, times(1)},
        {ENTITLED_TO_TRADE | PREFERENCE_ENABLED, Category.Auction, never()},
    };
}



@Test(dataProvider = "traderAlertScenarios")
public void trader_alert_scenarios(
    final int flags,
    final Category sessionType,
    final VerificationMode expectedResult
) {
    mockUserAsTrader();
    setEntitledToTrade(hasFlag(flags, ENTITLED_TO_TRADE));
    setPreferenceEnabled(hasFlag(flags, PREFERENCE_ENABLED));
    setWorkspaceVisible(hasFlag(flags, WORKSPACE_VISIBLE));
    Event e = buildEvent(sessionType);


    toTest.handle(e);


    expect(mockMessageGenerator, expectedResult).generate(e);
}




There. Same thing, except this time the booleans don't murder you. Now you have 3 (actually in my case 15) scenarios and all of them are readable. I spent some time with indentation to make it really easy. These are the sort of tests that make unit testing pleasant.


Of course this goes hand in hand with dependency injection and hard core OOP design. The good separation of concerns let me mock each dependency easily via Mockito, inject it, and set up all these scenarios in a snap.


Hope this helps a bit.

Friday, February 3, 2012

Wow, the mac touchpad. It still baffles me how much I use it.

I have never been a touchpad kind of guy. Ever. In fact every chance I got I would use the mouse. Touchpads were a nuisance. They interfered with my ability to type. They made simple operations hard. They were not comfortable. Made me use my fingers in ways that were not pleasant.

But then I got this Macbook Air. It all changed. All the awkward motions of touchpads disappeared. I will start with the most basic and work to advanced features.

Lets start with the single click. On a regular touchpad I had two options: tap-to-click or click the left button. The left button is WAY out of the way, so I always had tap-to-click. TTC sucks because if I accidentally touch the touchpad, the cursor clicks somewhere and makes me lose my typing place. very disruptive. On the mac, not an issue. I have two choices: tap-to-click or click the whole damn touchpad. The whole thing is a big easy-to-press button. No awkward motions, just ease of use.

Next, right click. On a regular touchpad I had one option: Right click button. With special drivers, two finger tap. The right click button was always hard to get to due to me using my right hand.  The two finger tap suffers from same problems as single click. On Mac, no problem. I have two choices, two finger click, or click on the lower right side of the touchpad. I like two finger. Never an issue, and never out of the way.

Next, drag. On a regular touchpad drag is click twice, the second click makes you go into drag mode. In drag mode you move your finger not letting go until you want to drop the thing. On Mac, again its better. The touchpad is made of a material that is quite slippery, unlike non-mac touchpads. But better than that, the action is click with one finger, and use a second finger to drag. So motions like move a finger right, let go, move it left, touch again, and right again, which is how you move "far" on the screen is never an issue. In fact it is straight up pleasant.

Next, scrolling. On a regular touchpad scrolling is a special place on the touchpad that scrolls up or down. It's rather annoying since missing it you just move the cursor around, and hitting it accidentally is annoying. Also I like to use that space for motion, but it winds up scrolling. Recently two finger scrolling has been gaining some half-decent implementations. On a mac, two finger scrolling in any direction. Marvelous. Love it more than a mouse actually.

Next, in OSX 10.7 there are multiple desktops via full screen applications or an awkward interface to create multiple. You scroll through them with four finger swipes left and right. This is great.


This is pretty much all I use. What is interesting is that I find it more awkward to use a mouse on a mac than a touchpad. My fingers are already in place, as it is perfectly located, to use it, rather than move to the mouse. I wind up not moving my hands at all while I am using the mac. The whole "all you need is a keyboard" mentality disappears when your mouse is right there, though I still prefer keyboard over touchpad.

So some unscientific accuracy numbers:
Accidental clicks while I am typing:
Mac: ~1%
Windows: ~30%, I had to disable large chunks of the touchpad to just be able to type.

Accidental right click while trying to scroll:
Mac: ~1%
Windows: ~50%, two finger tap and two finger scroll combined = recipe for accidental right clicks.

Accidentally missing the scrolling:
Mac: 0%
Windows (old style touchpad): ~30%

Accidentally scrolling instead of moving mouse:
Mac: 0%
Windows (old style touchpad): ~15%

Ability to start drag:
Mac: 100%
Windows: 70%, 30% of the time I wind up double-clicking the icon instead of dragging it.

Ability to drag anything into exactly desired target in first drag:
Mac: 90% meh sometimes my finger just lets go by accident
Windows: 50%, usually I have to drag twice or more to get it into the right spot, or ensure my finger starts on the oposite end of the touchpad when I even begin dragging.


So there you have it, on my mac I wind up not using the mouse. On a windows machine I dread touching the touchpad, sometimes even using the "disable touchpad" feature. Hell having that feature is a workaround for a real problem.

Scanners and Dead trees. Going paperless can be liberating...

So my wife bought us a HP 8600 Pro printer. At first I was reluctant, but it has been quite liberating.

The main feature is that aside from the standard all-in-one printer setup it contains a multi-page, duplex, scanner feeder. Using this I was able to scan about 20 lbs of bills and important documents that I have kept around in a drawer, and store it into google docs. That means for lets say $5/year I can meet ALL my document storage needs for the next 20 years or so. I get 1 gig of space on google docs free. I doubt I can fill it up, but if I can $5/yr is damn cheap for a highly available, fully backed up service.

This is quite liberating. Basically closet space is expensive, disk space is cheap. And since google has nice data liberation I don't feel trapped by storing with them.

The only issue left is OCR and searchability. That would require a custom server, or a tool which takes your documents, OCRs them, and gives you a searchable document mechanism. But even without this, I am no worse off than before, except now it's all digital, takes up no space, no weight, no unsorted papers, it's all just there.

Another potential gain is I should split the PDF files into 10MB increments so google docs can live-preview them, and virus scan. But that is pretty much it.



Other nice things part of this printer: email printing - I get an email address with a whitelist and anyone emails sent to it from the whitelist are printed. Also google cloud print integration. This stuff is nice.

Wednesday, February 1, 2012

Why I Hate Javascript

I am hoping CoffeeScript will resolve some of these problems, but many are fundamental problems with JS.

1) The defaults are all crap. == operator is 99% useless. Sometimes it is nice to compare '1' == 1 or x == null (or undefined). However the thruthification of things and fun things like "\n \t\r" == 0 being true are insane. Variables are global by default, local via var. That is just... oh so wrong.

2) Clusterfuck of overrides. That means that if I have an object, call it O. And O has a property "foo". "foo" can be a method (function), foo can be "defined" as a class-level method. foo can be injected later as a method. foo can be accidentally overridden into an object. There is just so much that can go wrong, that many languages check at compile time.

3) No static typing. You may say "static typing is too restricting" to which I answer, no, it is freedom. You see if you look at ActionScript, AS has a hybrid ECMA script. It is javascript except it has classes. You can define something as a dynamic object, or something as a class. The great thing about classes is you can give a method arguments that expect a certain type. And a compiler will tell you about it. That means tools like IntelliJ can know where the definition is letting contextual navigation happen, compiler can complain about bugs before they even happen, and it can be optimized at compile time. In AS statically typed objects run much faster because much better assumptions can be made by the compiler.

4) Function arguments are a joke. The arguments "array" is what arguments really are. It has vararg but not in a nice mechanism. In fact look at coffeescript:


race = (winner, runners...) ->
  print winner, runners
race = function() {
  var runners, winner;
  winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  return print(winner, runners);
};

It is basically complex by default.

In the end, these things really mean one thing: Great for rapid prototyping, bad for long-term development. I can see why some developers keep away from JS like the plague. JS's strength is it's object orientation combined with functions as first class citizens. It's weakness is a completely fly-by-the-seat-of-your-pants object creation strategy, hidden overrides, and lack of maintainability.

This is why I am hoping Dart takes off. It has the potential to resolve these core problems.

Tuesday, January 31, 2012

Why I love Backbone.js (data bindings really)

So I've been playing around with backbone.js. And I have to say I love it.

First thing I noticed is how little backbone does. It is actually quite small. Sure it does a few things about object creation, constructors, initialization behavior, but that's really it.

The biggest strength is data binding events. "change:foo" event fires when the foo attribute changes. On a collection add/remove/reset events fire. This is powerful. Not to mention custom events.

This basically means that all you need to do is wire everything correctly, have a view render your collection/model, bind appropriately, and boom the entire page changes whenever the model is updated.

One thing I've been implementing is this filtering model
https://github.com/dlikhten/filtered-collection
https://github.com/dlikhten/paginated-collection
The big advantage here is that I set up a chain of filters, and just update them independently, and the displayed elements just update.

In my setup I have the following:

a main collection (main)
a filter on main (f1)
a filter on f1 (f2)
a filter on f2 (f3)
a pagination on f3 (p1)

I give p1 to a view which renders all the elements (data view).

f1 is given to a view to apply f1 filters (f1 view)
f2 is given to a view to apply f2 filters (f2 view)
f3 is given to a view to apply f3 filters (f3 view)

p1 is given to a pagination view which renders page #s, clicking on a page # will tell p1 to change itself to the given page (p1 view)

now I have power

I don't need to do anything else. Data view will react to things like add/remove/reset events that data/f1-f3/p1 trigger. So whenever stuff happens data view will just re-render.

Since the events trickle down (if f1 is filtered, f2 filters, then f3, then p1 etc) I don't care which filer gets modified and when, it just all renders correctly. Furthermore p1 view does not need to track which page we are on. When p1 notifies of it's own changes, p1 view just re-renders with the new total number of pages and vuala pagination auto updates.

Just wire once and stop worrying. That's backbone's motto (it seems). I am sure I will hit performance issues sooner or later, maybe not :P