Marmara

Marmara is a Ruby Gem that analyses your css during UI testing and generates a code coverage report.

Alt text

Why is CSS code coverage important?

CSS code coverage is a little different than traditional code coverage.

Discovering Unused CSS

Removing dead CSS code will decrease the number size of your CSS that gets delivered to your user and decreases the number amount of work that client will need to perform once it receives that file, both should lead to an faster website overall and may save you server costs.

While this tool will tell you which CSS rules were untouched during testing, you shouldn't always consider a deeper analysis before modifying your source. Imagine that you have a report that looks ike the following:

 /*
  * Make all links red
  */
+ a {
+     color: red;
+     opacity: 0.9;
+ }

 /*
  * We used to colour our links blue, maybe we should remove this rule...
  */
- a.my-old-style {
-     color: blue;
- }

 /*
  * Do some old IE fixing
  */
- html.ie-9 a {
-     filter: alpha(opacity=90);
- }

As you can see here, the first a rule was used, so we definitely want to keep it but there is an older rule a.my-old-style which can probably be safely removed. The last rule however is a fix for older browsers, so we should probably consider keeping it.

Safer CSS Refactoring

Sometimes our CSS files become monoliths when it would be much better to split up a file into smaller modules. By running a subset of your tests, you can safely determine where files can be split.

Discovering Untested Features

With traditional code coverage, this is the most important factor in improving your code base, with CSS testing it is still important but to a lesser degree. If you look back at the first example, the fact that these rules are not covered may mean that you are actually not testing important features. You may want to consider adding tests for IE by using a different user agent or setting the html class programmatically.

Set up

This project has yet only been set up in a Rails Capybara/Poltergeist environment, more work may need to be done to get it woking in other environment.

It is important to run Marmara.start_recording before you run any tests and Marmara.stop_recording after testing is complete but currently the call to Marmara.stop_recording needs to happen before poltergeist as closed its connection with phantomjs. It would probably be best for us to spin up our own process to avoid this.

1. Create a Rake task

I'm using Cucumber, so I added a new rake task that looks like this:

task "css:cover" do
  Marmara.start_recording
  Rake::Task[:cucumber].execute
end

2. Capture your output

AfterStep do
  Marmara.record(page) if Marmara.recording?
end

Since I also want to capture used selectors for mobile, my after step looks more like this:

AfterStep do
  if Marmara.recording?
    Marmara.record(page)
    old_size = page.driver.browser.client.window_size
    page.driver.resize_window(600, 400)
    Marmara.record(page)
    page.driver.resize_window(*old_size)
  end
end

3. Stop recording and generate your output

at_exit do
  Marmara.stop_recording if Marmara.recording?
end

Development plan

This project is currently in a "works in my project" stage, there's still work to be done to make it more vendable so I welcome pull requests. In addition, there are probably a lot of tweaks required to the parser and a lot of features that would be nice to have.