SlideShare una empresa de Scribd logo
1 de 38
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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 a 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
 

Similar a 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
 

Último

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
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
 
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...Miguel Araújo
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
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
 
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
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
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
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
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
 
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
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
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
 

Último (20)

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
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...
 
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...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
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
 
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
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
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
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
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
 
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
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
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
 

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