Micrologger proof of concept

By Adam Grant | Copy the Snippet (v0.0.1)

Open your browser's JavaScript console to see Micrologger work.

Micrologger is the JavaScript testing framework that is always running, making sure each and every interaction from your users behaves as expected.

How is this different from other testing frameworks like Mocha.js?

Micrologger is designed to be used, not only during CI but on production itself. This is because test failures can sometimes be the result of particularities in the user's context.

Wouldn't it be nice to be notified when a user sees a JavaScript error and what the context of that error was?

Conceptual differences

Assertions and expectations are two-sided. The first side lives on the user's interaction

var requestNews = function() {
  // Expect that a list of news articles will be returned.
}

And the other side lives on the application.

var getNewsViaAJAX = function() {
  // Return whatever data was fetched to that expectation.
}

Micrologger also exposes the reporting functions for passed and failed tests, allowing you to use for 3rd party reporting tools like Mixpanel

Just override $ml.pass(message) and $ml.fail(message, args).

$ml.pass = function(message) {
  mixpanel.track("Successful interaction", { message: message });
}

$ml.fail = function(message args) {
  mixpanel.track("Error", { message: message, args: JSON.stringify(args) });
}

Stupidly small

The idea of loading a testing framework as a dependency on production doesn't sound very tempting, so Micrologger has been made very small and simple, relying on built in JavaScript logic for testing. The additional load is truly negligible.

Examples

The button on the left will expect you to press the button on the right in three seconds.

Open your console to see Micrologger output.

 

What happened?

On the event listener for Button 1 we registered a simple assertion

$ml.waitForButton = new $ml.Assert("button was pressed in less than 3 seconds", 3000);

On the event listener for Button 2 we simply made a call to the function we created from button 1.

$ml.waitForButton.return()

waitForButton is a custom name, you can create any name you want after $ml

Specs

We can also bundle tests into specs. Let's use the same example but we want to see that the second button is pressed both less than 3 and less than 5 seconds.

 

What happened?

When we pressed the first button, the event listener created a new spec with two assertions.

$ml.specs.waitTwiceForButton = new $ml.Spec([
  $ml.waitForButton = new $ml.Assert("button was pressed in less than 3 seconds", 3000),
  $ml.waitForButton = new $ml.Assert("button was pressed in less than 5 seconds", 5000)
]);

On the second button, again, we just call return on the function we created in button 1's event listener.

$ml.specs.waitTwiceForButton.return();

Expect

How about conditional logic? Let's use Expect to compare two numbers.

This button will check if the variable is equal to 1.

Now these two buttons will set a variable equal to 1 or 2 respectively. And run the test.

 

What happened?

First, our get one button set up an expectation

$ml.getOne = new $ml.Expect("variable is set to 1", function(variable) {
  return variable === 1; // We'll use plain old JavaScript to return true or false.
});

Next, each of our buttons set the return value. We could have also done this in reverse order and called return on the button that did the expectation.

// Button 1's event listener
var someVar = 1;
$ml.getOne.return(someVar);

// Button 2's event listener
var someVar = 2;
$ml.getOne.return(someVar);

Adding it all together

Now let's use both assertions and expectations in a spec.

We expect that a variable is set to 1 in less than 3 seconds

Now, one of these will need to be pressed in less than 3 seconds and sets the var equal to 1.

 

What happened?

In the first button's event listener, we created a spec.

$ml.specs.getOneQuickly = new $ml.Spec([
  new $ml.Expect("variable is set to 1", function(variable) {
    return variable === 1;
  }),
  new $ml.Assert("variable is set in less than 3 seconds", 3000);
]);

Now each button just needs to return the variable to the spec function we created.

// Button 1's event listener
someVar = 1
$ml.specs.getOneQuickly.return(someVar);

// Button 2's event listener
someVar = 2
$ml.specs.getOneQuickly.return(someVar);