SlideShare une entreprise Scribd logo
1  sur  69
Télécharger pour lire hors ligne
1
Test Driven development
& Qunit
Anup Singh
Points to Discuss
 Unit Testing & Test Driven Development
 Debugging JS
 Writing Testable Code
 Designing own testing framework
 QUnit
 QUnit API
 Mocking AJAX
 Testing Forms
 Code coverage using Blankets
 Automated Testing (a brief introduction)
2
How do you test your JS?
1. Write your JavaScript code
2. See if it works in your favourite browser
3. Change something + [F5]
4. If it doesn't work repeat #3 until you make it work or you
go crazy...
5. In case you made it work, discover few days/weeks later
that it doesn't work in another browser
3
I think I'm going crazy...
4
Unit Testing
 In computer programming, unit testing is a procedure
used to validate that individual modules or units of source
code are working properly.
 Unit testing is used for
(i) Test Driven Development
(ii) Fixing bugs
(iii) Regression testing
5
Test Driven Development
 Test-Driven Development (TDD) is a computer
programming technique that involves repeatedly first
writing a test case and then implementing only the code
necessary to pass the test.
 Test-driven development is a method of designing
software, not merely a method of testing.
6
Test Driven Development
 TDD in its simplest form is just this:
 Write your tests
 Watch them fail
 Make them pass
 Refactor
 Repeat
7
The TDD Micro-Cycle
8
Fixing bugs/Regression Testing
9
 Fixing bugs
 Regression testing
What do you need?
 A UnitTesting framework
 Development Environment
10
Tools
 Firebug -The popular developer extension for Firefox that got the ball rolling.
See http://getfirebug.org/.
 IE DeveloperTools - Included in Internet Explorer 8 and later.
 Opera Dragonfly - Included in Opera 9.5 and newer.Also works with mobile versions of Opera.
 WebKit DeveloperTools - Introduced in Safari 3, dramatically improved as of Safari 4, and now available in
Chrome.
Logging - http://patik.com/blog/complete-cross-browser-console-log/
1. alert()
2. Console.log()
3. Common logging method that for all modern browsers
function log() {
try {
console.log.apply(console, arguments);
} catch (e) {
try {
opera.postError.apply(opera, arguments);
} catch (e) {
alert(Array.prototype.join.call(arguments," "));
}
}
}
1.Tries to log message using the
most common method
2. Catches any failure in logging
3.Tries to log the Opera way
Uses alert if all else fails
Testing and debugging - Debugging code
Breakpoints allow us to halt execution at a specific line of code so we can take a gander at the state.
<!DOCTYPE html>
<html>
<head>
<title>Listing 2.2</title>
<script type="text/javascript" src="log.js"></script>
<script type="text/javascript">
var x = 213;
log(x);
</script>
</head>
<body>
</body>
</html>
Testing and debugging - Breakpoints
Good tests make Good code - Emphasis on the word good.
It's quite possible to have an extensive test suite that doesn't really help the quality of our
code, if the tests are poorly constructed.
Good tests exhibit three important characteristics:
1. Repeatability - Our test results should be highly reproducible.Tests run repeatedly should always produce
the exact same results. If test results are nondeterministic, how would we know which results are valid and which
are invalid?
2. Simplicity - Our tests should focus on testing one thing.We should strive to remove as much HTML markup,
CSS, or JavaScript as we can without disrupting the intent of the test case.The more we remove, the greater the
likelihood that the test case will only be influenced by the specific code that we’re testing.
3. Independence - Our tests should execute in isolation.We must avoid making the results from one test
dependent upon another. Breaking tests down into the smallest possible
Test generation
A test suite should serve as a fundamental part of your development workflow, so you
should pick a suite that works particularly well for your coding style and your
code
base.
JavaScript unit testing framework features
• The ability to simulate browser behaviour (clicks, keypresses, and so on)
• Interactive control of tests (pausing and resuming tests)
• Handling asynchronous test timeouts
• The ability to filter which tests are to be executed
Testing Frameworks
Market Share of Testing frameworks
15
The fundamentals of a test suite
The fundamentals of a test suite
1. Aggregate all the individual tests into a single unit
2. Run the in Bulk
3. Providing a single resource that can be run easily and repeatedly
How to construct a test suite
Q. Why would I want to build a new test suite,WhenThere are already a number of good-quality suites
to choose from?
A. Building your own test suite can serve as a good learning experience, especially when looking at how
asynchronous testing works.
16
The Assertion – (assert.html)
17
1. The core of a unit-testing framework is its assertion method, usually named
assert().
2. This takes a value—an expression whose premise is asserted—and a
description that describes the purpose of the assertion. If the value
evaluates to true
3. Either the assertion passes or it’s considered a failure.
4. The associated message is usually logged with an appropriate pass/fail
indicator.
Simple Implementation of JavaScript Assertion
18
More Examples -
 Custom/1_jq_test.html
 Custom/assert.html
 Custom/test_group.html
19
Test Groups – (test_group.html)
1. Grouping assertions together in a testing context to form test
groups.
2.Test group will likely represent a collection of assertions as they
relate to a single method in our API or application
3. If any assertion fails, then the entire test group is marked as failing
20
So what's the first step to sanity?
WRITE TESTABLE CODE
21
What's wrong with this code?
js_sample_001.js
(inline functions and more inside, ajax
directly hooked to element, etc.)
22
Anonymous functions, within functions,
within functions...
23
I'll put functions in your functions...
24
All your DOM elements are belong to JS!
25
Server URL coupling
js_sample_001.js
(with highlighted hardcoded url)
26
Refactoring...
js_sample_002.js
27
Refactoring...
js_sample_002.js
28
Now that's better...
29
js_sample_003.js
(init func and hooked named functions to
page)
Now that's better...
30
Now that's better...
31
Now what about testing?
Popular JS Unit-testing frameworks:
 QUnit
 Jasmine
 UnitJS
 JsUnit (no longer actively maintained)
 Some other – see:
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript
32
What's about QUnit?
 QUnit is a powerful, easy-to-use JavaScript unit
testing framework.
 Supports the same browsers as jQuery 1.x.That's
IE6+ and Current - 1 for Chrome, Firefox, Safari
and Opera.
 Used by the jQuery project to test jQuery,
jQuery UI, jQuery Mobile
 Can be used to test any generic JavaScript code,
including itself
 Very easy to install – just include JS & CSS file in
your HTML
33
Minimal setup: The tests.htm file
34
Getting Started
 Just qunit.js, qunit.css, and a little bit of HTML
 A Quick Demo: http://jsfiddle.net/anups/4cweqhhs/
35
QUnit API
 Test
 Assert
 Async Control
 Callback
36
Test : QUnit.test( name, test )
 Adds a test to run.
 Testing the most common, synchronous code
Qunit.test(“name of the test”, function() {
//write down the assertions
});
function: Function to close over assertions
37
Test : expect()
Specify how many assertions are expected to run
within a test.
If the number of assertions run does not match the
expected count, the test will fail.
test(”expected assertions", function() {
expect( 2 );
//two assertions are expected
});
38
Asserts
 ok
 Equal
 notEqual
 strictEqual
 notStrictEqual
 deepEqual
 notDeepEqual
 throws
39
Assert - ok()
ok( state, message )
A boolean check, passes if the first argument is truthy.
test("ok”, function() {
assert.ok( true, "true succeeds" );
assert.ok( "non-empty", "non-empty string succeeds" );
assert.ok( false, "false fails" );
assert.ok( 0, "0 fails" );
assert.ok( NaN, "NaN fails" );
assert.ok( "", "empty string fails" );
assert.ok( null, "null fails" );
assert.ok( undefined, "undefined fails" );
});
40
Assert - equal()
equal( actual, expected, message )
A comparison assertion that passes if actual ==
expected.
test("equal”, function() {
assert.equal( 0, 0, "Zero, Zero; equal succeeds" );
assert.equal( "", 0, "Empty, Zero; equal succeeds" );
assert.equal( "", "", "Empty, Empty; equal succeeds" );
assert.equal( 0, false, "Zero, false; equal succeeds" );
assert.equal( "three", 3, "Three, 3; equal fails" );
assert.equal( null, false, "null, false; equal fails" );
});
41
Assert - notEqual()
notEqual( actual, expected, message )
A comparison assertion that passes if actual !=
expected.
test("notEqual”, function() {
expect(3);
var actual = 5 - 4;
notEqual(actual, 0, "passes because 1 != 0");
notEqual(actual, false, "passes because 1 != false");
notEqual(actual, true, "fails because 1 == true");
});
42
Assert - strictEqual()
strictEqual( actual, expected, message )
A comparison assertion that passes if actual ===
expected.
test("notEqual”, function() {
expect(3);
var actual = 5 - 4;
strictEqual(actual, 1, "passes because 1 === 1");
strictEqual(actual, true, "fails because 1 !== true");
strictEqual(actual, false, "fails because 1 !== false");
});
43
Assert - notStrictEqual()
notStrictEqual( actual, expected, message )
A comparison assertion that passes if actual !==
expected.
test("notStrictEqual”, function() {
expect(3);
var actual = 5 - 4;
notStrictEqual(actual, 1, "fails because 1 === 1");
notStrictEqual(actual, true, "passes because 1 !== true");
notStrictEqual(actual, false, "passes because 1 !== false");
});
44
Assert - deepEqual ()
deepEqual( actual, expected, message )
Recursive comparison assertion, working on primitives,
arrays and objects, using ===.
test("deepEqual”, function() {
expect(3);
var actual = {a: 1};
equal( actual, {a: 1}, "fails because objects are different");
deepEqual(actual, {a: 1}, "passes because objects are equivalent");
deepEqual(actual, {a: "1"}, "fails because '1' !== 1");
});
45
Assert - notDeepEqual()
notDeepEqual( actual, expected, message )
Recursive comparison assertion.The result of
deepEqual, inverted.
test("notDeepEqual”, function() {
expect(3);
var actual = {a: 1};
notEqual( actual, {a: 1}, "passes because objects are different"); notDeepEqual(actual, {a:
1}, "fails because objects are equivalent"); notDeepEqual(actual, {a: "1"}, "passes because '1' !==
1");
});
46
Assert - throws()
Assertion to test if a callback throws an exception
when run and optionally compare the thrown error.
test("throws”, function() {
expect(3);
throws(
function() { throw new Error("Look me, I'm an error!"); },
"passes because an error is thrown inside the callback”
);
throws(
function() { x // ReferenceError: x is not defined },
"passes because an error is thrown inside the callback”
);
throws (
function() { var a = 1; },
"fails because no error is thrown inside the callback”
);
});
47
Tests Should be Atomic
 Execution order cannot be guaranteed!
 Each test should be independent from one another.
 QUnit.test() is used to keep test cases atomic.
48
Async Control : QUnit.asyncTest
For testing asynchronous code, QUnit.asyncTest will
automatically stop the test runner and wait for your
code to call QUnit.start() to continue.
The following illustrates an asynchronous test that
waits 1 second before resuming
QUnit.asyncTest( "asynchronous test: one second later!", function(
assert ) {
expect( 1 );
setTimeout(function() {
assert.ok( true, "Passed and ready to resume!" );
QUnit.start(); }, 1000);
});
49
Async Control : QUnit.stop()
Increase the number of QUnit.start() calls the
testrunner should wait for before continuing.
When your async test has multiple exit points, call
QUnit.stop() multiple times or use the increment
argument.
QUnit.test( "a test", function( assert ){
QUnit.stop();
setTimeout(function(){
assert.equals("somedata" , "someExpectedValue" );
QUnit.start(); }, 150 );
});
50
Grouping Tests : QUnit.module()
It groups tests together to keep them logically
organized and be able to run a specific group of tests
on their own.
All tests that occur after a call to QUnit.module() will
be grouped into that module.The test names will all be
preceded by the module name in the test results.
QUnit.module( "group a" );//tests for module a
QUnit.module( "group b" );//test for module b
51
Grouping Tests : QUnit.module()
QUnit.module() can also be used to extract common
code from tests within that module.
The QUnit.module() function takes an optional second
parameter to define functions to run before and after
each test within the module
QUnit.module( "module", {
setup: function( assert )
{//any setup task},
teardown: function( assert )
{//task to be performed after test completion}
});
QUnit.test( "test with setup and teardown", function()
{
//test cases
});
52
Callbacks
When integrating QUnit into other tools like CI
servers, use these callbacks as an API to read test
results.
 QUnit.begin()
 QUnit.done()
 QUnit.moduleStart()
 QUnit.moduleDone()
 QUnit.testStart()
 QUnit.testDone()
53
Mocking Ajax with the JQuery Mockjax
Library
 MockAjax
Downlaod it from https://github.com/mobz/mock-ajax
MockAjax is an mock XMLHttpRequest implementation
designed to allow asynchronous XHR requests to be run
inside a synchronous testing framework.
54
Mockjax benifits
 Mock out Ajax requests, so a server is not required to test
server dependent code
 Allow asynchronous requests to run synchronously, allowing
tests to run much faster than normal
 Allow you to test multiple simultaneous inflight requests
 Allow tricky edge cases to be tested with ease
 server timeouts
 receiving server responses out of order
 404’s
 server errors
 Allows tests that use setTimeout to run instantly and reliably
 also supports asynchronous and synchronous ajax without
blocking
55
asyncTest('Intercept and proxy (sub-ajax request)', function() {
$.mockjax({
url: '/proxy',
proxy: 'mock-ajax-response/test_proxy.json'
});
$.ajax({
url: '/proxy',
dataType: 'json',
success: function(json) {
ok(json && json.proxy, 'Proxy request succeeded');
},
error: function(){
ok( false, 'Error callback executed');
},
complete: function() {
start();
}
});
});
Mockjax Example - Intercept Request
More examples - mock-ajax.html
56
Testing User Action
Testing User Action
 Problem
Code that relies on actions initiated by the user can't be
tested by just calling a function. Usually an anonymous
function is bound to an element's event, e.g., a click,
which has to be simulated.
 Solution
 Trigger() event using jQuery trigger
 triggerHandler of jQuery can be used if you don’t wanr
the native browser event to be triggered
 If That is not enough
 https://github.com/bitovi/syn
 http://tinymce.ephox.com/jsrobot
 http://dojotoolkit.org/reference-
guide/1.8/util/dohrobot.html
 https://github.com/gtramontina/keyvent.js
58
Testing User Action
 form.htm
 Form-test.html
59
Testing Scope
Testing Scope - Variable
function outer() {
var a = 1;
function inner() {}
var b = 2;
if (a == 1) {
var c = 3;
}
QUnit.test( "Testing Variable Scope in function", function( assert ){
assert.ok(typeof c === 'number', "c is in scope");
});
}
QUnit.test( "Testing Variable Scope", function( assert ){
assert.ok(true, "some descriptive text");
assert.ok(typeof inner !== 'function', "inner() is not in scope");
assert.ok(typeof outer === 'function', "outer() is in scope");
assert.ok(typeof b !== 'number', "b is not in scope");
assert.ok(typeof a !== 'number', "a is not in scope");
outer();
});
61
Testing Scope – Function p1
function isFunction() { return true; }
var doSomething = function () { return true; };
window.testFunction = function () {return true; };
function outer() {
QUnit.test("Testing Function Scope before declaration", function( assert ){
assert.ok(typeof inner === "function", "inner() in scope before declaration");
});
function inner() {}
QUnit.test("Testing Function Scope after declaration", function( assert ){
assert.ok(typeof inner === "function", "inner() in scope after declaration");
assert.ok(window.inner === undefined, "inner() in global scope");
});
}
62
Testing Scope – Function p2
QUnit.test("Testing Function Scope", function( assert ){
assert.ok(typeof window.isFunction === "function", "isFunction() defined");
assert.ok(isFunction.name === "isFunction", "isFunction() has a name");
assert.ok(typeof window.doSomething === "function", "doSomething() defined");
assert.ok(doSomething.name === "", "doSomething() has no name");
assert.ok(typeof window.testFunction === "function", "testFunction() defined");
outer();
assert.ok(window.inner === undefined, "inner() still not in global scope");
window.doCoding = function writeCode() {
return true;
};
assert.ok(window.doCoding.name === 'writeCode', "wieldSword's real name is
writeCode");
});
63
QUnit Test - Suite
64
NodeJS
Integration and Automation
Node :QUnit
1. Install nodejs
2. Install qunit node module
npm install qunit
testrunner.js
var runner = require("../../node/node_modules/qunit");
runner.run({
code : "/full/path/to/public/js/main.js",
tests : "/full/path/to/tests/js/tests.js"
});
Node command
node tests/js/testrunner.js
66
Automated Testing
Install Node
Using Node Package Manager install Grunt
Install QUnit module to your project directory(npm
install qunit)
└ project
├ src // plugin source, project files, etc
├ tests // we'll be working in here mostly
│ ├ lib
│ │ ├ jquery-1.x.x.min.js // if you need it (QUnit doesn't)
│ │ ├ qunit-1.10.0.js
│ │ └ qunit-1.10.0.css
│ ├ index.html // our QUnit test specification
│ └ tests.js // your tests (could be split into multiple files)
├ Gruntfile.js // you'll create this, we'll get to it shortly
├ package.json // to specify our project dependencies
67
Automated Testing (contd.)
//package.json
{
"name": "projectName",
"version": "1.0.0",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-qunit": ">=0.2.1",
}
}
//Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
taskName: {qunit: {
all: ['tests/*.html']
}}
});
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.registerTask('default', ['qunit']);
};
68
69

Contenu connexe

Tendances

Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
Harry Potter
 
Advanced junit and mockito
Advanced junit and mockitoAdvanced junit and mockito
Advanced junit and mockito
Mathieu Carbou
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
Richard Paul
 

Tendances (19)

Unit Testing in Java
Unit Testing in JavaUnit Testing in Java
Unit Testing in Java
 
Unit Testing in iOS
Unit Testing in iOSUnit Testing in iOS
Unit Testing in iOS
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testing
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
 
JUnit 5
JUnit 5JUnit 5
JUnit 5
 
3 j unit
3 j unit3 j unit
3 j unit
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
Advanced junit and mockito
Advanced junit and mockitoAdvanced junit and mockito
Advanced junit and mockito
 
Tdd & unit test
Tdd & unit testTdd & unit test
Tdd & unit test
 
Test driven development - JUnit basics and best practices
Test driven development - JUnit basics and best practicesTest driven development - JUnit basics and best practices
Test driven development - JUnit basics and best practices
 
Mockito
MockitoMockito
Mockito
 
Java Unit Testing
Java Unit TestingJava Unit Testing
Java Unit Testing
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Unit testing with JUnit
Unit testing with JUnitUnit testing with JUnit
Unit testing with JUnit
 
Testing with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifeTesting with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs Life
 
Junit
JunitJunit
Junit
 
Junit
JunitJunit
Junit
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 

Similaire à JAVASCRIPT TDD(Test driven Development) & Qunit Tutorial

In search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingIn search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testing
Anna Khabibullina
 

Similaire à JAVASCRIPT TDD(Test driven Development) & Qunit Tutorial (20)

Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Joomla! Testing - J!DD Germany 2016
Joomla! Testing - J!DD Germany 2016Joomla! Testing - J!DD Germany 2016
Joomla! Testing - J!DD Germany 2016
 
Unit test
Unit testUnit test
Unit test
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
 
Mocking with Mockito
Mocking with MockitoMocking with Mockito
Mocking with Mockito
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Unit testing - A&BP CC
Unit testing - A&BP CCUnit testing - A&BP CC
Unit testing - A&BP CC
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
In search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingIn search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testing
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"
 
Testing Experience - Evolution of Test Automation Frameworks
Testing Experience - Evolution of Test Automation FrameworksTesting Experience - Evolution of Test Automation Frameworks
Testing Experience - Evolution of Test Automation Frameworks
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NET
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Implementing Quality on a Java Project
Implementing Quality on a Java ProjectImplementing Quality on a Java Project
Implementing Quality on a Java Project
 
Unit tests and TDD
Unit tests and TDDUnit tests and TDD
Unit tests and TDD
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Xp Day 080506 Unit Tests And Mocks
Xp Day 080506 Unit Tests And MocksXp Day 080506 Unit Tests And Mocks
Xp Day 080506 Unit Tests And Mocks
 
Unit testing for WordPress
Unit testing for WordPressUnit testing for WordPress
Unit testing for WordPress
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testing
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 

JAVASCRIPT TDD(Test driven Development) & Qunit Tutorial

  • 1. 1 Test Driven development & Qunit Anup Singh
  • 2. Points to Discuss  Unit Testing & Test Driven Development  Debugging JS  Writing Testable Code  Designing own testing framework  QUnit  QUnit API  Mocking AJAX  Testing Forms  Code coverage using Blankets  Automated Testing (a brief introduction) 2
  • 3. How do you test your JS? 1. Write your JavaScript code 2. See if it works in your favourite browser 3. Change something + [F5] 4. If it doesn't work repeat #3 until you make it work or you go crazy... 5. In case you made it work, discover few days/weeks later that it doesn't work in another browser 3
  • 4. I think I'm going crazy... 4
  • 5. Unit Testing  In computer programming, unit testing is a procedure used to validate that individual modules or units of source code are working properly.  Unit testing is used for (i) Test Driven Development (ii) Fixing bugs (iii) Regression testing 5
  • 6. Test Driven Development  Test-Driven Development (TDD) is a computer programming technique that involves repeatedly first writing a test case and then implementing only the code necessary to pass the test.  Test-driven development is a method of designing software, not merely a method of testing. 6
  • 7. Test Driven Development  TDD in its simplest form is just this:  Write your tests  Watch them fail  Make them pass  Refactor  Repeat 7
  • 9. Fixing bugs/Regression Testing 9  Fixing bugs  Regression testing
  • 10. What do you need?  A UnitTesting framework  Development Environment 10
  • 11. Tools  Firebug -The popular developer extension for Firefox that got the ball rolling. See http://getfirebug.org/.  IE DeveloperTools - Included in Internet Explorer 8 and later.  Opera Dragonfly - Included in Opera 9.5 and newer.Also works with mobile versions of Opera.  WebKit DeveloperTools - Introduced in Safari 3, dramatically improved as of Safari 4, and now available in Chrome. Logging - http://patik.com/blog/complete-cross-browser-console-log/ 1. alert() 2. Console.log() 3. Common logging method that for all modern browsers function log() { try { console.log.apply(console, arguments); } catch (e) { try { opera.postError.apply(opera, arguments); } catch (e) { alert(Array.prototype.join.call(arguments," ")); } } } 1.Tries to log message using the most common method 2. Catches any failure in logging 3.Tries to log the Opera way Uses alert if all else fails Testing and debugging - Debugging code
  • 12. Breakpoints allow us to halt execution at a specific line of code so we can take a gander at the state. <!DOCTYPE html> <html> <head> <title>Listing 2.2</title> <script type="text/javascript" src="log.js"></script> <script type="text/javascript"> var x = 213; log(x); </script> </head> <body> </body> </html> Testing and debugging - Breakpoints
  • 13. Good tests make Good code - Emphasis on the word good. It's quite possible to have an extensive test suite that doesn't really help the quality of our code, if the tests are poorly constructed. Good tests exhibit three important characteristics: 1. Repeatability - Our test results should be highly reproducible.Tests run repeatedly should always produce the exact same results. If test results are nondeterministic, how would we know which results are valid and which are invalid? 2. Simplicity - Our tests should focus on testing one thing.We should strive to remove as much HTML markup, CSS, or JavaScript as we can without disrupting the intent of the test case.The more we remove, the greater the likelihood that the test case will only be influenced by the specific code that we’re testing. 3. Independence - Our tests should execute in isolation.We must avoid making the results from one test dependent upon another. Breaking tests down into the smallest possible Test generation
  • 14. A test suite should serve as a fundamental part of your development workflow, so you should pick a suite that works particularly well for your coding style and your code base. JavaScript unit testing framework features • The ability to simulate browser behaviour (clicks, keypresses, and so on) • Interactive control of tests (pausing and resuming tests) • Handling asynchronous test timeouts • The ability to filter which tests are to be executed Testing Frameworks
  • 15. Market Share of Testing frameworks 15
  • 16. The fundamentals of a test suite The fundamentals of a test suite 1. Aggregate all the individual tests into a single unit 2. Run the in Bulk 3. Providing a single resource that can be run easily and repeatedly How to construct a test suite Q. Why would I want to build a new test suite,WhenThere are already a number of good-quality suites to choose from? A. Building your own test suite can serve as a good learning experience, especially when looking at how asynchronous testing works. 16
  • 17. The Assertion – (assert.html) 17 1. The core of a unit-testing framework is its assertion method, usually named assert(). 2. This takes a value—an expression whose premise is asserted—and a description that describes the purpose of the assertion. If the value evaluates to true 3. Either the assertion passes or it’s considered a failure. 4. The associated message is usually logged with an appropriate pass/fail indicator.
  • 18. Simple Implementation of JavaScript Assertion 18
  • 19. More Examples -  Custom/1_jq_test.html  Custom/assert.html  Custom/test_group.html 19
  • 20. Test Groups – (test_group.html) 1. Grouping assertions together in a testing context to form test groups. 2.Test group will likely represent a collection of assertions as they relate to a single method in our API or application 3. If any assertion fails, then the entire test group is marked as failing 20
  • 21. So what's the first step to sanity? WRITE TESTABLE CODE 21
  • 22. What's wrong with this code? js_sample_001.js (inline functions and more inside, ajax directly hooked to element, etc.) 22
  • 23. Anonymous functions, within functions, within functions... 23
  • 24. I'll put functions in your functions... 24
  • 25. All your DOM elements are belong to JS! 25
  • 26. Server URL coupling js_sample_001.js (with highlighted hardcoded url) 26
  • 29. Now that's better... 29 js_sample_003.js (init func and hooked named functions to page)
  • 32. Now what about testing? Popular JS Unit-testing frameworks:  QUnit  Jasmine  UnitJS  JsUnit (no longer actively maintained)  Some other – see: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript 32
  • 33. What's about QUnit?  QUnit is a powerful, easy-to-use JavaScript unit testing framework.  Supports the same browsers as jQuery 1.x.That's IE6+ and Current - 1 for Chrome, Firefox, Safari and Opera.  Used by the jQuery project to test jQuery, jQuery UI, jQuery Mobile  Can be used to test any generic JavaScript code, including itself  Very easy to install – just include JS & CSS file in your HTML 33
  • 34. Minimal setup: The tests.htm file 34
  • 35. Getting Started  Just qunit.js, qunit.css, and a little bit of HTML  A Quick Demo: http://jsfiddle.net/anups/4cweqhhs/ 35
  • 36. QUnit API  Test  Assert  Async Control  Callback 36
  • 37. Test : QUnit.test( name, test )  Adds a test to run.  Testing the most common, synchronous code Qunit.test(“name of the test”, function() { //write down the assertions }); function: Function to close over assertions 37
  • 38. Test : expect() Specify how many assertions are expected to run within a test. If the number of assertions run does not match the expected count, the test will fail. test(”expected assertions", function() { expect( 2 ); //two assertions are expected }); 38
  • 39. Asserts  ok  Equal  notEqual  strictEqual  notStrictEqual  deepEqual  notDeepEqual  throws 39
  • 40. Assert - ok() ok( state, message ) A boolean check, passes if the first argument is truthy. test("ok”, function() { assert.ok( true, "true succeeds" ); assert.ok( "non-empty", "non-empty string succeeds" ); assert.ok( false, "false fails" ); assert.ok( 0, "0 fails" ); assert.ok( NaN, "NaN fails" ); assert.ok( "", "empty string fails" ); assert.ok( null, "null fails" ); assert.ok( undefined, "undefined fails" ); }); 40
  • 41. Assert - equal() equal( actual, expected, message ) A comparison assertion that passes if actual == expected. test("equal”, function() { assert.equal( 0, 0, "Zero, Zero; equal succeeds" ); assert.equal( "", 0, "Empty, Zero; equal succeeds" ); assert.equal( "", "", "Empty, Empty; equal succeeds" ); assert.equal( 0, false, "Zero, false; equal succeeds" ); assert.equal( "three", 3, "Three, 3; equal fails" ); assert.equal( null, false, "null, false; equal fails" ); }); 41
  • 42. Assert - notEqual() notEqual( actual, expected, message ) A comparison assertion that passes if actual != expected. test("notEqual”, function() { expect(3); var actual = 5 - 4; notEqual(actual, 0, "passes because 1 != 0"); notEqual(actual, false, "passes because 1 != false"); notEqual(actual, true, "fails because 1 == true"); }); 42
  • 43. Assert - strictEqual() strictEqual( actual, expected, message ) A comparison assertion that passes if actual === expected. test("notEqual”, function() { expect(3); var actual = 5 - 4; strictEqual(actual, 1, "passes because 1 === 1"); strictEqual(actual, true, "fails because 1 !== true"); strictEqual(actual, false, "fails because 1 !== false"); }); 43
  • 44. Assert - notStrictEqual() notStrictEqual( actual, expected, message ) A comparison assertion that passes if actual !== expected. test("notStrictEqual”, function() { expect(3); var actual = 5 - 4; notStrictEqual(actual, 1, "fails because 1 === 1"); notStrictEqual(actual, true, "passes because 1 !== true"); notStrictEqual(actual, false, "passes because 1 !== false"); }); 44
  • 45. Assert - deepEqual () deepEqual( actual, expected, message ) Recursive comparison assertion, working on primitives, arrays and objects, using ===. test("deepEqual”, function() { expect(3); var actual = {a: 1}; equal( actual, {a: 1}, "fails because objects are different"); deepEqual(actual, {a: 1}, "passes because objects are equivalent"); deepEqual(actual, {a: "1"}, "fails because '1' !== 1"); }); 45
  • 46. Assert - notDeepEqual() notDeepEqual( actual, expected, message ) Recursive comparison assertion.The result of deepEqual, inverted. test("notDeepEqual”, function() { expect(3); var actual = {a: 1}; notEqual( actual, {a: 1}, "passes because objects are different"); notDeepEqual(actual, {a: 1}, "fails because objects are equivalent"); notDeepEqual(actual, {a: "1"}, "passes because '1' !== 1"); }); 46
  • 47. Assert - throws() Assertion to test if a callback throws an exception when run and optionally compare the thrown error. test("throws”, function() { expect(3); throws( function() { throw new Error("Look me, I'm an error!"); }, "passes because an error is thrown inside the callback” ); throws( function() { x // ReferenceError: x is not defined }, "passes because an error is thrown inside the callback” ); throws ( function() { var a = 1; }, "fails because no error is thrown inside the callback” ); }); 47
  • 48. Tests Should be Atomic  Execution order cannot be guaranteed!  Each test should be independent from one another.  QUnit.test() is used to keep test cases atomic. 48
  • 49. Async Control : QUnit.asyncTest For testing asynchronous code, QUnit.asyncTest will automatically stop the test runner and wait for your code to call QUnit.start() to continue. The following illustrates an asynchronous test that waits 1 second before resuming QUnit.asyncTest( "asynchronous test: one second later!", function( assert ) { expect( 1 ); setTimeout(function() { assert.ok( true, "Passed and ready to resume!" ); QUnit.start(); }, 1000); }); 49
  • 50. Async Control : QUnit.stop() Increase the number of QUnit.start() calls the testrunner should wait for before continuing. When your async test has multiple exit points, call QUnit.stop() multiple times or use the increment argument. QUnit.test( "a test", function( assert ){ QUnit.stop(); setTimeout(function(){ assert.equals("somedata" , "someExpectedValue" ); QUnit.start(); }, 150 ); }); 50
  • 51. Grouping Tests : QUnit.module() It groups tests together to keep them logically organized and be able to run a specific group of tests on their own. All tests that occur after a call to QUnit.module() will be grouped into that module.The test names will all be preceded by the module name in the test results. QUnit.module( "group a" );//tests for module a QUnit.module( "group b" );//test for module b 51
  • 52. Grouping Tests : QUnit.module() QUnit.module() can also be used to extract common code from tests within that module. The QUnit.module() function takes an optional second parameter to define functions to run before and after each test within the module QUnit.module( "module", { setup: function( assert ) {//any setup task}, teardown: function( assert ) {//task to be performed after test completion} }); QUnit.test( "test with setup and teardown", function() { //test cases }); 52
  • 53. Callbacks When integrating QUnit into other tools like CI servers, use these callbacks as an API to read test results.  QUnit.begin()  QUnit.done()  QUnit.moduleStart()  QUnit.moduleDone()  QUnit.testStart()  QUnit.testDone() 53
  • 54. Mocking Ajax with the JQuery Mockjax Library  MockAjax Downlaod it from https://github.com/mobz/mock-ajax MockAjax is an mock XMLHttpRequest implementation designed to allow asynchronous XHR requests to be run inside a synchronous testing framework. 54
  • 55. Mockjax benifits  Mock out Ajax requests, so a server is not required to test server dependent code  Allow asynchronous requests to run synchronously, allowing tests to run much faster than normal  Allow you to test multiple simultaneous inflight requests  Allow tricky edge cases to be tested with ease  server timeouts  receiving server responses out of order  404’s  server errors  Allows tests that use setTimeout to run instantly and reliably  also supports asynchronous and synchronous ajax without blocking 55
  • 56. asyncTest('Intercept and proxy (sub-ajax request)', function() { $.mockjax({ url: '/proxy', proxy: 'mock-ajax-response/test_proxy.json' }); $.ajax({ url: '/proxy', dataType: 'json', success: function(json) { ok(json && json.proxy, 'Proxy request succeeded'); }, error: function(){ ok( false, 'Error callback executed'); }, complete: function() { start(); } }); }); Mockjax Example - Intercept Request More examples - mock-ajax.html 56
  • 58. Testing User Action  Problem Code that relies on actions initiated by the user can't be tested by just calling a function. Usually an anonymous function is bound to an element's event, e.g., a click, which has to be simulated.  Solution  Trigger() event using jQuery trigger  triggerHandler of jQuery can be used if you don’t wanr the native browser event to be triggered  If That is not enough  https://github.com/bitovi/syn  http://tinymce.ephox.com/jsrobot  http://dojotoolkit.org/reference- guide/1.8/util/dohrobot.html  https://github.com/gtramontina/keyvent.js 58
  • 59. Testing User Action  form.htm  Form-test.html 59
  • 61. Testing Scope - Variable function outer() { var a = 1; function inner() {} var b = 2; if (a == 1) { var c = 3; } QUnit.test( "Testing Variable Scope in function", function( assert ){ assert.ok(typeof c === 'number', "c is in scope"); }); } QUnit.test( "Testing Variable Scope", function( assert ){ assert.ok(true, "some descriptive text"); assert.ok(typeof inner !== 'function', "inner() is not in scope"); assert.ok(typeof outer === 'function', "outer() is in scope"); assert.ok(typeof b !== 'number', "b is not in scope"); assert.ok(typeof a !== 'number', "a is not in scope"); outer(); }); 61
  • 62. Testing Scope – Function p1 function isFunction() { return true; } var doSomething = function () { return true; }; window.testFunction = function () {return true; }; function outer() { QUnit.test("Testing Function Scope before declaration", function( assert ){ assert.ok(typeof inner === "function", "inner() in scope before declaration"); }); function inner() {} QUnit.test("Testing Function Scope after declaration", function( assert ){ assert.ok(typeof inner === "function", "inner() in scope after declaration"); assert.ok(window.inner === undefined, "inner() in global scope"); }); } 62
  • 63. Testing Scope – Function p2 QUnit.test("Testing Function Scope", function( assert ){ assert.ok(typeof window.isFunction === "function", "isFunction() defined"); assert.ok(isFunction.name === "isFunction", "isFunction() has a name"); assert.ok(typeof window.doSomething === "function", "doSomething() defined"); assert.ok(doSomething.name === "", "doSomething() has no name"); assert.ok(typeof window.testFunction === "function", "testFunction() defined"); outer(); assert.ok(window.inner === undefined, "inner() still not in global scope"); window.doCoding = function writeCode() { return true; }; assert.ok(window.doCoding.name === 'writeCode', "wieldSword's real name is writeCode"); }); 63
  • 64. QUnit Test - Suite 64
  • 66. Node :QUnit 1. Install nodejs 2. Install qunit node module npm install qunit testrunner.js var runner = require("../../node/node_modules/qunit"); runner.run({ code : "/full/path/to/public/js/main.js", tests : "/full/path/to/tests/js/tests.js" }); Node command node tests/js/testrunner.js 66
  • 67. Automated Testing Install Node Using Node Package Manager install Grunt Install QUnit module to your project directory(npm install qunit) └ project ├ src // plugin source, project files, etc ├ tests // we'll be working in here mostly │ ├ lib │ │ ├ jquery-1.x.x.min.js // if you need it (QUnit doesn't) │ │ ├ qunit-1.10.0.js │ │ └ qunit-1.10.0.css │ ├ index.html // our QUnit test specification │ └ tests.js // your tests (could be split into multiple files) ├ Gruntfile.js // you'll create this, we'll get to it shortly ├ package.json // to specify our project dependencies 67
  • 68. Automated Testing (contd.) //package.json { "name": "projectName", "version": "1.0.0", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-qunit": ">=0.2.1", } } //Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), taskName: {qunit: { all: ['tests/*.html'] }} }); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.registerTask('default', ['qunit']); }; 68
  • 69. 69