Using tags to run select Cucumber tests

Today I learned… that I can “tag” select Cucumber scenarios and run just the tagged ones, speeding up my testing and making it faster to debug a failing test.

I’m working with Ruby Cucumber tests for my current project and as the tests grew in number and complexity, I found myself wanting a way to run just a specific test.

If your tests are set up anything like mine, you can just add a tag with an @ symbol to your tests like so:

@javascript @tagname
Scenario: Verify that the thing in the thing works
Given I am already logged in
And the page has finished loading
Then the thing should be in the thing

When you run your Cucumber tests from the command line, just add –tag @tagname as an argument:

cucumber --tag @tagname test/specs/features/testfile.feature

This is just a simple implementation that might be useful if you are trying to debug a single test. Taken to its logical conclusion, you could have entire suites organized under different tags for different purposes, environments, etc.

More Reading

Most of what I know about Cucumber tagging came from krazyrobot.com’s excellent guide on Cucumber tagging.

cukes

Two ways to inject a service into a Mocha Chai test

Today I learned… there are [at least] two ways to inject a service into Mocha unit tests using the Chai assertion library and Angular mocks. This is just a little thing, but I’ve seen this difference in a few unit testing tutorials and it confused me the first time I came across it.

In my project I have a service called mealsServer. No need to worry about what it does, for now we’re just testing that it gets injected successfully (in other words, exists).

Service Injection Technique #1:

Here I am declaring mealsServer as a variable and then injecting _mealsServer_ using beforeEach:

var mealsServer;

beforeEach(inject(function(_mealsServer_) {
    mealsServer = _mealsServer_;
}));

The underscores are an oddity. The underscores are a little syntax trick that make it possible to use the same name for the injection as we use for the variable. In other words, if we didn’t inject _mealsServer_ wrapped in underscores, then var mealsServer would need a different name. I’m all for keeping names consistent whenever possible, so I’m glad I learned about this.

Service Injection Technique #2:

And here’s an alternative: here I am injecting the mealsServer service as part of the it block:

it('should have a working meals-server service', inject(function(mealsServer) {
 expect(mealsServer).to.exist;
 }));

I’m still learning the ropes of unit testing, so I’m sure there are advantages/disadvantages to each of these approaches. I’m relying a lot on this tutorial: Testing AngularJS Apps Using Karma to get me started.

Personally, I like injecting the service in the same line of code that relies upon it being there. I think this is neater and will hold up better as this file becomes longer.

For reference’s sake, here’s the complete meals-test.js file below. It’s small right now, but just getting to the point of having (any!) tests run successfully was a several hour endeavor. In this version, I am just testing that my services exist and I’m using technique #2 from above.

I am using Mocha as my testing framework, Chai as my assertion library, and my project (and its tests) get Browserified so the requires as there to ensure the modules can be found. I also use Karma to run the tests and PhantomJS as my headless browser.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
'use strict';
 
require('../../../app/js/app.js');
require('angular-mocks');
 
describe('Testing services', function() {
 
 beforeEach(angular.mock.module('cbmApp'));
 
 it('should pass a simple test: true = true', function() {
 expect(true).to.equal(true);
 });
 
 it('should have a working meals-server service', inject(function(mealsServer) {
 expect(mealsServer).to.exist;
 }));
 
 it('should have a working user-factory service', inject(function(userFactory) {
 expect(userFactory).to.exist;
 }));
 
 it('should have a working file-reader service', inject(function(fileReader) {
 expect(fileReader).to.exist;
 }));
 
});

Whew! Now that that works, it’s onwards to writing more thorough unit tests!