But How Do I Test, Really?!?! – Rhett Lowe – Why don't you test?



But How Do I Test, Really?!?! – Rhett Lowe – Why don't you test?

0 1


but-how-do-i-test-really

Slides on how to test. Basics for testing in the modern JavaScript Environment.

On Github rhettl / but-how-do-i-test-really

But How Do I Test, Really?!?!

A definition and functional description of how to get started testing in Modern Javascript.

Rhett Lowe

  • Work at i-Showcase, Inc.
  • AngularJS for 12+ months
  • GitHub
  • Google+

this is me. I am not in many places yet and I haven't been on the scene long, but I have been working hard and learning much.

Why don't you test?

Reasons people give

  • "I don't have the time."
  • "My boss isn't into it."
  • "I know my code works."
  • "I don't see the point."
  • "I have legacy code."

These reasons are all crap really

  • While this takes you longer to write the first time around, it saves you massive amounts of time in the future. Effectively a little time now = less or no extra time in the future
  • Bosses can be swayed once they see how much time it can save them and how much security they can gain by having a test suite.
  • I know my code works too, but does it work tomorrow after the intern has a go with it?
  • ... No comment ...
  • This one is the only reason Misko Hevery states is an acceptable answer to why NOT to test.

Reasons people don't give

(but are more true)

  • "I don't know how."
  • "I don't know how to get started."

More often then not we all know HOW to test on a theoretical sense. This is similar to how I as an engineer have a theoretical working knowledge of the internal workings of the combustion engine. That said, I cannot fix a combustion engine nor would I know the first thing about where to start or really how to build one from scratch.

Most of us work in multiple environments with multiple different testing requirements and unless we already know how to do tests in all of those environments we wont do testing at all -- or at least on the lenguages we don't know how to test on.

We usually don't give thees answers because we know how bad it makes us look as programmers. When we talk to other programmers, whether they test or not, we feel guilty that we don't test and we know that we should be testing even though we aren't.

Don't feel guilty, Just try testing. It really is not that difficult and it isn't hard to work into your workflow.

Javascript and Testing

(Before)

  • JS is horrible for Cross-ENV
  • JS is horrible for testing
  • Different browsers => Different tests
  • Internet Explorer!

JavaScript used to be a bitch to work with as little as 5 years ago. It was a pain impossible to truly write cross-env code.

Internet Explorer is evil. It is everywhere and supports NOTHING that is common to other browsers

Javascript and Testing

(Now)

  • Major Backlash
  • Frameworks and languages meant JUST for JS
  • YOU CAN TEST INTERNET EXPLORER!!!

Where do I start??

What does this mean??

Words we have heard

  • Jasmine
  • Karma
  • Testacular
  • Spec
  • Test Runner
  • Test Framework
  • Test Driven Development (TDD)
  • Behavior Driven Development (BDD)

Definitions

  • Jasmine :: This is a simplified language to make testing easier to read as if it were in english. It is a Testing Framework
  • Karma :: This is a platform to run tests automatically and in many browsers. It is a Testing Framework
  • Testacular :: was the original name for Karma. Same thing. when you see it think Karma instead of testicle.
  • Spec :: This is a set of requirements for your code written in english. It is not always written by the developer. It is used to help better write testing.
  • Test Runner :: Any program meant to control when to run tests, what tests to run, and on what platforms/browsers to run them.
  • Test Framework :: is a platform/language to simplify your test running.
  • TDD :: This is a paradigm to help modify your workflow putting Spec-design and test writing first and coding second. The paradigm is sound and it makes knowing WHAT to program and WHERE to start much easier.
  • BDD :: is a modification of the TDD paradigm. It puts users first, then specs, then tests, then code.

I'll explain more about most of these in future slides.

Test Driven Development

  • Boss gives you list of requirements => Spec
  • Write Spec in language of tests => Test Suite
  • Write Code to pass tests
  • Tidy up code to make it more efficient

Behavior Driven Development

  • Boss gives you list of requirements => Spec
  • Write Spec in language of tests => Test Suite
  • Consider how a user would mess things up
  • Write Code to pass tests and make users happy
  • Tidy up code to make it more efficient

Let's Put it Together

None.js - Platform
Karma - Test Runner
Jasmine - Test Framework
Source Code - Actual Code
var Calc = function(start) {
 this.total = start || 0;

 this.equals = function() { /* ... */ };
 this.clear = function() { /* ... */ };

 this.add = function() { /*... */ };
 this.subtract = function() { /*... */ };
 this.multiply = function() { /*... */ };
 this.divide = function() { /*... */ };

 this.less = this.minus = this.subtract;
 this.greaterThan = this.plus = this.add;
 this.and = this.by = this.times = this.multiply;
 this.over = this.dividedBy = this.divide;
};

This is how they all fit togeather.

  • Karma Runs on Node.js
  • Jasmin runs through Karma
  • Your source code runs inside the Jasmin tests
  • No, Node.js is not needed for Testing
  • No, Karma is not needed for Testing
  • No, Jasmin is not needed for Testing
  • Yes your code is needed

If you want to test your code, AngularJS or not, and you want half the work done form you, you will need Jasmine (or at least some testing framework). Frameworks are the best way to do QUICK tests that give you UNDERSTANDABLE fail messages

If you know that your code is ONLY going to run in one version of one browser, and you plan to run your tests through github or want to invent some procedure for WHEN you run your tests you may. Karma knows all these things for you. It does them all easily. Just tell it WHEN to test (ex: every save or before every commit) and what to test on and it will handle everything else. No need to waste time deciding when to run it and opening each browser individually, just run it ALL THE TIME and test in ALL browsers (or most)

Karma sits on Node.js. Is there any question why it is awesome!

In short... <Next slide>

Do I need all this extra crap??

I just want to test!

Do I need Jasmin?!?

NO!

but...

  • It is the best way to write you tests QUICK
  • Best way to have UNDERSTANDABLE failure messages

Do I need Karma?!?

NO!

but...

  • Simplest answer to "When do I test my code?"
  • The Answer is ALWAYS
  • Simplest answer to "What browsers/platforms do I test on?"
  • The Answer is ALL/MOST OF THEM

Do I need Node.js?!?

NO!

but...

  • Karma runs on Node.js
  • You don't need to know Node.js
  • Just install and configure Karma
  • Nothing to it.
  •  
  • Plus, it is AWESOME

Moral of the section?

Use Node.js, Karma, and Jasmine

Save yourself the headache

Let's examine the building blocks

Source Code - Actual Code
var Calc = function(start) {
 this.total = start || 0;

 this.equals = function() { /* ... */ };
 this.clear = function() { /* ... */ };

 this.add = function() { /*... */ };
 this.subtract = function() { /*... */ };
 this.multiply = function() { /*... */ };
 this.divide = function() { /*... */ };

 this.less = this.minus = this.subtract;
 this.greaterThan = this.plus = this.add;
 this.and = this.by = this.times = this.multiply;
 this.over = this.dividedBy = this.divide;
};

Example of running the Calc

var calcA = new Calc(5)
    .plus(6).greaterThan(10).add(1, 3)
    .less(10).minus(1, 2)
    .by(30).and(10)
    .over(3).dividedBy(16);

console.log(calcA.equals()); // equals 75

Where is the error?

Calc definition or usage of Calc

var calcA = new Calc(5)
    .plus(6).greaterThan(10).add([1, 3])
    .less(10).minus([1, 2])
    .by(30).and(10)
    .over(3).dividedBy(16);

console.log(calcA.equals()); // equals NaN

If we had a test ...

We would be more secure in our answer

Our first test!!

Enter Jasmine

How spec-writing is made simple

Describe() It()

describe('A Number', function(){
    var number = 0;

    it('should equal 0 in the beginning', function(){
        expect(number).toEqual(0);
    });
    it('should be 5 after adding 5', function(){
        expect(number + 5).toEqual(5);
    });
    it('should not equal 10 when adding 3', function(){
        expect(number + 3).not.toEqual(10);
    });
    //it('should equal 10 when adding 3', function(){
    //    expect(number + 3).toEqual(10); // This will fail
    //});
});

Jasmine test Passing

Jasmine test failing

Make a spec for our Calc

Our Spec

  • A Calc should add 2 numbers
  • A Calc should subtract 2 numbers
  • A Calc should multiply 2 numbers
  • A Calc should divide 2 numbers
  • A Calc should accept multiple args

Our Calc Tests

describe('A Calc', function(){
    var calc;

    beforeEach(function(){
        calc = new Calc(0);
    });

    it('should add 2 numbers', function(){
        expect(calc.plus(2).plus(10).equals()).toEqual(12);
    });
    it('should subtract 2 numbers', function(){
        expect(calc.plus(2).minus(10).equals()).toEqual(-8);
    });
    it('should multiply 2 numbers', function(){
        expect(calc.plus(2).times(10).equals()).toEqual(20);
    });
    it('should divide 2 numbers', function(){
        expect(calc.plus(2).over(10).equals()).toEqual(0.2);
    });
    it('should accept multiple args', function(){
        expect(calc.plus(2, 10).equals()).toEqual(12);
    });
});

It Passed!!

To run this

<link rel="stylesheet" type="text/css" href="...jasmine.css">

<script type="text/javascript" src="...jasmine.js"></script>
<script type="text/javascript" src="...jasmine-html.js"></script>
<script type="text/javascript" src="...boot.js"></script>

<!-- include source files here... -->
<script type="text/javascript" src="...Calc.js"></script>

<!-- include spec files here... -->
<script type="text/javascript" src="...CalcSpec.js"></script>

That is it!!

Who needs Karma!

Jasmine - Test Framework
Source Code - Actual Code
var Calc = function(start) {
    this.total = start || 0;

    this.equals = function() { /* ... */ };
    this.clear = function() { /* ... */ };

    this.add = function() { /*... */ };
    this.subtract = function() { /*... */ };
    this.multiply = function() { /*... */ };
    this.divide = function() { /*... */ };

    this.less = this.minus = this.subtract;
    this.greaterThan = this.plus = this.add;
    this.and = this.by = this.times = this.multiply;
    this.over = this.dividedBy = this.divide;
};

But does my code work in...

Internet Explorer?!?

(dum dum DUUMM!)

How to test for IE

  • Go to IE and run code,
  • Look for red or green
  • This takes time
  • What about other browsers?
  • What if I forget to run it in IE?

Karma's Selling Points

  • Easy setup to test against:
    • Multiple Browsers
    • w/ Multiple Versions
    • w/ Multiple Configs
  • Tests can run in Shell or Server somewhere
  • Has plugins for most common systems including:
    • Require.js
    • Grunt
    • Gulp
    • AngularJS
  • While easy to set up also has EXTENSIVE advanced setup

How to setup

Install Node.js and NPM :: Nodejs.org Install Karma Initialize Karma

(After Node.js and NPM Install)

$ npm install karma --save-dev

$ npm install karma-jasmine karma-chrome-launcher --save-dev

$ ./node_modules/karma/bin/karma start
INFO [karma]: Karma v0.12.3 server started at http://localhost:9876/

$ npm install -g karma-cli
Karma Installation

Setup

Install karma itself in your project Add on any plugins you may want Start the server -- it will give you a location to reach it. If you prefer using the Command Line interface install the CLI You are now ready to set up Karma

This was taken almost directly from the Karma website

Configuration

$ karma init my.conf.js

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture a browser automatically ?
Press tab to list possible options.
Enter empty string to move to the next question.
> Chrome
> Firefox
>

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> *.js
> test/**/*.js
>

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

Config file generated at "/Users/vojta/Code/karma/my.conf.js".

$ karma start my.conf.js
Karma Configuration
  • Start by telling Karma where to init.
  • We will use Jasmine
  • No i don't include Require.js
  • List all the browsers you want
  • List where your tests are
  • List file exceptions
  • Turn file watcher on or off. This will run every time you save changes to a file and tell you if you broke something.
  • then start karma with the config file.

Karma can also write the file in coffee fi you prefer

I have yet to figure our how to run Internet explorer on Ubuntu in a way that is worth the amount of effort required, but I think you must have the browser on your computer to make it work. I was going to ask Rit Lee tonight, but he was called away and is not here.

Start Karma with Watchers On

Added New Tests and Saved

describe('A Calc', function(){
    var calc;

    beforeEach(function(){
        calc = new Calc(0);
    });

    /* ... Previous Tests ... */

    it('should res-et back to 0 when res-et', function(){
        expect(calc.plus(1,2,3).times(10).clear().equals()).toEqual(0);
    });
    it('should set the total to any number with set()', function(){
        expect(calc.set(100).equals()).toEqual(100);
    });
});

Added New Tests and Saved (cont.)

Added set() function to pass test

None.js - Platform
Karma - Test Runner
Jasmine - Test Framework
Source Code - Actual Code
var Calc = function(start) {
 this.total = start || 0;

 this.equals = function() { /* ... */ };
 this.clear = function() { /* ... */ };
 this.set = function() { /* ... */ };

 this.add = function() { /*... */ };
 this.subtract = function() { /*... */ };
 this.multiply = function() { /*... */ };
 this.divide = function() { /*... */ };

 this.less = this.minus = this.subtract;
 this.greaterThan = this.plus = this.add;
 this.and = this.by = this.times = this.multiply;
 this.over = this.dividedBy = this.divide;
};

Quick Review on TDD

(Test Driven Development)

Talk to Boss -> Get Spec Convert Spec to Test Suite See Tests Fail (red all over) Write code to pass tests See Tests Pass (green all over) Tidy up and make more efficient Check for failures

Downsides to TDD

Writing Code just to pass tests !== Good Code !== User Friendly

Enter BDD

(Behavior Driven Development)

Modifications to TDD

  • Consider the User above all else
  • Consider how code SHOULD be; not JUST to pass tests
  • Remember to write tests that help the user

Overall: Remember the user is not a computer

What's Next?

This Presentation Online

github.com/rhettl/but-how-do-i-test-really