Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts

Thursday, September 17, 2015

Mock your Dojo AMD modules with StubModule.js

When testing AMD modules it is sometimes necessary to verify how it interacts with it's dependencies. For example, you might be writing a module that makes XHR requests using dojo/request and you want to make sure that it's passing the correct parameters. How would you test this? Creating a wrapper around the request method in your module and then spying on that method would work. You could also store the request method as a property of your module and spy on that in your tests. However, both of these solutions lead to messy code and there's something that feels wrong to me when adding code to production modules just for testing purposes.

You might think that it would be as easy as adding a map config to the Dojo loader and pointing dojo/request to a mocked module. While this is a possible solution it means that you have to create a separate file for each mock that you use and it gets very messy if you want to mock the same module multiple times within a single test page (since modules are cached by the loader).

StubModule.js provides a cleaner way to solve this problem. It allows you to stub modules with no dependencies on external files and no side effects to pollute your other tests. It does this by using the map config mentioned above as well as require.undef which is a Dojo-specific method that removes a module from the cache.

Using this tool is fairly straight forward. stub-module.js returns a single method that accepts two parameters. The first is the module identifier (MID) of the module that you want to test. The second is an object with keys that are MID's of the dependencies that you want to mock and values that are the mocked returned values. The method returns a promise that resolves with the stubbed module. For example (using Jasmine):

it('this is a demo', function (done) {
    var stub = jasmine.createSpy('request');
    stubModule('test/Module', {'dojo/request': stub}).then(function (StubbedModule) {
        var testObject = new StubbedModule();
        testObject.makeRequest();
 
        expect(stub).toHaveBeenCalledWith('some/url');
 
        done();
    });
});

To be honest I was surprised that I couldn't find an existing project that met my use case before I wrote this project. Did I miss something? Also, I wonder if the API of this project could be simplified. Any suggestions?

Tuesday, November 18, 2014

How to Wire up Travis-CI to your JS Projects

For the past six months, AGRC has been using Travis CI to automatically test and lint our projects each time we push a commit to the associated GitHub repository. Even though we run these tasks locally it's been helpful to have them run on Travis for when we miss things. It's also a major step towards automated deployments as well as running our tests via something like Sauce Labs or Browser Stack.

travis-ci.org

The set up is relatively simple. The first step is to sign into travis-ci-.org with your GitHub account. Once you're signed in you can go to your accounts page and see all of the GitHub repositories associated with your account. Switching a repository to "ON" tells Travis-CI to start watching any new commits that you push to that repository.
accounts page

.travis.yml

The next step is to let Travis-CI know what you want it to do. The first part of this step is accomplished by creating a .travis.yml file at the root of your project. Here's an example from one of our projects:
language: node_js
node_js:
  - '0.10'
before_install:
  - npm install -g grunt-cli
  - npm install -g bower
  - npm install
  - bower install
notifications:
  email:
    on_success: never
The lines below before_install load all of the project dependencies via npm & Bower. The notifications code just tells Travis to only send us emails when a build fails.

package.json

The second part to defining what you want Travis-CI to do is to add a scripts property to the your package.json file for your project. Travis-CI automatically runs npm test for NodeJS projects. Adding this new property to package.json defines this command. We use a special travis GruntJS task to run tasks so this is the command for us:
"scripts": {
    "test": "grunt travis -v"
}
The travis grunt task can contain any sub-tasks that you want. Here's what ours looks like:
grunt.registerTask('travis', [
    'if-missing:esri_slurp:travis',
    'jshint',
    'connect',
    'jasmine:app',
    'build-prod'
]);

Build Status Badge

The icing on the cake is to copy code from Travis-CI to your app's README.md to show a "build:passing" or "build:failing" (gasp!) badge. You can do this by going to your project's page on travis-ci.org and clicking on the badge in the upper right-hand corner of the page.

GitHub.com Integration

After getting everything wired up you'll notice that pull requests automatically display the build status of each commit and will let you know if it is still waiting on a build to run.
still waiting
still waiting
good to go
good to go
If you want to see all of this in action you can checkout the AGRCJavaScriptProjectBoilerPlate repository.