Meteor Testing — Simple architecture targeting

The testing story for Meteor improved dramatically with the arrival of Meteor 1.3 as testing became a first class citizen. Files in the tests directory and files named *.tests.js can be loaded automatically with a single command.

What this means is that you can write tests in files with a certain filename pattern and know they’ll not be included in normal builds of your app. When your app runs in test mode, those files will be loaded (and nothing else will), and they can import the modules you want to test. As we’ll see this is ideal for unit tests and simple integration tests.

However, one part of Meteor’s testing story remains a frustration.

Where should the tests be run?

Meteor is awesome. With Meteor you can write code that runs on both the client and the server effortlessly. However, Meteor’s unique ability to cross the client-server boundary makes for an additional step when writing tests.

By default, test files are loaded on BOTH the client and the server. This can cause issues if you only want to run certain tests on only the client or the server (eg. UI tests)

How can I specify where tests are run?

As of now, there are two (not awesome) ways to have tests run on only the client or the server.

Directory structure

One possible solution is to place architecture-specific test files in their own client or server directory (per Meteor’s default load order). This method is utilized in Meteor’s example Todos App. However, much of the stated goal of 1.3 was to remove the need to change application structure to accommodate Meteor’s load order and this also makes it impossible to keep application code in close proximity to test code. Not awesome.

“If” blocks using Meteor.isClient and Meteor.isServer

Another method used in the Todos App is checking Meteor.isClient and Meteor.isServer and only running test code if those checks pass. This is a bit better, but still feels pretty not awesome. Having large if-blocks all throughout your code becomes unreadable and sloppy.

If only there was a way to obtain the same result without adding more blocks of code.

Isn’t there a better way?

Now there is!

I wrote the ecwyne:describe-target package to solve this exact problem.

This package exposes new serverDescribe and clientDescribe methods that work exactly as advertised. Simply rename your calls to the describe function and you’re good to go! No large if-blocks, no additional indentation at all.

An added benefit of this pattern is the ability to specify any check before running your test code. Have some tests you only want to run on Sundays? No problem!

const sundayDescribe = predicateDescribe(new Date().getDay() == 0);
sundayDescribe('example sunday test', function(){
it('only runs on Sunday', function(){
expect(new Date().getDay()).to.equal(0);
});
});

Pass any value or function to the predicateDescribe function and you’re good to go!

Granted, this package isn’t earth shattering and it’s not going to revolutionize the way Meteor developers build applications, but it took something that felt profoundly not awesome in my day to day development and made it feel pretty awesome. :)

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.