SlideShare a Scribd company logo
How to test complex SaaS solutions! 
! 
The Family! 
16th july 2014
Founder & CTO! 
! 
@guillaumepotier! 
http://imctobitch.com
By the numbers 
• 4 years old! 
• 23 employes and counting! 
- ~ 10 tech / product! 
- ~ 10 sales! 
- ~ 3 support, market, administrative ! 
• 400+ clients! 
- Total, Orange, Areva, Air Liquide, Google, SNCF, AXA, Société 
Générale, Sanofi, L’Oréal, Crédit Agricole, Danone, Deloitte, Capgemini, 
Auchan…! 
• 4000+ tests! 
- UT backend, functional backend! 
- UT javascript, functional javascript! 
! 
! 
!
What we’ll talk about 
• Why testing?! 
• What need to be tested?! 
• How to test?! 
• Tools! 
• Limits..! 
• Going further! 
!
Why testing? 
Sometimes shit may happen
Why testing? 
Tests are here to prevent that (at least they try..)
Why testing? 
Tests also allow you refactor without fearing to break things
Why testing? 
Tests are great to rely on other people code (and other people on yours)
Why testing? 
Ultimately, tests allow you to be faster!
Why testing? 
A little more seriously..! 
Let’s see a real Parsley.js example here
Why testing?
Why testing? 
• 10+ classes! 
• 2k+ lines! 
• ~200 tests (UT & functional)! 
• ran in < 3sec in browser! 
• ran in < 1sec in CLI! 
! 
! 
http://parsleyjs.org/doc/tests.html
Why testing? 
max: function (value) { 
return $.extend(new Validator.Assert().LessThanOrEqual(value), { priority: 30 }); 
UT : validate your methods API and behavior 
! 
} 
it('should have a max validator', function () { 
expect(parsleyValidator.validate('foo', parsleyValidator.max(10))).to.be(false); 
expect(parsleyValidator.validate('5', parsleyValidator.max(10))).to.be(true); 
expect(parsleyValidator.validate('10', parsleyValidator.max(10))).to.be(true); 
expect(parsleyValidator.validate('42', parsleyValidator.max(10))).to.be(false); 
}); 
✓ should have a max validator 
Code 
Test 
Result
Why testing? 
max: function (value) { 
return $.extend(new Validator.Assert().LessThan(value), { priority: 30 }); 
Prevent regressions, ensure 3rd party libs consistency 
! 
} 
it('should have a max validator', function () { 
expect(parsleyValidator.validate('foo', parsleyValidator.max(10))).to.be(false); 
expect(parsleyValidator.validate('5', parsleyValidator.max(10))).to.be(true); 
expect(parsleyValidator.validate('10', parsleyValidator.max(10))).to.be(true); 
expect(parsleyValidator.validate('42', parsleyValidator.max(10))).to.be(false); 
}); 
1) should have a max validator 
Code 
Test 
Result
Why testing?
Why testing?
Why testing? 
Fixes bugs found to ensure they’ll never show up again 
! 
it('should have a max validator', function () { 
expect(parsleyValidator.validate('foo', parsleyValidator.max(10))).to.be(false); 
expect(parsleyValidator.validate('5', parsleyValidator.max(10))).to.be(true); 
expect(parsleyValidator.validate('10', parsleyValidator.max(10))).to.be(true); 
expect(parsleyValidator.validate('42', parsleyValidator.max(10))).to.be(false); 
expect(parsleyValidator.validate('5', parsleyValidator.max(”10”))).to.be(true); 
}); 
✓ should have a max validator 
Code 
Test 
Result 
max: function (value) { 
return $.extend(new Validator.Assert().LessThan(value), { 
priority: 30, 
requirementsTransformer: function () { 
return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value; 
} 
}); 
}
Why testing? 
it('should show custom error message with variabilized parameters', function () { 
$('body').append('<input type="text" id="element" value="bar" data-parsley-minlength="7" data-parsley-minlength- 
message="foo %s bar"/>'); 
var parsleyField = $('#element').psly(); 
parsleyField.validate(); 
! 
expect($('ul#parsley-id-' + parsleyField.__id__ + ' li').text()).to.be('foo 7 bar'); 
}); 
Functional test : validate your end-user behavior
Why testing? 
it('should save some calls for querries already done', function (done) { 
$('body').append('<input type="text" data-parsley-remote="http://foo.bar" id="element" required 
name="element" value="foo" />'); 
var parsleyInstance = $('#element').parsley(); 
! 
sinon.stub($, 'ajax').returns($.Deferred().resolve({}, 'success', { status: 200, state: function () { return 
'resolved' } })); 
parsleyInstance.asyncIsValid() 
.done(function () { 
expect($.ajax.calledOnce).to.be(true); 
expect($.ajax.calledWithMatch({ data: { "element": "foo" } })).to.be(true); 
$.ajax.restore(); 
sinon.stub($, 'ajax').returns($.Deferred().reject({ status: 400, state: function () { return 'rejected' } 
}, 'error', 'error')); 
! 
$('#element').val('bar'); 
parsleyInstance.asyncIsValid() 
.fail(function () { 
expect($.ajax.calledOnce).to.be(true); 
expect($.ajax.calledWithMatch({ data: { "element": "bar" } })).to.be(true); 
! 
$.ajax.restore(); 
sinon.stub($, 'ajax').returns($.Deferred().resolve({}, 'success', { status: 200, state: function () { 
return 'resolved' } })); 
$('#element').val('foo'); 
! 
parsleyInstance.asyncIsValid() 
.done(function () { 
expect($.ajax.callCount).to.be(0); 
expect($.ajax.calledOnce).to.be(false); 
$.ajax.restore(); 
done(); 
}); 
}); 
}); 
});
What need to be tested?
What need to be tested? 
• Application logic (services, algorithms, microapps)! 
• API responses! 
• Application behavior, End-user responses! 
! 
TO 
BE 
TESTED
What need to be tested?
What need to be tested? 
• getters / setters! 
• already tested 3rd party libraries! 
• ORM, all exceptions, errors! 
! 
NOT 
TO 
BE 
TESTED
What need to be tested?
What need to be tested? 
100% 
coverage!
What need to be tested?
What need to be tested?
What need to be tested?
How to test?
How to test?
How to test? 
class SynchronizedUserTest extends PHPUnit_Framework_TestCase 
{ 
/** 
* @covers ::construct() 
* @expectedException InvalidArgumentException 
* @expectedExceptionMessage User and IntercomUser are not the same. 
*/ 
public function testConstructWithWrongEmails() 
{ 
$intercomUser = new IntercomUser(1, 'bar@foo.fr'); 
$user = (new User)->setEmail('foo@bar.fr'); 
$this->setProperty($user, 'id', 1); 
! 
new SynchronizedUser($intercomUser, $user); 
} 
! 
/** 
* @covers ::construct() 
* @expectedException InvalidArgumentException 
* @expectedExceptionMessage User and IntercomUser are not the same. 
*/ 
public function testConstructWithWrongIds() 
{ 
$intercomUser = new IntercomUser(2, 'foo@bar.fr'); 
$user = (new User)->setEmail('foo@bar.fr'); 
$this->setProperty($user, 'id', 1); 
! 
new SynchronizedUser($intercomUser, $user); 
} 
}
How to test? 
class SynchronizedUser 
{ 
private $intercomUser; 
private $user; ! 
/** 
* @throws InvalidArgumentException If the user intercom and user wisembly doesn't match 
*/ 
public function __construct(IntercomUser $intercomUser, User $user) 
{ 
if ($intercomUser->getUserId() !== $user->getId() || $intercomUser->getEmail() !== mb_strtolower($user->getEmail(), 
mb_detect_encoding($user->getEmail()))) { 
throw new InvalidArgumentException('User and IntercomUser are not the same.'); 
} ! 
$this->intercomUser = $intercomUser; 
$this->user = $user; 
} ! 
/** 
* @return IntercomUser 
*/ 
public function getIntercomUser() 
{ 
return $this->intercomUser; 
} ! 
/** 
* @return User 
*/ 
public function getUser() 
{ 
return $this->user; 
} 
}
How to test?
How to test?
Tools 
• PHPUnit! 
• Behat, PHPSpec..! 
• Mocha, Jasmine, QUnit..! 
• Karma, PhantomJS, TestEM..! 
• Travis, Jenkins, Shipper, CodeShip..! 
!
Limits 
• CSS glitches! 
• User experience! 
• Browser compatibility! 
• Do not take to much time to code / maintain tests!! 
• Do not have too long test suites!! 
• Fixtures for functional tests! 
• Isolate tests among themselves!! 
!
Going further 
• Script & test deploy scripts..! 
• SLA & performance tests..! 
!
How to test complex SaaS applications - The family july 2014

More Related Content

What's hot

04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascript
crgwbr
 
async/await Revisited
async/await Revisitedasync/await Revisited
async/await Revisited
Riza Fahmi
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
Rafael Felix da Silva
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
Kacper Gunia
 
Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011
Rafael Felix da Silva
 
QA for PHP projects
QA for PHP projectsQA for PHP projects
QA for PHP projects
Michelangelo van Dam
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2
Kacper Gunia
 
Zero to SOLID
Zero to SOLIDZero to SOLID
Zero to SOLID
Vic Metcalfe
 
Functional Structures in PHP
Functional Structures in PHPFunctional Structures in PHP
Functional Structures in PHP
Marcello Duarte
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
Marcello Duarte
 
My Development Story
My Development StoryMy Development Story
My Development Story
Takahiro Fujiwara
 
Backbone - TDC 2011 Floripa
Backbone - TDC 2011 FloripaBackbone - TDC 2011 Floripa
Backbone - TDC 2011 Floripa
Rafael Felix da Silva
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
Rafael Dohms
 
Proposed PHP function: is_literal()
Proposed PHP function: is_literal()Proposed PHP function: is_literal()
Proposed PHP function: is_literal()
Craig Francis
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
Tim Tyrrell
 
Espresso devoxx 2014
Espresso devoxx 2014Espresso devoxx 2014
Espresso devoxx 2014
Publicis Sapient Engineering
 
Instant Dynamic Forms with #states
Instant Dynamic Forms with #statesInstant Dynamic Forms with #states
Instant Dynamic Forms with #statesKonstantin Käfer
 
Get into the FLOW with Extbase
Get into the FLOW with ExtbaseGet into the FLOW with Extbase
Get into the FLOW with Extbase
Jochen Rau
 
Perl 6 by example
Perl 6 by examplePerl 6 by example
Perl 6 by example
Andrew Shitov
 

What's hot (20)

04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascript
 
async/await Revisited
async/await Revisitedasync/await Revisited
async/await Revisited
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011
 
QA for PHP projects
QA for PHP projectsQA for PHP projects
QA for PHP projects
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2
 
Zero to SOLID
Zero to SOLIDZero to SOLID
Zero to SOLID
 
Functional Structures in PHP
Functional Structures in PHPFunctional Structures in PHP
Functional Structures in PHP
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
My Development Story
My Development StoryMy Development Story
My Development Story
 
Backbone - TDC 2011 Floripa
Backbone - TDC 2011 FloripaBackbone - TDC 2011 Floripa
Backbone - TDC 2011 Floripa
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Proposed PHP function: is_literal()
Proposed PHP function: is_literal()Proposed PHP function: is_literal()
Proposed PHP function: is_literal()
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
Espresso devoxx 2014
Espresso devoxx 2014Espresso devoxx 2014
Espresso devoxx 2014
 
Instant Dynamic Forms with #states
Instant Dynamic Forms with #statesInstant Dynamic Forms with #states
Instant Dynamic Forms with #states
 
Get into the FLOW with Extbase
Get into the FLOW with ExtbaseGet into the FLOW with Extbase
Get into the FLOW with Extbase
 
Perl 6 by example
Perl 6 by examplePerl 6 by example
Perl 6 by example
 

Similar to How to test complex SaaS applications - The family july 2014

Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
Ryan Anklam
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
Tagged Social
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
Fernando Daciuk
 
JQuery Presentation
JQuery PresentationJQuery Presentation
JQuery Presentation
Sony Jain
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
Joseph Chiang
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
Visual Engineering
 
Security Challenges in Node.js
Security Challenges in Node.jsSecurity Challenges in Node.js
Security Challenges in Node.js
Websecurify
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Michelangelo van Dam
 
From typing the test to testing the type
From typing the test to testing the typeFrom typing the test to testing the type
From typing the test to testing the type
Wim Godden
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
Michelangelo van Dam
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
Marco Otte-Witte
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
Michelangelo van Dam
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitmfrost503
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
Michelangelo van Dam
 
Google guava
Google guavaGoogle guava
JavaScript Sprachraum
JavaScript SprachraumJavaScript Sprachraum
JavaScript Sprachraumpatricklee
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPresswpnepal
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
Peter Friese
 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experienced
rajkamaltibacademy
 

Similar to How to test complex SaaS applications - The family july 2014 (20)

Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
JQuery Presentation
JQuery PresentationJQuery Presentation
JQuery Presentation
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Security Challenges in Node.js
Security Challenges in Node.jsSecurity Challenges in Node.js
Security Challenges in Node.js
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
From typing the test to testing the type
From typing the test to testing the typeFrom typing the test to testing the type
From typing the test to testing the type
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Google guava
Google guavaGoogle guava
Google guava
 
JavaScript Sprachraum
JavaScript SprachraumJavaScript Sprachraum
JavaScript Sprachraum
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPress
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experienced
 

Recently uploaded

Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 

Recently uploaded (20)

Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 

How to test complex SaaS applications - The family july 2014

  • 1. How to test complex SaaS solutions! ! The Family! 16th july 2014
  • 2. Founder & CTO! ! @guillaumepotier! http://imctobitch.com
  • 3. By the numbers • 4 years old! • 23 employes and counting! - ~ 10 tech / product! - ~ 10 sales! - ~ 3 support, market, administrative ! • 400+ clients! - Total, Orange, Areva, Air Liquide, Google, SNCF, AXA, Société Générale, Sanofi, L’Oréal, Crédit Agricole, Danone, Deloitte, Capgemini, Auchan…! • 4000+ tests! - UT backend, functional backend! - UT javascript, functional javascript! ! ! !
  • 4. What we’ll talk about • Why testing?! • What need to be tested?! • How to test?! • Tools! • Limits..! • Going further! !
  • 5. Why testing? Sometimes shit may happen
  • 6. Why testing? Tests are here to prevent that (at least they try..)
  • 7. Why testing? Tests also allow you refactor without fearing to break things
  • 8. Why testing? Tests are great to rely on other people code (and other people on yours)
  • 9. Why testing? Ultimately, tests allow you to be faster!
  • 10. Why testing? A little more seriously..! Let’s see a real Parsley.js example here
  • 12. Why testing? • 10+ classes! • 2k+ lines! • ~200 tests (UT & functional)! • ran in < 3sec in browser! • ran in < 1sec in CLI! ! ! http://parsleyjs.org/doc/tests.html
  • 13. Why testing? max: function (value) { return $.extend(new Validator.Assert().LessThanOrEqual(value), { priority: 30 }); UT : validate your methods API and behavior ! } it('should have a max validator', function () { expect(parsleyValidator.validate('foo', parsleyValidator.max(10))).to.be(false); expect(parsleyValidator.validate('5', parsleyValidator.max(10))).to.be(true); expect(parsleyValidator.validate('10', parsleyValidator.max(10))).to.be(true); expect(parsleyValidator.validate('42', parsleyValidator.max(10))).to.be(false); }); ✓ should have a max validator Code Test Result
  • 14. Why testing? max: function (value) { return $.extend(new Validator.Assert().LessThan(value), { priority: 30 }); Prevent regressions, ensure 3rd party libs consistency ! } it('should have a max validator', function () { expect(parsleyValidator.validate('foo', parsleyValidator.max(10))).to.be(false); expect(parsleyValidator.validate('5', parsleyValidator.max(10))).to.be(true); expect(parsleyValidator.validate('10', parsleyValidator.max(10))).to.be(true); expect(parsleyValidator.validate('42', parsleyValidator.max(10))).to.be(false); }); 1) should have a max validator Code Test Result
  • 17. Why testing? Fixes bugs found to ensure they’ll never show up again ! it('should have a max validator', function () { expect(parsleyValidator.validate('foo', parsleyValidator.max(10))).to.be(false); expect(parsleyValidator.validate('5', parsleyValidator.max(10))).to.be(true); expect(parsleyValidator.validate('10', parsleyValidator.max(10))).to.be(true); expect(parsleyValidator.validate('42', parsleyValidator.max(10))).to.be(false); expect(parsleyValidator.validate('5', parsleyValidator.max(”10”))).to.be(true); }); ✓ should have a max validator Code Test Result max: function (value) { return $.extend(new Validator.Assert().LessThan(value), { priority: 30, requirementsTransformer: function () { return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value; } }); }
  • 18. Why testing? it('should show custom error message with variabilized parameters', function () { $('body').append('<input type="text" id="element" value="bar" data-parsley-minlength="7" data-parsley-minlength- message="foo %s bar"/>'); var parsleyField = $('#element').psly(); parsleyField.validate(); ! expect($('ul#parsley-id-' + parsleyField.__id__ + ' li').text()).to.be('foo 7 bar'); }); Functional test : validate your end-user behavior
  • 19. Why testing? it('should save some calls for querries already done', function (done) { $('body').append('<input type="text" data-parsley-remote="http://foo.bar" id="element" required name="element" value="foo" />'); var parsleyInstance = $('#element').parsley(); ! sinon.stub($, 'ajax').returns($.Deferred().resolve({}, 'success', { status: 200, state: function () { return 'resolved' } })); parsleyInstance.asyncIsValid() .done(function () { expect($.ajax.calledOnce).to.be(true); expect($.ajax.calledWithMatch({ data: { "element": "foo" } })).to.be(true); $.ajax.restore(); sinon.stub($, 'ajax').returns($.Deferred().reject({ status: 400, state: function () { return 'rejected' } }, 'error', 'error')); ! $('#element').val('bar'); parsleyInstance.asyncIsValid() .fail(function () { expect($.ajax.calledOnce).to.be(true); expect($.ajax.calledWithMatch({ data: { "element": "bar" } })).to.be(true); ! $.ajax.restore(); sinon.stub($, 'ajax').returns($.Deferred().resolve({}, 'success', { status: 200, state: function () { return 'resolved' } })); $('#element').val('foo'); ! parsleyInstance.asyncIsValid() .done(function () { expect($.ajax.callCount).to.be(0); expect($.ajax.calledOnce).to.be(false); $.ajax.restore(); done(); }); }); }); });
  • 20. What need to be tested?
  • 21. What need to be tested? • Application logic (services, algorithms, microapps)! • API responses! • Application behavior, End-user responses! ! TO BE TESTED
  • 22. What need to be tested?
  • 23. What need to be tested? • getters / setters! • already tested 3rd party libraries! • ORM, all exceptions, errors! ! NOT TO BE TESTED
  • 24. What need to be tested?
  • 25. What need to be tested? 100% coverage!
  • 26. What need to be tested?
  • 27. What need to be tested?
  • 28. What need to be tested?
  • 31. How to test? class SynchronizedUserTest extends PHPUnit_Framework_TestCase { /** * @covers ::construct() * @expectedException InvalidArgumentException * @expectedExceptionMessage User and IntercomUser are not the same. */ public function testConstructWithWrongEmails() { $intercomUser = new IntercomUser(1, 'bar@foo.fr'); $user = (new User)->setEmail('foo@bar.fr'); $this->setProperty($user, 'id', 1); ! new SynchronizedUser($intercomUser, $user); } ! /** * @covers ::construct() * @expectedException InvalidArgumentException * @expectedExceptionMessage User and IntercomUser are not the same. */ public function testConstructWithWrongIds() { $intercomUser = new IntercomUser(2, 'foo@bar.fr'); $user = (new User)->setEmail('foo@bar.fr'); $this->setProperty($user, 'id', 1); ! new SynchronizedUser($intercomUser, $user); } }
  • 32. How to test? class SynchronizedUser { private $intercomUser; private $user; ! /** * @throws InvalidArgumentException If the user intercom and user wisembly doesn't match */ public function __construct(IntercomUser $intercomUser, User $user) { if ($intercomUser->getUserId() !== $user->getId() || $intercomUser->getEmail() !== mb_strtolower($user->getEmail(), mb_detect_encoding($user->getEmail()))) { throw new InvalidArgumentException('User and IntercomUser are not the same.'); } ! $this->intercomUser = $intercomUser; $this->user = $user; } ! /** * @return IntercomUser */ public function getIntercomUser() { return $this->intercomUser; } ! /** * @return User */ public function getUser() { return $this->user; } }
  • 35. Tools • PHPUnit! • Behat, PHPSpec..! • Mocha, Jasmine, QUnit..! • Karma, PhantomJS, TestEM..! • Travis, Jenkins, Shipper, CodeShip..! !
  • 36. Limits • CSS glitches! • User experience! • Browser compatibility! • Do not take to much time to code / maintain tests!! • Do not have too long test suites!! • Fixtures for functional tests! • Isolate tests among themselves!! !
  • 37. Going further • Script & test deploy scripts..! • SLA & performance tests..! !