Front End TDD
For Fun and Profit
Victor Aponte
Front-end Dev @ Wells Fargo
gh: FunnyDewd
@FunnyDewd
Impromptu Survey
Why I test...
Then, one day...
TDD
T.D.D.
(Test Dat code! Dammit!)
BDD
B.D.D.
(Blame Dat other Developer)
but seriously...
Focus on Testing
There are a lot of different types
Unit Testing
(This is where TDD/BDD usually comes in.)
Here we test the individual functionality of the object/component you are coding.
Your tests are completely focused on the
singular piece of code you're writing.
singular piece of code you're writing.
Integration testing
( this is a very different mode of testing )
Here you test how your code fits in with the
other components in your application.
other components in your application.
In front end dev, this also means how
your code can be interacted with.
your code can be interacted with.
Think of how it integrates with the rest of the page/app.
Others
- Component Integration
- Systems Integration
- Stress Testing (load testing)
- Quality Assurance Testing
- User Acceptance Testing
- Drug Testing
- Sobriety Testing
- ... and many more ...
Testing Styles:
-
TDD - Test Driven Development
-
BDD - Behavior Driven Development
TDD Style (a la qunit):
module("User Registration: Validation");
test("validate user input", function() {
var emailIsValid = function_to_validate_email(user_input);
ok(emailIsValid, "Validation successful");
};
test("verify unique email in database", function() {
var emailExists = function_to_search_db(user_input);
ok(!emailExists, "Email is unique and can be added to db.");
};
module("User Registration: Save to DB");
test("verify user record is saved to DB", function() {
// This assumes DB.save() returns a truthy/falsey value
ok(DB.save(user_input), "Record saved successfully");
};
BDD Style (jasmine):
describe("User Registration", function() {
describe("While validating the registration info", function() {
it("should make sure the email address is valid", function() {
expect(function_to_validate_email(user_input)).toBeTrue();
});
it("should verify the email doesn't already exist", function() {
expect(function_to_search_db(user_input)).toBeEmpty();
});
});
describe("While creating the user's database record", function() {
it("should save successfully in the database", function() {
expect(function_to_save_user(user_input)).toBeTruthy();
});
});
});
TDD is Terse
User Registration: Validation - validate user input 1. Validation Successful - verify email does not exist in db 1. Email is unique and can be added to DB. User Registration: Save to DB - verify user record is saved successfully 1. Record saved successfully.
Tests show clear linear test progression.
BDD is narrative
Describe User Registration While validating the registration info - it should make sure the email address is valid - it should verify the email doesn't already exist ... While creating the user's database record - it should save successfully in the database ...
Tests are expressed in behavioral terms
Ok, but what kind of tests should I write??
What you should be Unit testing:
- Instantiation
- Error Handling
- API
- State changes
- DOM changes
- Functions/Calculations
- Events/Behaviors
- Performance
What you shouldn't be Unit testing:
- Third party libraries/frameworks (like jQuery, backbone)
- Remote services (like twitter, github api) *
- Application related services (database, messaging, etc.) *
- Other libraries and modules written by your team *
*Remember: These are done during integration testing.
TDD/BDD Workflow
The tools for Front End Testing
- Testing Framework/Library (for JS & DOM)
- Mocks, Stubs, Spies & Fixtures (oh my!)
- Command-line based test runners
For the Jargon Cup
- Fixtures
- Spies
- Stubs & Mocks
- Assertion Library
- Matchers
- Sync vs Async testing
Testing Frameworks
- QUnit
- Jasmine
- Mocha
- Buster.JS
- YUI Test
- JSUnit
- DOH
- Screw.Unit
- and many more...
QUnit
- Developed by the jQuery folks
- Designed to run inside the browser
- TDD Style
- QUnit is easy to get started with.
- Supports Async testing
- Easy support for DOM testing
- Supports Fixtures
- No built-in support for Spies & Mocks
Jasmine
- Brought to you by Pivotal Labs (popular in rails)
- Also designed to run in the browser
- Supports BDD Style
- Built-in support for function spies
- Supports Async testing
- Supports custom matchers
- No built-in support for fixtures and mocks (jasmine-jquery)
Mocha.js
- Written by Mr. VisionMedia (TJ Holowaychuk)
- Originally for Node testing
- Supports both TDD and BDD style
- Does NOT come with an assertion library (chai.js)
- Supports Async testing (super easy!)
- No built-in support for spies, mocks and fixtures (js-fixtures)
- Global Leak Detection
- Displays slow running tests
- Configurable timeout for tests
Command Line test runners
- Guard, Guard-Jasmine, Jasmine-Headless-Webkit (ruby)
- Cucumber/Capybara (ruby)
- Testem (node)
- Karma (node)
Guard-Jasmine
-
Ruby Based
-
Uses a "headless" browser for DOM testing
- Supports file watching
- No built-in support for multi-browser testing (Selenium)
Cucumber/Capybara
- Ruby based
- Specifically for doing Integration/User Acceptance tests
- Also uses a headless browser
- No built-in multi-browser testing. (Selenium, watir)
- Uses Gherkin for describing user actions
Testem & Karma
- Node.js based
- Supports many testing libraries (QUnit, Jasmine, Mocha)
- File watching to re-run tests when files are updated
- Creates a "server" in which each browser loads and runs tests.
- Each browser runs the test suite and reports back the results to the server which is reported by the command line interface.
- Testem is easier to set up and run, while Karma is more extensible (via plugins) and is highly configurable.
- Testem has a nicer UI than Karma.
My Testing Stack...
- Karma (via Grunt.js)
- Jasmine (including spies)
- Jasmine-jQuery (for fixtures, extra matchers)
- occasionally Sinon.js (for mocks & stubs)
Demo: Getting Started with Karma
Conclusion
Stay testing my friends!
Front-End TDD
By funnydewd
Front-End TDD
Presentation for Charlotte Front End Dev meetup on front end testing.
- 4,832