Tag Archives: tdd

Testing Javascript Singletons

Testing javascript singleton modules can be a challenge, especially ones that maintain some sort of internal state. Examples of singletons that manage internal state are usually either a factory or cache manager. In order to effectively test these sorts of modules, you often either resort to exposing a method to reset the state, or carefully order your tests… until now!

To eliminate this problem, I propose the following solution (assuming you’re using a spec-style test):

  1. Wait to require the module you’re testing until all stubs, spies, and mocks are defined in a beforeEach
  2. require the module you’re testing after stubbing/spying/mocking in the beforeEach
  3. in the afterEach, remove the module you’re testing from the require.cache
    • this effectively destroys the singleton and when it is require‘d again the the beforeEach it will be rebuilt.

Here’s how you remove a module from the require.cache:


I’m assuming that you have your tests in a sibling directory to a lib directory, where your production modules live. If not, you can adjust the path spec accordingly.

Other things to be mindful of are:

  • Event listeners (both DOM and custom events)
  • The state of the DOM itself
  • Callbacks you’ve stored off in the body of stubs and/or spies within your test suite

These are all things that need to be cleared out in the afterEach as well.

But wait, I’m a front-end developer and I use karma or testem to execute my tests in a real browser. Well, I personally believe runners are a source of pain and frustration and should be avoided. However, it is theoretically possible with karma to achieve this by removing the script element that corresponds to the module you’re testing in the afterEach and then append it back immediately after removing it. I am not familiar enough with testem to give equivalent advice.

TDD and BDD With The MEAN Stack: Introduction

As the MEAN stack is growing in adoption, a variety of testing strategies have sprouted up on the interwebs. As I have started to dig deeper into automated testing strategies for both sides of the MEAN stack, I have found it difficult to find advice or material on how to setup an environment to support the mockist style of test-driving the implementation. Many articles offer some light recommendations, but are typically more classicist-oriented. I’d like to help fill the gap by outlining a tooling strategy which I believe enables the following:

  • Automation
  • Mockist unit testing
  • BDD/ATDD testing
  • End-To-End system testing

In case you want to dive straight into the code, I’ve set up a project on github to prove out the technology.

I’m going to assume you’ve already got a working MongoDB and Node.js environment. If not, take a look at a vagrant solution or mean.io.

One of my goals has been to try to find tools that can work on both the server and the browser. I also put a lot of stock into automation, so I have aimed to avoid tools that require manual loading of browser pages to launch the tests. This has proven to be quite a challenge, but the xUnit-side of testing is much closer to that goal than the BDD-side. However, all hope is not lost.

Let’s get down to business and outline the tools that are working well on both sides:

  • Grunt – The task runner
  • Mocha – The test framework
  • Chai – The assertion library
  • Sinon – The stub, spy, and mock swissarmy knife

Some tools are sort of in the middle, where they can be made to work in both the browser and the server, but they aren’t rock solid in one or the other:

  • Yadda – BDD layer that works nicely with Mocha+Chai (needs a little help on the browser side, but I’m working on that)
  • Cucumber-js – (BDD) works great on the server-side, but fails in the browser side (particularly because of a lack of support for karma integration)

And finally, some tools are targeted at one side or the other:

  • Karma – THE test runner for the browser
  • karma-browserifast – A browserify plugin for Karma, which is needed to automate running Yadda BDD tests in the browser
  • Supertest – Awesome library for testing Express-based RESTful endpoints
  • CasperJS – Drive user interactions through the UI (and works with Yadda)

There is more to come. I plan to write two more articles to dig further into to the details of what it means to test drive on the server side and in the browser. For now, take a look at my Yadda/Karma example on Github for BDD in the browser and thoughtsom for BDD and unit testing on the server. I plan to build out of a few more code examples on the browser side of testing before the next set of articles. In the mean time, I welcome your feedback.

P.S. I am aware of Protractor, but I have not had much of a chance to experiment with it yet.

Setting up a project using karma with mocha and chai

Recently, I was on a quest to evaluate the mocha javascript testing framework
and its direct support for async testing in the browser. I had a hard time finding a complete description of everything that needed to be done in order to get things working with karma for testing in the browser as opposed to testing a node module.

Consequently, I decided it would be useful to create a guide for those who have similar interests to save everyone time. If you want to skip the steps and just download the code, feel free to clone my github repository. As a quick aside, I decided to try mocha thanks to some frustrations with jasmine. Async testing with jasmine can be done, but it does not have first-class support in my opinion. I intend to give buster a spin in the near future as well.

This tutorial assumes that you are on a unix-based system (I used OSX to write the article) and already have a working nodejs and npm installation, therefore installing and configuring a node.js/npm environment is outside the scope of this article. With that said, let’s dig in!

  1. Create a directory to hold the project and navigate to that directory:
    • mkdir <new_dir>
    • cd <new_dir>
  2. We’ll be installing a bunch of npm modules, so let’s run npm init to build our package.json file for us
  3. Let’s install karma with npm. I recommend installing it locally, since it’s likely that you’ll be either executing karma from an IDE (such as webstorm) or as a grunt task. Additionally, one project may be configured for one version of karma while a different project can use a different version if needed.
    • npm install karma --save-dev
    • At the time I wrote this article, the latest stable version of karma was 0.10.8.
  4. Now we’re ready to install mocha:
    • npm install mocha --save-dev
  5. We’ll also need the karma-mocha adapter so we can use mocha as a test framework with karma:
    • npm install karma-mocha --save-dev
  6. An assertion library will need to included as well. I prefer the chai assertion library, since it offers both bdd style assertions using expect and should as well as junit-style assertions.
    • npm install karma-chai --save-dev.
    • Installing chai this way will make it available as a framework within karma, which makes setup much simpler.
  7. I also find sinon to be extremely useful for stubbing and spying, so let’s install it to round out our set of packages required to get our test environment provisioned:
    • npm install karma-sinon --save-dev

At this point, our package.json should have a devDependencies directive that looks something like this:

devDependencies:

We can now create our karma configuration and write some tests. Let’s first make sure that our karma installation is working correctly:

  • ./node_modules/karma/bin/karma --version

That should print out the version number to the console if everything is working correctly. If you want to, you can initialize a karma configuration file using:

  • ./node_modules/karma/bin/karma init

I’ll provide the boilerplate so you can avoid that step. Include the following configuration in a file named

karma.conf.js:

Once that file is ready, we can create a failing test to ensure our configuration is working as expected. Create a new file in src/test called test.spec.js. Create the directory:

  • mkdir -p src/test

And a test file with the following contents:

describe("A test suite", function() {
   beforeEach(function() { });
   afterEach(function() { });
   it('should fail', function() { expect(true).to.be.false; });
});

With our test spec in place, we can run karma and make sure that we can successfully execute failing tests. ./node_modules/karma/bin/karma start karma.conf.js

After running our tests, we should see some output along the lines of

A test suite should fail FAILED

If so, then you’ve successfully configured karma with mocha, chai and sinon. Cheers!

Update: 07/14/14

I recently updated this to use the new 0.12.x version of karma and also added an example Gruntfile.js