Test Case

The base class for any Aria Templates test is aria.jsunit.TestCase. On top of basic assertions it allows to assert logs and events, it provides mocking and sandboxing. This is ideal for pure JavaScript classes that don't need DOM interaction.

Here is an example of unit test class.

Aria.classDefinition({
    $classpath : "SyncTest",
    $extends : "aria.jsunit.TestCase",
    $prototype : {
        testAssertTrue : function () {
            this.assertTrue(false, "This assertion is false");
        }
    }
});

A Test Case (cf. API doc) will usually feature several single test methods. All tests are supposed to be completely independent from each other, and the order in which they are executed should not be taken into consideration.

When running a TestCase, all the methods defined in the prototype and with a name starting with test will be considered as test methods. It is mandatory to follow this naming convention.

The scope of a test method is the test case and no return value is expected. The status of the test is determined by the result of the various asserts made during this test. A test method containing no failing assert is considered as successful if no JavaScript error was thrown during its execution.

Assert

The possible assertions that can be done from within a test case are defined in aria.jsunit.Assert and are

  • assertTrue / assertFalse Test if a value is true or false
this.assertTrue("a truth-y value");  // assert fail

// assertTrue(value) corresponds to: assertEquals(value, true)
  • assertEquals / assertNotEquals Test that two values are strictly equal
var number = 12;
this.assertEquals(number, 12);   // true
this.assertEquals(number, "12"); // false

// assertEquals(one, two) corresponds to: assertTrue(one === true)
// It's preferable to use assertEquals over assertTrue for easier debugging
  • assertJsonEquals / assertJsonNotEquals Test for deep equality of objects / array
this.assertEquals([1, 2], [1, 2]); // false
this.assertJsonEquals([1, 2], [1, 2]); // true
this.assertJsonEquals({
  one : 1,
  two : 2
}, {
  two : 2,
  one : 1
});    // true
  • assertJsonContains Assert that an object is included in a bigger container
var serverResponse = {
  one : 1,
  two : 2,
  // other values
  end : "eventually"
};
this.assertJsonContains(serverResponse, {
  one : 1
});   // true
  • assertLogsEmpty Test that no class logged an error message
  • assertErrorInLogs Test that a precise error has been logged
someClass.$raiseError("Error while having fun");
this.assertErrorInLogs("Error while having fun");   // true

Error messages for which a corresponding assertion is not performed will make the test fail

  • fail Explicitly let the test fail with a given message
if (number > 10) {
  this.fail("I'd like a smaller number");
}

Error Message

assert* methods accept as message parameter used to better understand why the assert failed. It is usually the first parameter after the value(s) being asserted, for more information refer to the API documentation.

this.assertEquals("a", "A", "In a case insensitive world, letter %1 equals %2");
// It'll log
// In a case insensitive world, letter "a" equals "A"

Asynchronous testing

Asynchronous tests are a special kind of test methods, and their name should start with testAsync

The easiest way to do an asynchronous test is to directly call the asynchronous method, passing a callback defined in the Test Case. This callback will then be responsible of notifying the tester when the test is finished.

The callback can be defined in the prototype of the Test Case, but in this case, make sure its name doesn't start with test, otherwise it will be picked up and executed on its own as a test method.

To notify the test runner, aria.jsunit.TestCase provides the notifyTestEnd method.

Aria.classDefinition({
  $classpath : "AsyncTest",
  $extends : "aria.jsunit.TestCase",
  $prototype : {
    testAsyncMethod : function () {
      someClass.callMeLater({
        fn : this.methodCallback,
        scope : this
      });
    },

    methodCallback : function () {
      this.assertTrue(true);
      this.notifyTestEnd("testAsyncMethod");
    }
  }
});

Fixtures : setUp / tearDown

If several tests in a single test case are using the same kind of objects in their tests, it can be interesting to define the setUp and tearDown methods in the $prototype of the TestCase. These two methods are called before and after each test method.

Aria.classDefinition({
  $classpath : "Fixtures",
  $extends : "aria.jsunit.TestCase",
  $prototype : {
    countSetUp : 0,      // 2 at the end of testing
    countTearDown : 0,   // 2 at the end of testing

    setUp : function () {
      this.countSetUp += 1;
    },

    tearDown : function () {
      this.countTearDown += 1;
    },

    testOne : function () {},

    testTwo : function () {}
  }
});

Listening events

In some cases we want to assert that an event has been raised or not by a given class. This is a basic form of spy. Assert provides the following methods

  • registerObject / unregisterObject Listen to all events fired by a given object
  • assertEventFired / assertEventNotFired Assert that en event with a given name has been raised
  • getEvent Get the event object of a given event name, useful to assert that parameters are passed correctly.
The following is an example test case using assertEventFired
Aria.classDefinition({
  $classpath : "Events",
  $extends : "aria.jsunit.TestCase",
  $dependencies : ["anotherClass"],
  $prototype : {
    testEventFired : function () {
      // We mu register an object to be able to assert that it's raising events
      this.registerObject(anotherClass);

      // Call a method that raises an event
      anotherClass.callMe();

      this.assertEventFired("callMeDone");
    }
  }
});