SlideShare uma empresa Scribd logo
1 de 38
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

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
 

Mais procurados (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
 

Semelhante 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
 

Semelhante 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

Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
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
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
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
 
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
 
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
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
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
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
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
 
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
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
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
 
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
 
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
 
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
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 

Último (20)

Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
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...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
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
 
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...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
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
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
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
 
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...
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
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
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 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..! !