JS Frameworks Day April,26 of 2014
-
Upload
da-14 -
Category
Engineering
-
view
145 -
download
0
description
Transcript of JS Frameworks Day April,26 of 2014
В поисках качества JavaScript:модульное тестированиеАнна ХабибуллинаDA-14 / da-14.com
akhabibullina
_khabibullina
ZE QUALITYS?
“Any feature without a test doesn’t exist”
Steve Loughran HP Laboratories
AGENDA
Unit Testing Concept Pros & Cons Basic Terms & Structure TDD &/vs. BDD Tools & Libraries Unit Testing Specifics in JavaScript Best Practices
UNIT TESTING CONCEPT
Unit testing is a method by which individual units of source code are tested to determine
if they are fit for use.
WHY UNIT TESTING?
Unit tests find problems early in the development cycle (TDD & BDD)
Refactoring
Integration
Documentation
Better design
IS UNIT TESTING A GOOD INVESTMENT?
slow down the development process
share the same blind spots with the code
doesn’t prove that they’re compatible with one another or configured correctly
BASIC TERMS
In simple words, the goal of assertion is to forcefully define if the test fails or passes.
STATEMENT PASSES FAILSx = 1 assert(x > 0) assert(x < 0)
expect(4+5).to.equal(9);
ASSERTION
function initialize() {
// The initialization was successful. return true;}
Given the function initialize():
ASSERTION: EXAMPLE
ASSERTION: EXAMPLE
var isInitialized = initialize();
TDD assert.isTrue(isInitialized)BDD expect(isInitialized).to.be.true
Check that function initialize() returns true when called.
FIXTURE
A test fixture is a fixed state of the software under test used as a baseline for running tests. In JavaScript for client side:
simulate AJAX responses;loading known set of data such as html objects.
FIXTURE: EXAMPLE
Require the piece of markup stored in myfixturemarkup.html file before each test:
beforeEach(function() {
loadFixtures('myfixturemarkup.html');
});
STUB
Method stubs are functions
with pre-programmed
behavior.
STUB: EXAMPLE
Forcing a method to throw an error in order to test error handling.
var fn = foo.stub().throws(Error);
expect(fn).to.throw(Error);
SPY
A test spy is a function that
records arguments,
return value, the value of this and exception thrown (if any) for all its
calls.
SPY: EXAMPLE
Test that a function cursor.hide() has been only called once, and only once.
sinon.spy(cursor, "hide");
TDD sinon.assert.calledOnce(cursor.hide) BDD expect(cursor.hide.calledOnce).to.be.true
MOCK
Mocks are fake objects with pre-programmed behavior (like stubs) and
pre-programmed expectations.They are like both stubs and spies – in
one.
MOCK: EXAMPLE
Create an expectation that jQuery.each is called once, and only once, and also instructs the mock to behave as we pre-define.
var mock = sinon.mock(jQuery);
MOCK: EXAMPLE
#1 – which method?#2 – how many times it is called?#3 – what are the arguments when the method called?#4 – what the method returns?
TEST DRIVEN DEVELOPMENT(TDD)
TDD is a software development process that…I’ll tell you the rest
WHAT ARE THESE BDD?
ALRIGHT, WHAT IS BDD YOU ASK?
Terminology:
TDD BDDTest ExampleAssertion ExpectationUnit Behavior
BASIC STRUCTURE
#1. Setup/BeforeEach/Before
#2. Prepare an input
#3. Call a method
#4. Check an output
#5. Tear down/AfterEach/After
#1. Setup / Before
before(function(done) { // Create a basic document. document = jsdom.jsdom(); window = document.parentWindow; done(); });
BASIC STRUCTURE: EXPLAINED
Before / BeforeEachbefore(function() { console.log(‘before test’); });
test(‘first test’, function() { console.log(‘first test’); });
test(‘second test’, function() { console.log(‘second test’);});
afterEach(function() { console.log(‘after each test’); });
Result
before testfirst testafter each testsecond testafter each test
BASIC STRUCTURE: EXPLAINED
BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom level.',
#2. Prepare an input and predicted result. var minZoomLevel = 1; var zoomLevel = minZoomLevel + 0.1; var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method. var actualCursor = cursor.init(zoomLevel);
#4. Check an output. expect(actualCursor).to.deep.equal(expectedCursor); done();
});
function(done) {
BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom level.',
#2. Prepare an input and predicted result. var minZoomLevel = 1; var zoomLevel = minZoomLevel + 0.1; var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method. var actualCursor = cursor.init(zoomLevel);
#4. Check an output. expect(actualCursor).to.deep.equal(expectedCursor); done();
});
function(done) {
BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom level.',
#2. Prepare an input and predicted result. var minZoomLevel = 1; var zoomLevel = minZoomLevel + 0.1; var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method. var actualCursor = cursor.init(zoomLevel);
#4. Check an output. expect(actualCursor).to.deep.equal(expectedCursor); done();
});
function(done) {
BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom level.',
#2. Prepare an input and predicted result. var minZoomLevel = 1; var zoomLevel = minZoomLevel + 0.1; var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method. var actualCursor = cursor.init(zoomLevel);
#4. Check an output. expect(actualCursor).to.deep.equal(expectedCursor); done();
});
function(done) {
#5. TearDown / After
after(function(done) {// Remove global objects document. document = null; window = null;done();
});
BASIC STRUCTURE: EXPLAINED
OUTPUT
<testsuite name="Macchiato Tests" tests="13" failures="0" errors="0" skipped="0" timestamp="Mon, 02 Dec 2013 11:08:09 GMT" time="0.114">
<testcase classname = "cursor #init ()" name = "should initialize cursor if zoom level > minimum zoom level." time="0.004"/>
</testsuite>
OUTPUT: SUCCESS
<failure classname="cursor #init()" name="should initialize cursor if zoom level > minimum zoom level." time="0" message="Cannot read property 'show' of undefined"><![CDATA[TypeError: Cannot read property 'show' of undefined
// ..... Exception Stack Trace .....
</failure>
OUTPUT: FAILURE
TOOLS
TOOLS
> 40 frameworks & libraries
qUnit(TDD) light-weight TDD framework
Jasmine(BDD) flexible BDD framework
Mocha / Karma test runner for async code
+ Chai TDD / BDD assertion library
+ Sinon test spies, stubs & mocks
ENTIRE SPACE OF FRAMEWORKS…
HOW DO I UNIT TEST Known Frameworks / Libraries?
What to test? What to use?Angular, React, Flight Karma + JasmineBackbone qUnitEmber Karma + qUnit (ember-app-kit)ExtJs Jasmine, Siesta (UI)TypeScript tsUnitCoffeeScript qUnitDart Unittest, Hop and Drone.io
NodeJs expresso and vows, Nodeunit
TOOLS: WHAT WE USE
Run UT: Mocha Run UT in parallel: Macchiato Assert/Expect: Chai W3C DOM in JavaScript: Jsdom Mock, spy, stub: Sinon Code coverage tool: None Routine automation: make/Grunt
TOOLS: WHAT WE USE
TOOLS: WHAT WE USE
Project unit tested like a dream ♥
UNIT TESTING SPECIFICS IN JAVASCRIPT
UI
Load fake data via “fixtures”Jsdom(W3C JavaScript implementation)
UNIT TESTING SPECIFICS IN JAVASCRIPT
AJAX
Stub jQuery.ajaxFake XMLHttpRequest
(XMLHTTP ActiveXObject)Fake server
UNIT TESTING SPECIFICS IN JAVASCRIPT
3rd-party scripts
Stubbing jQuery plugin functions(mock jQuery.fn)
UNIT TESTING SPECIFICS IN JAVASCRIPT
Dependency Injection
Mocking deps in RequireJs sucks hard! Squire.js lib / testr.js
UNIT TESTING SPECIFICS IN JAVASCRIPT
NodeJs
Server-side specificsrewire: node.js dependency injection
BEST PRACTISES
FastIsolatedConsistentResponsibilitySelf-descriptiveNo exception HandlingUse assertions when needed
WRAPPING UP
Each test verifies a small chunk of code
Unit tests work best in isolation Mocks, stubs and spies help to
isolate test Don’t test everything but write
many tests > 40 tools are available to ease
unit testing experience, so CHOOSE YOUR OWN!
SHWEEET
ありがとう