Thursday, March 3, 2016

Rails - Testing Javascripts



  INTRODUCTION

  Developers usually are in a habit of writing specs for all our ruby code , but we tend to skip javascript tests and try writing tests in a high level.

All javascript functionalities are usually tested by manually running the application in the browser which is NOT BAD but there are a scenarios where javascript gets complicated enough.This is where it would be a good practice to introduce unit testing for javascripts. Ofcourse there are couple of ways, gems, plugins etc here we'll be picking up Jasmine.

Jasmine is a behavior-driven development for testing javascript codes and luckily the syntax resembles that of Rspec style, however the tests are written in javascript not in Ruby,Ofcourse!

Integrating Jasmine In Rails Project

 Integrating jasmine into a rails project would be as simple as

group :development, :test do
  gem 'jasmine'
end

To initialize a rails project for Jasmine
rails g jasmine:install

Writing Specs

A test suite begins with a call to the global Jasmine function describe with two parameters: a string and a function. The string is the title for a spec suite. The function is a block of code that implements the suite.

Specs are defined by calling the global Jasmine function it, which takes a string and a function as parameters The string is the title of the spec and the function is the spec, or test. A spec contains one or more expectations that test the state of the code.

Here's our hello world example.As you can see - these javascript specs kind of uses the rspec style - making it easier to grok

app/assets/javascripts/lib/HelloWorld.js
function helloWorld(){
  return "Hello world";
}
spec/javascripts/lib/HelloWorldSpec.js
describe("Hello world", function() {
  it("returns hello world", function() {
    expect(helloWorld()).toEqual("Hello world")
    )};
)};

For getting deeper into how to write more precise javascript specs Jasmine Documentation on Github would be the best place to start off!

Running Specs

Running javascript specs would now be as simple as

rake jasmine
Open localhost:8888  in your browser.This port could be altered with certain configuration settings. To re-run the test suite this page needs to be reloaded - pretty simple.This is how we run specs locally - but how do we integrate this to a CI server like travis - for that we would require GRUNT
Grunt is a javascript task runner for automation. To install grunt, first we would need to install node and npm in our local machines.
After which we need to install Grunt's command line interface (CLI) 
sudo npm install -g grunt-cli

In your project directory, run npm init to create the file package.json for your project. This file contains information about what node.js modules the project depends on.

Now to get up and running, we need the grunt package along with a grunt task that can run the tests.

npm install grunt grunt-contrib-jasmine --save-dev
The --save-dev flag will add the package as a dependency in package.json.

Finally add the configurations to a Gruntfile.js in the project's root. This file will describe different tasks run by grunt.


module.exports = function(grunt) {
  grunt.initConfig({
    jasmine: {
      tappy: {
        src: 'app/assets/javascripts/lib/*.js',
        options: {
          specs: 'spec/javascripts/lib/*Spec.js',
          vendor: 'vendor/assets/javascripts/jquery-1.8.2.min.js'
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.registerTask('default', 'jasmine');
};


* src describes where your javascript files are located.
* specs describes where your tests are located.
* vendor denotes if you have used any third-party libraries like Jquery
* loadNpmTasks enables the specified plugin .
* registerTask - default is the rask that is run when grunt is run i.e when grunt is invoked without any task being specified.

Finally run the test suite with 
grunt jasmine