Sass Unit Testing

We all know that testing is good, and most of us hopefully already write tests for our front-end JavaScript code – but is it needed for our Sass code as well?

We need to think about long-term maintenance as our Sass projects and libraries gets more and more powerful. Just look at some of the things Sass can do today, things nobody would’ve imagined just a few years ago:

The term Sass unit testing is not referring to visual regression testing of the visual end-result, but instead logical unit tests focused on the core functions of a library. The term is also not referring to linting of sassor scss, if that’s what you’re looking for scss-lint may be for you.

The logical testing of functions that an entire project relies on, just makes plain sense – additionally creating tests upfront prevent regressions later. Testing your individual functions will force you to break up your code into small modular functions, and maybe even adopting techniques like object oriented css.

Continuous integration

If you’re using continuous integration in your deployment process you are probably already running existing tests before deploying, the first step to making sure your Sass doesn’t break on deployment is making sure that it can compile with errors.

In case you’re already using Grunt for your local development workflow it would make sense to just make Grunt run your test and build tasks. If you’re using Travis it’s just a few simple steps to make your Grunt tasks run on every new build.

No matter what build system you are using, the key is that the build will fail if compilation of Sass/Compass fails - the last thing we want is for broken output css to make it into production.

Bootcamp

A BDD-style framework that doesn’t rely on any frameworks.

Bootcamp is developed by James Kyle who have done some crazy things with Sass, checkout his GitHub. The syntax for Bootcamp is clean and obvious, especially if you’ve worked with BDD frameworks in other languages before. You begin a new test suite by calling the mixin describe with the title for the spec suite and then the @content block inside:

@include describe("A suite") {
  @include it("contains spec with an expectation") {
    @include should(expect(true), to(be(true)));
  }
}

Specs are called by the mixin it which just like describe takes the name/title and a @content block. The spec contains at least one expectation which evaluates to either true or false, a spec with at least one false assertion is a failing spec.

The syntax for defining suites and specs are important, but the matchers that are available in assertions are just as important. Bootcamp comes with a bunch of rich matchers already included. An extensive list and demo of each matcher is right here.

It’s possible to disable suites and specs by changing the mixins to xdescribe and xit, just like Jasmine.

Installation

You can install Bootcamp from either npm or Bower:

$ npm install bootcamp --save-dev
$ bower install bootcamp --save-dev

After installing Bootcamp you’ll probably want to add it to your Sass :load_paths, instructions for Grunt and Compass:

npm   './node_modules/bootcamp/dist'
bower './bower_components/bootcamp/dist'

tests.scss

@import "bootcamp"; // or "[node_modules|bower_components]/bootcamp/dist/bootcamp" if you didn't set load_paths

@include runner-start;
@import "specs/example";
@include runner-end;

To run Bootcamp and get the results of the test suite simply compile the tests.scss file. If you’re using Grunt in your workflow please see a full working example in the official documentation.

The wiki for Bootcamp includes a full working example.

True

A TDD-style framework inspired by QUnit.

True is developed by the talented Eric M Suzanne who also gave a great talk at SassConf ‘13.

In True you define a suite with the mixin test-module with the title of the suite/module and again utilizing the @content block:

@include test-module('Column Math') {
  @include test('[function] is-symmetrical()') {
    @include assert-true(true, 'Number should be symmetrical');
  }
}

Individual specs are defined with the mixin test which again takes a name/title. True contains 4 different assertion-types: assert-true, assert-false, assert-equal and assert-unequal.

Installation

True can be installed with RubyGems:

$ gem install true

After installation you’ll need to add the following line to your config.rb:

require 'true'

It can also be installed with Bower or by copying the Sass directory from the project.

After install creating a test suite is a simple as creating a main test file. tests.scss

@import "functions/all"; // functions we want to test
@import "true";

@include test-module('Column Math') {
  @include test('[function] is-symmetrical()') {
    $s: is-symmetrical(12); // externally defined function

    @include assert-true($s, 'Number should be symmetrical');
  }
}

A great production example of True can be seen found Susy Next.

Going forward

As Chris Eppstein mentioned in his talk “It Takes a Village to Raise a Website” at SassConf ‘13, the community/ecosystem really needs to rally around these new unit testing frameworks.

We as a community need to figure out what it is that we want to test. What is missing in the current frameworks and maybe even in the Sass language. How are we going to do unit testing in Sass in the future.

Do we want a standard set of assertions and matchers in the Sass language, which we as a community can build different language/syntaxes on top of?


Update 1: Corrected mistakes in section about True, especially about dependencies on Compass, Ruby etc. Thanks to Eric for correcting me.