SlideShare ist ein Scribd-Unternehmen logo
1 von 38
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascriptcrgwbr
 
async/await Revisited
async/await Revisitedasync/await Revisited
async/await RevisitedRiza 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 BackboneRafael 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 - 4DevelopersKacper Gunia
 
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 2Kacper Gunia
 
Functional Structures in PHP
Functional Structures in PHPFunctional Structures in PHP
Functional Structures in PHPMarcello Duarte
 
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 UnConRafael 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 JasmineTim Tyrrell
 
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 ExtbaseJochen Rau
 

Was ist angesagt? (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
 

Ähnlich wie 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 JavaScriptRyan Anklam
 
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 2015Fernando Daciuk
 
JQuery Presentation
JQuery PresentationJQuery Presentation
JQuery PresentationSony Jain
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testingVisual Engineering
 
Security Challenges in Node.js
Security Challenges in Node.jsSecurity Challenges in Node.js
Security Challenges in Node.jsWebsecurify
 
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 typeWim Godden
 
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 jsFrancois Zaninotto
 
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.8Michelangelo 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 tek12Michelangelo van Dam
 
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 SwiftPeter Friese
 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experiencedrajkamaltibacademy
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
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...Martijn de Jong
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
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 DevelopmentsTrustArc
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 

Kürzlich hochgeladen (20)

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
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...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
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
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 

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..! !