Making JS Tests


Fast, Easy, and Friendly


 http://cascadiajs2014.formidablelabs.com

 @ryan_roemer | formidablelabs.com

Tip - space bar advances slides

JS in the Modern World

JavaScript applications are getting larger and more complex.

Our developer community is growing. Our technology ecosystem is exploding.

Yay!

Photo Credit: Brooklyn Morgan

But is it Good JS?

Our apps are now critical.

The JavaScript must be robust and reliable.

Testing!

So, we test — to find bugs early, build confidence in our code, and allow us to change things without breaking everything.

Testing?

In theory, we agree we should test.

In practice...

The Reality

"Crying"

An Observation

If dev's won't write or run the tests, your technology and processes don't matter.

Will avoid when

  • Difficult (to write)
  • Slow (to run)
  • Daunting

but, seek when

  • Easy
  • Fast
  • Friendly

Some tips from the trenches...

Formidable Labs

... and from teaching

Backbone.js Testing

Our Focus

Our examples will be frontend unit tests.

... but should apply to your backend, integration, and non-JS tests.

The Periphery

We're not going to talk about:

  • wiring up frameworks
  • debating stacks (Mocha, Jasmine, etc.)
  • how to substantively write tests

Let's Make it Better

... and help dev's actually write, run, and (maybe) love the tests.


    

Making Tests Easy

The tools and process should make the tests easy to learn, write, and run.

Why Is Testing Hard?

  • Browser idiosyncrasies
  • Events, timing, async I/O
  • Test tools, DOM/data fixtures

1. Set a Foundation

Build your infrastructure :

  • Should be in place from the start (or ASAP)
  • Integrate and automate (GitHub, Slack, Travis, etc.)
  • Choose good tools ...

1. Set a Foundation

The tools enable organization and flexibility.

  • Reporting (esp. failures)
  • Asynchronous support
  • Assertions
  • Node.js? Use the same tools

1. Set a Foundation

TL;DR?

A Foundation Demo


                describe("CascadiaJS", function () {
                  it("is awesome!", function () {
                    expect("CascadiaJS")
                      .to.include("JS").and
                      .to.not.equal("dull");
                  });
                  
                  it("fails without love", function () {
                    expect("the tests").to.contain("love");
                  });
                });
                

2. Lower Barriers to Entry

  • Make no assumptions
  • Provide test skeletons / "Get out and push"

Photo Credit: Andy Pixel

3. Write it Down

New dev's should be able to get started with just the docs.

  • The test stack
  • Conventions, best practices, guides
  • Anything you learn, as you learn it
  • And iterate

Photo Credit: Viktor Hanacek

4. Teach & Learn

  • Have an on-boarding process and training
  • Promote and expect mentorship
  • "Baby Steps" - Identify small chunks of test work to learn on

Making Tests Fast

The tests must run blazingly fast.

Photo Credit: Folkert Gorter

What is "Fast"?

Whole suite runs in < 30 seconds

  • (Yes, the whole thing)
  • Aim for < 5 seconds

Why Is Testing Slow?

  • Network
  • Timers, waits
  • UI effects

1. Know What to Look For

  • Ignore pure JavaScript code execution
  • Network / communication outside of JS
  • Explicit waits in code (setTimeout, etc.)

2. Find the Slow Pokes

Need a good test reporter.

  • Test timing results
  • Flexible / different output formats

Find The Slow Tests! Demo


                it("is fast", function () {});
                it("is sort of slow", function (done) {
                  setTimeout(done, 51);
                });
                it("is really slow", function (done) {
                  setTimeout(done, 300);
                });
                it("times out", function (done) {
                  setTimeout(done, 2001);
                });
                

3. Fake It

Use fakes for anything slow / external.

  • XHR / backend servers
  • Timers
  • Use Sinon.JS to patch JS internals
  • Tests should run on an airplane with no internet

Photo Credit: Folkert Gorter

Fake It! Demo


                it("is faked and fast", function (done) {
                  var clock = sinon.useFakeTimers();
                  setTimeout(function () {
                    clock.restore();
                    done();
                  }, 5 * 60 * 1000); // Wait 5 minutes!
                  
                  // Simulate 5 min, 1 ms
                  clock.tick(5 * 60 * 1001);
                });
                

4. Offer Shortcuts

Provide "relief" if not blazingly fast (yet).

  • Run test subsets (.only, grep)
  • Single-browser runners (e.g., just PhantomJS).

Making Tests Friendly

The culture should support testing and embrace new developers.

Why Is Testing Daunting?

  • Variety of backgrounds, experience
  • Learning curve
  • Organizational obstacles

1. Find Champions

Testing is too hard to "just pick up"

  • Identify or create "test leads"
  • Spread responsibility and fan out

2. Win the Higher-Ups Over

Educate your boss(es):

  • Create good stories for the cost of bugs vs. stage in pipeline
  • Track bugs avoided and regressions

2. Win the Higher-Ups Over

If you are a higher-up, support the tests:

  • Allocate sprint / developer time
  • Fine to ask for process / priority / goals
  • But don't make dev's re-justify the tests!

Bringing it all Together

  • Your infrastructure should make it easy for folks to jump into and write tests
  • Your infrastructure should be blazingly fast, so dev's don't have to wait
  • Everyone should contribute to making the process of running and writing the tests friendly and supported

Go Forth and Test!

These are just some of the techniques you can use to bring the love to testing.

Read the docs! Try it out! Ask for help!

Thanks!

 http://cascadiajs2014.formidablelabs.com

 @ryan_roemer | formidablelabs.com

Tip - space bar advances slides