Category Archives: Tools

ES6+ code coverage with Babel plugin

babel-logo

Running unit tests against an ES6+ source code base has now become an almost trivial task, thanks to Babel and all the ecosystem around it. There are a lot of good resources explaining how to do that, with different tools and frameworks.

On the other hand, code coverage on this kind of tests is a rather less covered subject …

If you apply regular code coverage solutions to that case, you end up with reports based on the transpiled code, not your original source code in ES6+, which isn’t really relevant …

Here comes isparta

This problem was solved by isparta, a code coverage tool for ES6+, using Babel, which provides code coverage reports using istanbul (which is also a code coverage tool … ūüėČ more infos here).

Using isparta, you can generate code coverage from unit tests on ES6+ source code base, directly against your original source code (not the transpiled one). This works great, combined with tools like karma-coverage, you can output coverage reports under any format (html, lcov … that can be processed by various tools/services like Jenkins or coveralls.io …).

isparta not maintained anymore

No Maintenance Intended

About two weeks ago, @duglasduteil added the “No Maintenance Intended” badge to his module. This should remind us that behind every open source project there are developers maintaining them (most of the time on there free time).

So, now may be the time to find a replacement for isparta … I was looking for an alternative for a few days when I eventually ended up on twitter with @kentcdodds who mentionned dtinth/babel-plugin-__coverage__.

ES6+ code coverage using a Babel plugin

Since Babel v6, you can make your very own plugins that can do much more than simply transpile ES6+ to ES5.

Babel is a generic multi-purpose compiler for JavaScript. More than that it is a collection of modules that can be used for many different forms of static analysis.

Babel Plugin Handbook

That’s what @dtinth has done with babel-plugin-__coverage__. He made a babel plugin that instrument your code, injecting metadata that will be processed by istambul (which is used under the hood by karma-coverage and other coverage report tools).

The great thing is that, since you go through Babel anyway to transpile your source code, the only thing you have to do to get those infos to feed tools like karma-coverage (or any istambul-based coverage reporter) is to activate this plugin in your .babelrc file …

Using a babel plugin for coverage is a no-brainer.

@kentcdodds

You won’t have to add complex configuration or tools anymore. @dtinth‘s plugin is 300 LOC, it’s his first babel plugin that he made over two nights. As far as I have tested it, it works very well.

This is clear that using a babel plugin for that kind of purpose is the right way to proceed. Since it’s becoming easier to setup, we might see more projects using ES6+ including code coverage reports in a near futur.

You can see an example of setup on my project topheman/react-es6-redux.

Checkout it out

How to fail webpack build on error

webpack-logo

By default, webpack will tolerate any errors happening while bundling.

It’s useful when you’re running in webpack-dev-server mode, however, when you’re making your final build you might want it to fail if any error happens (the main use case being when you’re testing the build step on your CI).

For that, you can use the bail configuration option.

Here is an example of a minimal webpack.config.js setup that will fail your Travis CI tests if any error happens at build time:

const plugins = [];
const TRAVIS = process.env.TRAVIS ? JSON.parse(process.env.TRAVIS) : false;

if (TRAVIS) {
  console.log('TRAVIS mode (will fail on error)');
  plugins.push(new webpack.NoErrorsPlugin());
}

const config = {
  bail: TRAVIS,
  // ... the rest of your config
};

module.exports = config;

Resources:

Make your own React production version with webpack

react-webpack

If you’ve been developing with React, you must have seen that you are provided with very verbose errors/warnings that can come in handy.

Quote from the download page of React:

We provide two versions of React: an uncompressed version for development and a minified version for production. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages.

When you’re making your production bundle, you should not include all the extra code used in development (which makes extra checks not useful in production and at the end makes your bundle heavy).

The way to do that is to use the Webpack.DefinePlugin or envify, if you’re using browserify.

By doing the following, you’ll be injecting a variable process.env.NODE_ENV set to "production" at build time which is used inside React as we’ll see.

webpack.config.prod.js

module.exports = {
  //...
  plugins:[
    new webpack.DefinePlugin({
      'process.env':{
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress:{
        warnings: true
      }
    })
  ]
  //...
}

That way, you’ll be including¬†the same kind of code which is in react.min.js inside your bundle. If you take a look at the source code of React inside ./node_modules/react/lib, you’ll see a lot of places with a ternary like process.env.NODE_ENV !== 'production'. All those development related features will be dropped at the minification step.

Resources:

Continue reading

Optimize your bundle’s weight with webpack

webpack-logo

The usage of a package manager for the dependencies in front-end JavaScript development has become mainstream for some time now. One of the downsides is that since it’s now very easy to install and require external modules in your application, if you’re not careful, you’ll end up with a big main.js file in production …

To avoid that, you can use multiple strategies of optimization:

  • uglify
  • deduplicate code
  • split your bundle in multiple ones and only load them on demand

But the very first thing to do is to drop the unnecessary code. For that, webpack provides the Webpack.DefinePlugin which lets you inject your own variables at build time, so that if they are set to false in a conditional, the minification step will drop the dead code.

But if you are using ES6 modules import statement, there is a catch …

webpack.config.js

module.exports = {
  //...
  plugins:[
    new webpack.DefinePlugin({
      '__DEVTOOLS__': false //set it to true in dev mode
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress:{
        warnings: true
      }
    })
  ]
  //...
}

test.js

import { DevTools, logger } from 'some-devtools';

if(__DEVTOOLS__){
  DevTools();
  logger();
}

With this configuration, the code inside the if statement will be dropped at minification since it will be inlined as if(false). But you’ll still be importing those packages that you won’t be using (aka dead code).

In this case you shouldn’t be using ES6 static imports but CommonJS require syntax:

if(__DEVTOOLS__){
  const { DevTools, logger } = require('some-devtools');
  DevTools();
  logger();
}

That way, if __DEVTOOLS__ === false, not only the calls inside this if statements will be dropped but the modules DevTools and logger wont even be part of the bundle, which will make it lighter.

Note: I made this example with webpack, but this kind of feature is available on other module bundlers such as browserify. An other way to resolve that kind of problem would be to specify a list of modules to exclude at build time in production mode …

Update: If you’re doing universal JavaScript (running your code on both client and server side), a good practice would be to use process.env.DEVTOOLS instead of __DEVTOOLS__. A good example is the React setup where you make your own production version of React.

Resources:

Setup Travis CI & SauceLabs for Protractor

travis-ci-sauceLabs-protractor-bandeau

Add end to end testing to your continuous integration

You already know those technologies ? Jump directly to how to setup Travis CI & SauceLabs for Protractor.

Reminders

What are Travis CI, SauceLabs & Protractor ?

Protractor is an end-to-end test framework for AngularJS applications. It can also test any non-angular applications since it’s a wrapper around¬†WebDriverJs (which controls the Selenium Server) and Jasmine (which brings the testing framework).

seleniumVia Selenium, it will send commands to web browsers (like “click here” then “check if this is displayed”, “populate that field”, “submit the form” then “check if we are logged in” …).

SauceLabs is a cross-browser automation tool built on top of Selenium WebDriver. It lets you run your end-to-end tests on multiple browsers and operating systems, in the cloud (you can run tests in multiple vms in parallel). It integrates very well in CI tools such as Travis CI.

Travis CI is an open-source hosted, distributed continuous integration service used to build and test projects hosted at GitHub. You configure it with a simple .travis.yml file where you specify your CI workflow (you can launch test scripts as well as deploy scripts).

It will try to build your project and run your tests on each push (on any branches, including pull-requests). It supports many languages and you’ll see a lot of open-source projects using it.

If you want to know more – some resources:

Why use SauceLabs with Travis CI ?

By default, Travis CI doesn’t provide extended features for e2e testing. You’ll see that on SauceLabs, you can use your Protractor/Selenium tests “as is” (just add a little config) and get lots of interesting informations such as extended logs, screencast (video playback) …

Setup Travis CI & SauceLabs for Protractor

This part takes for granted that you already know how to run protractor tests in local.

Pre-requisites

Create a SauceLabs account

Download Travis cli

Follow these instructions to download the Travis Command Line Interface.

Setup SauceLabs credentials

Go to your SauceLabs account and retrieve your ACCESS KEY. Then, at the root of your project:

travis login

#the following will encrypt and add the tokens to your .travis.yml

travis encrypt SAUCE_USERNAME=[your-SauceLabs-login] --add
travis encrypt SAUCE_ACCESS_KEY=[your-SauceLabs-AccessKey] --add

Enable Sauce Connect addon for Travis CI

Travis CI integration with SauceLabs automatically sets up a tunnel required to get started testing with. To do that we need to enable the Sauce Connect addon for Travis CI.

To enable Sauce Connect for Travis CI, add the following to your .travis.yml file:

addons:
  sauce_connect: true

That way, the e2e tests launched on your Travis CI will be executed on SauceLabs’s Selenium server which in return will have access to the test server you’ll be running from your Travis CI – all this, via Sauce Connect’s encrypted tunnel.

running-tests-on-sauce-connect

Upgrade your protractor config

Add the following to your protractor config file. This is a basic config. It won’t affect your local tests, it will only activate when running on Travis CI:

if (process.env.TRAVIS) {
  config.sauceUser = process.env.SAUCE_USERNAME;
  config.sauceKey = process.env.SAUCE_ACCESS_KEY;
  config.capabilities = {
    'browserName': 'chrome',
    'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
    'build': process.env.TRAVIS_BUILD_NUMBER
  };
}

Feel free to customize it (if you don’t work with protractor but only Selenium WebDriver, it’s about the same).

Don’t forget to add the task running protractor to the tests to be run by Travis CI on the .travis.yml¬†file, in the script section.

Tips

Keep in mind you’ll need a server to run your e2e tests against (this is not unit testing), so you will have to launch an instance of this server in the before_script part of the .travis.yml file.

Since you are doing tests, this server might have to be in “test” mode (providing mock results on API endpoints for example).

Even if your app is full front-end and doesn’t rely on a backend you built, you will have to provide a server to run your e2e tests on (this is my case on topheman/vanilla-es6-jspm).

Good thing to know: when you develop in ES6 using runtime transpiling (like babel-runtime), a lot of different scripts are loaded (and evaled browser-side), which can raise timeouts SauceLabs-side (that you didn’t have on your local computer when running your e2e tests).

To avoid that, run your e2e tests against a bundled version of your website (all scripts/assets bundled/concateneted in one or a few files). This will relieve the traffic on the sauce tunnel and the VM, SauceLabs-side (that may not be as powerfull as your computer).

Resources

I set up Travis CI with SauceLabs for Protractor on my latest project: topheman/vanilla-es6-jspm, to have my e2e test being a part of my continuous integration workflow.

Take a look at the commit where I added the feature, it could give you some ideas of implementation …

Tophe

Edit: Using React ? Here is one of my latest projects topheman/react-es6-redux where I also setup SauceLabs (amongst other things like unit-tests, code coverage on es6+ …)