Test Driven Development with Meteor

    Arunoda Susiripala
    Share

    If you’ve followed the tech scene recently, Meteor won’t be anything new to you. We hear lots of good news about Meteor every week.

    If you haven’t  heard of it before, Meteor is a revolutionary JavaScript framework that allows you to create realtime single page web applications very quickly. It’s an OpenSource project, but unlike other projects, it has serious funding to keep up the rapid development.

    Meteor is not a toy anymore

    Although Meteor is still young, many people are keen to build high volume production apps with it. This is because it solves a real problem and allows developers to focus on the application logic rather than worrying about how to manage communications between the server and the client.

    Here, we’re talking about production quality applications, not prototypes anymore. So before we ship a single line of code, we need to test it. Unfortunately, Meteor doesn’t have an official testing framework – yet. But they do have a testing framework called tinytest, to test Meteor packages – but not the whole app.

    What should a meteor testing framework look like?

    When you are developing a Meteor application, you write both the server and client code together and they are tightly interconnected. So, we should be able to write test cases involving both the client and the server.

    Meteor is all about realtime and how we can share data between clients (browsers). So a testing framework should be capable of writing test cases involving multiple clients.

    And most of all, it should be fun.

    Introducing Laika – a testing framework for meteor

    Laika is a feature rich testing framework for meteor that satisfies all the above requirements. Laika is not the first, nor the only testing framework, but it is the easiest to use and well documented.

    Website: http://arunoda.github.io/laika/

    With Laika, you can write tests targeting both the server and client. And it can work with multiple clients. Laika runs tests against your actual application, not with some mocks or stubs, so it makes your tests more accurate.

    Laika - Testing Framework for Meteor

    Setting up the system

    Laika does some magics behind the scene for you. So it needs some third party tools to be available on your system.

    • install nodejs – Laika runs on top of nodejs
    • install phantomjs – Laika uses phantomjs to create clients
    • install mongodb – Laika needs an external mongodb database for each test

    Additionally,

    • you need to run mongodb while running the test
    • use this command to start mongodb with some optimizations for Laika

    mongod --smallfiles --noprealloc --nojournal

    Finally, install Laika with sudo npm install -g laika.

    Getting Started Guide

    We’ll test a Meteor Collection in two scenarios.

    1. Inserting a document from a client and observe it from the server
    2. Inserting a document from a client an test another client got it correctly

    Let’s create our Meteor app

    We need a Meteor application to test. Let’s create it.

    • create a meteor app with meteor create hello-laika
    • cd into hello-laika

    Then create a file named collections.js with the following content:

    Posts = new Meteor.Collection('posts');

    This app is available on github.

    tests folder

    All the Laika tests files should reside under the tests folder in your Meteor app. tests is a special folder in that the files in it won’t be included in either client or server. This is a rule of Meteor itself.

    Let’s write our first test

    Create a file named posts.js under our tests folder with the following content: (there is no restriction for the filename, you can name it whatever (.js) you like)

    var assert = require('assert');
    
        suite('Posts', function() {
          ltest('using both client and the server', function(done, server, client) {
            server.eval(function() {
              Posts.find().observe({
                added: addedNewPost
              });
    
              function addedNewPost(post) {
                emit('post', post);
              }
            })
    
            server.once('post', function(post) {
              assert.equal(post.title, 'hello title');
              done();
            });
    
            client.eval(function() {
              Posts.insert({title: 'hello title'});
            });
          });
        })

    This is written in nodejs and all the built-in node modules can be used in the tests. And if you are familiar with writing tests with mocha, this should all be familiar.

    Here, we are observing the Post collection for new documents in the server. And we insert a document using a client, which triggered our observation.

    Let’s review the code.

    • first line we are loading nodejs assert module to do assertions
    • then we create a test suite named ‘Posts’
    • inside our suite, we can create our test (using ltest method) with a name and a callback
    • in callback we accept server and client were used to evaluate code inside the server and client
    • server.eval() method allows us to evaluate code inside the server
    • you can send some results back to test with emit() and catch it with server.once or server.on
    • client.eval() behaves in the same way but evaluates the code inside the client
    • the rest of the code is self explanatory

    Run the test

    After you’ve created tests,

    • go to project folder
    • run Laika

    You’ll see something like below. If you get an error, double check your test code.
    laika test result

    Create our second test

    Create the following test inside your test suite Posts.

    ltest('using two client', function(done, server, c1, c2) {
          c1.eval(function() {
            Posts.find().observe({
              added: addedNewPost
            });
    
            function addedNewPost(post) {
              emit('post', post);
            }
            emit('done');
          })
    
          c1.once('post', function(post) {
            assert.equal(post.title, 'from c2');
            done();
          })
    
          c1.once('done', function() {
            c2.eval(insertPost);
          });
    
          function insertPost() {
            Posts.insert({title: 'from c2'});
          }
        });

    Here, we are observing a collection in one client and another clients insert a document. Let’s review it.

    • Now we have 2 clients (c1 and c2) instead of one in the previous test
    • You can specify any number of clients as above and laika can create clients for you
    • if you look at first c1.eval(), there are two emit() calls.
    • we can emit() from the server/client any time to the test
    • they can be caught via .on() or .once()

    Real life use case

    Now you have seen how to use Laika. But Laika can do more. It can test Meteor-specific functionalities very quickly. Some of them are:

    • Meteor methods
    • Publications/Subscriptions
    • Permissions
    • Authentication
    • Authorization

    A few examples can be found here – http://arunoda.github.io/laika/examples.html

    How Laika works internally

    As developers, we are always curious about how internals work. So in this section you’ll see how Laika works internally.

    Laika does isolated testing

    Laika runs a separate app with a clean db for each test you write. Each test is isolated from another so you don’t need to worry about cleaning states of your app and the database.

    For this reason, your tests will run bit slower.

    Server and test communicate via TCP

    In your test case, you can simply evaluate Meteor code inside the server, but internally Laika can do some hard work for you. When you start testing, Laika injects some server-side code into your Meteor app. Then it starts a TCP server and Laika connects to it.

    Once you call .eval() method, Laika will send it to the server via TCP connection. If any result available (calling .emit() in server), it also sends back to the server via the same connection.

    Laika cleans injected code from your app at the end.

    Client and server communicate via PhantomJS

    Just like the server, Laika does some magic for you under the hood. For every client you request, Laika creates a client using PhantomJS and code will be evaluated on it. PhantomJS is webkit browser without a UI, so we do real client testing here.

    Laika uses mocha

    Laika’s main goal is to be the testing framework for meteor targeting its unique requirements, not to create another JavaScript testing framework. mocha is a really good and widely used JavaScript/NodeJS testing framework, and we use it internally. So most of the options available in mocha are also available in Laika.

    See laika command line options

    Error Handling

    Mistakes are common to human beings, so it is natural to write some tests with errors. It could be on the test itself or code targeted to evaluated on server or client. Laika does handle these errors and report back to you, so you can fix it right away.

    Laika - Error Reporting

    Unfortunately, Laika cannot show you which line number caused the error, but it will show you in which test it has occurred and the context.

    Syntax Sugar

    You’ve seen that Laika uses EventEmitter pattern (or something similar) to communicate between evaluated code and the test. This is really useful if you want to trigger multiple results from the evaluated code.

    But if you want to send a single result and test depend on that result, EventEmitter style could be a headache. Sometimes, you’ll end up in callback hell too.

    Laika knows the pain and it has the .evalSync() method which allows you to write synchronous code. .evalSync() is available on the both server and the client. This is possible due to each test being run inside a Fiber.

    Let’s see it in action

    With EventEmitter style

    ltest('with eventEmitter style', function(done, server, client) {
          server.eval(function() {
            //assumes we do some real async work
            setTimeout(function() {
              emit('some-data', {data: 'data'});
            }, 100);
          });
    
          server.on('some-data', function(data) {
            client.eval(function(data) {
              //do something with the data
              emit('result', true);
            }, data);
          });
    
          client.on('result', function(result) {
            assert.ok(result);
            done();
          });
        });
    
    ### With .evalSync() synchronously
    
        ltest('wiht .evalSync()', function(done, server, client) {
          var data = server.evalSync(function() {
            setTimeout(function() {
              emit('return', {data: 'data'});
            }, 100);
          });
    
          var result = client.evalSync(function(data) {
            //do something with the data
            emit('return', true);
          }, data);
    
          assert.ok(result);
          done();
        })

    You can see the difference. You must use special emit('return', {some: 'data'}) to send execution back to the test. It is also possible to use other emit() events but they must occur after emit('return').

    But .evalSync() only works on the main test callback

    That’s right, evalSync() only works inside the main test callback. If you try to invoke it from a nested callback, it gets failed. See the following example, and it gets failed.

    ltest('failing .evalSync()', function(done, server, client) {
          server.eval(function() {
            emit('some-event');
          });
    
          server.on('some-event', function() {
            var result = client.evalSync(function() {
              emit('return', true);
            });
            assert.ok(result, true);
            done();
          });
        })

    Laika evalSync() inside a nested callback

    Laika – the project

    Laika is released under the OpenSource MIT license and you can use it for any purpose. It is highly appreciated if you can mention Laika in a blog post or in a tweet.

    The project is hosted on github – Laika Testing Framework for Meteor.

    Laika is a new framework – released in mid-May 2013. It is well-tested, but there could be some edge cases. If you have a bad time with Laika, or have something to say, use our issue tracker on github or contact me via @arunoda.

    So. What are you waiting for? Test your Meteor project with Laika and ship it today.