SlideShare une entreprise Scribd logo
1  sur  86
Télécharger pour lire hors ligne
Tests and Testability
Apex Structure and Strategy
Stephen Willcock, FinancialForce.com, Director of Product Innovation
@stephenwillcock
All about FinancialForce.com
Revolutionizing the Back Office
#1 Accounting, Billing and PSA Apps on the Salesforce platform

▪ Native apps
▪ San Francisco HQ, 595 Market St
▪ R&D in San Francisco, Harrogate UK, and Granada ES
▪ We are hiring! Meet us at Rehab!
Tests and Testability - overview
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Testing strategy
In an ideal world we would test…
An entire system “end-to-end”
Using different types of user
With production data volumes
With complex / varied data profiles
All possible code paths
SIMULTANEOUSLY!
Test pyramid
Fewer tests

More
numerous
tests

More
complex
tests
Less
complex
tests
Test pyramid
Test pyramid
The test pyramid is a concept
developed by Mike Cohn....
[the] essential point is that you
should have many more lowlevel unit tests than high level
end-to-end tests running
through a GUI.
http://martinfowler.com/bliki/TestPyramid.html
Test pyramid
Even with good practices on writing them, end-to-end tests are
more prone to non-determinism problems, which can undermine
trust in them.
In short, tests that run end-to-end through the UI are: brittle,
expensive to write, and time consuming to run.
So the pyramid argues that you should do much more
automated testing through unit tests than you should through
traditional GUI based testing.
http://martinfowler.com/bliki/TestPyramid.html
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Unit test principles - what is a unit?
The smallest testable chunk of code
Independent from other units and systems

Uno
Unit test principles - what is a unit?
Unit test principles - what is a unit?
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Unit test principles - isolation
https://

Uno

Uno

Uno

Uno
@

Uno
Trigger
Validation Rule
Workflow Rule

Uno

Managed Apex

Database
Related Data

…further
dependencies
Unit test principles - isolation
Uno

Uno

Mocked resources
Database
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Unit test principles - saturation
The Force.com platform requires that at least 75% of the Apex
Code in an org be executed via unit tests in order to deploy the
code to production. You shouldn’t consider 75% code coverage to
be an end-goal though
Instead, you should strive to increase the state coverage of
your unit tests
Code has many more possible states than it has lines of code
http://wiki.developerforce.com/page/How_to_Write_Good_Unit_Tests
Unit test principles - saturation
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Unit test principles - expectation
Unit test
•Stakeholder: developers
•Asks: does this code do what it says it will?
System test
•Stakeholder: Business Analyst
•Asks: does this system fulfil my functional requirements?
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Unit test principles - testability
Unit test principles - testability
Well structured, Object Oriented code is likely to be testable:
•Encapsulation - well defined inputs and outputs
•Limited class scope
•Limited class size
•Limited method size
TDD
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
SObject fabrication

Insert supporting
data

Evaluate and
assert

Read data

Insert test data

Database commit

Trigger fires

Triggered record
update

Unit test
SObject fabrication - the unit
trigger OpportunityLineItems on OpportunityLineItem
(before insert) {
for(OpportunityLineItem item : Trigger.new) {
if(item.Description==null)
item.Description = 'foo';
}
}
SObject fabrication - the test

AccountId
StageName
OpportunityLineItem oli = new OpportunityLineItem (
insert new
CloseDate
Description=null );
Opportunity
insert oli;

insert new
oli = [select Description from OpportunityLineItem where
Account
OpportunityId
id=:oli.Id];
UnitPrice
Quantity
insert new
insert new
system.assertEquals('foo',oli.Description);
PricebookEntryId
PricebookEntry
Product2

Select Id from
Pricebook2
SObject fabrication - the test
a = new Account(…); insert a;
o = new Opportunity(…); insert o;
pb = [select Id from Pricebook2 … ];
p = new Product2(…); insert p;
pbe = new PricebookEntry(…); insert pbe;
oli = new OpportunityLineItem(…); insert oli;
oli = [select … from OpportunityLineItem …];
system.assertEquals('foo',oli.Description);
SObject fabrication - the revised unit
trigger OpportunityLineItems on OpportunityLineItem
(before insert) {
new OpportunityLineItemsTriggerHandler().beforeInsert(
Trigger.new );
}

Testable code:
break up the Trigger
SObject fabrication - the revised unit
public class OpportunityLineItemsTriggerHandler {
public void beforeInsert(List<OpportunityLineItem>
items) {
for(OpportunityLineItem item : items) {
if(item.Description==null)
item.Description = 'foo';
}
}
}

Avoid referring to
Trigger variables in the
handler

Testable code:
break up the Trigger
SObject fabrication - the revised test
OpportunityLineItem oli = new OpportunityLineItem(
Description=null );
new OpportunityLineItemsTriggerHandler().beforeInsert(
new List<OpportunityLineItem>{oli});
system.assertEquals('foo',oli.Description);
SObject fabrication #2 - the unit
public class OpportunityService {
public void adjust(OpportunityLineItem oli) {
oli.UnitPrice += (oli.UnitPrice *
oli.Opportunity.Account.Factor__c);
}
}
SObject fabrication #2 - the test
Account a = new Account(Factor__c=0.1);
Opportunity o = new Opportunity(Account=a);
OpportunityLineItem oli = new OpportunityLineItem(
Opportunity=o, UnitPrice=100);
OpportunityService svc = new OpportunityService();
svc.adjust(oli);
system.assertEquals(110,oli.UnitPrice);
SObject fabrication - what did we do?
Structured the code to make it easier to test
•Trigger handler / Trigger
Fabricated SObjects (including relationships)
•In-memory
•No database interaction
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Loose type coupling
Use inheritance to “loosen” a relationship
•Interface
•Superclass
Substitute a mock “sibling implementation” during unit tests
Loose type coupling
Consumer

Provider

OrderController
(Custom
Controller)

Aggregator

OrderController.Item
Unit test
Loose type coupling - the provider (test subject)
public class Aggregator {
List<OrderController.Item> items;
public void setItems(List<OrderController.Item> items) {
this.items = items; }
public Decimal getSum() {
Decimal result = 0;
for(OrderController.Item item : this.items)
result += item.getValue();
return result;
}
}
Loose type coupling - the provider test
List<OrderController.Item> testItems = new
List<OrderController.Item>{ new OrderController.Item(…), … };
Aggregator testAggregator = new Aggregator();
testAggregator.setItems(testItems);
system.assertEquals(123.456,testAggregator.getSum());
Loose type coupling - the revised provider
public class Aggregator {
public interface IItem {
Decimal getValue();
}
public void setItems(List<IItem> items) {…}
Loose type coupling - the revised provider
public Decimal getSum() {
Decimal result = 0;
for(IItem item : items)
result += item.getValue();
return result;
}
}
Loose type coupling - the revised consumer
public controller OrderController {
…
public class Item implements Aggregator.IItem {…}
Aggregator a…
List<Item> items…
a.setItems(items);
Decimal s = a.getSum();
Loose type coupling - the revised provider test
class TItem implements Aggregator.IItem {
Decimal value;
TItem(Decimal d) {
value = d;
}
public getValue() {
return value;
}
}
Loose type coupling - the revised provider test
List<TItem> testItems = new List<TItem>{ new TItem(100),
new TItem(20.006), new TItem(3.45) };
Aggregator testAggregator = new Aggregator();
testAggregator.setItems(testItems);
system.assertEquals(123.456,testAggregator.getSum());
Loose type coupling - what did we do?
OrderController.Item

Aggregator.IItem

TItem

Aggregator

Production

Unit
Test
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Dependency Injection
Dependency Injection is all about injecting dependencies, or
simply said, setting relations between instances
Some people refer to it as being the Hollywood principle "Don't
call me, we'll call you”
I prefer calling it the "bugger" principle: "I don't care who
you are, just do what I ask”
http://www.javaranch.com/journal/200709/dependency-injection-unit-testing.
html
Dependency injection
Consumer

Provider

Opportunity
Controller

Opportunity
Adjuster

Opportunity o;
OpportunityAdjuster a;
a = new OpportunityAdjuster();
a.adjust(o);
Unit test
Dependency injection
Production
usage
Opportunity
Adjuster
Opportunity
Controller

Unit test
usage
Inject
dependency

TOpportunity
Adjuster
Opportunity
Controller
Dependency injection - interface
public interface IAdjustOpportunities {
void adjust(Opportunity o);
}
Dependency injection - provider
public with sharing class OpportunityAdjuster implements
IAdjustOpportunities {
public void adjust(Opportunity o) {
// the actual implementation
// do some stuff to the opp
}
}
Dependency injection - mock provider
public with sharing class TOpportunityAdjuster
implements IAdjustOpportunities {
@testVisible Opportunity opp;
@testVisible Boolean calledAdjust;
public void adjust(Opportunity o) {
opp = o;
calledAdjust = true;
}
}

@testVisible
Dependency injection - consumer
public class OpportunityController {
IAdjustOpportunities adjuster;
@testVisible OpportunityController(
IAdjustOpportunities a,
ApexPages.StandardController c ) {
this.adjuster = a;
…
}
Dependency injection - consumer
public OpportunityController(
ApexPages.StandardController c) {
this(new OpportunityAdjuster(), c);
}
…
public void makeAdjustment() {
adjuster.adjust(opp);
}
Dependency injection - consumer test
Opportunity opp = new Opportunity(…);
ApexPages.StandardController sc = new
ApexPages.StandardController(opp);
TOpportunityAdjuster adjuster = new TOpportunityAdjuster();
OpportunityController oc = new
OpportunityController(adjuster, sc);
oc.makeAdjustment();
system.assert(adjuster.calledAdjust);
system.assertEquals(opp,adjuster.opp);

Constructor
injection
Dependency injection - what did we do?
• Loosen the coupling to a provider class in a consumer class
• Mock the provider class
• Inject the mock provider implementation into the consumer via
a new @testVisible constructor on the consumer class to test
the consumer class
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
SObject Decoupler - the unit
public class OpportunitiesTriggerHandler {
public static void afterUpdate(List<Opportunity> items) {
for(Opportunity item : items) {
if(item.IsClosed){
// do something
}
}
}…
}
SObject Decoupler - the test
@isTest private class OpportunitiesTriggerHandlerTest {
@isTest static void myTest() {
Opportunity o = new Opportunity(IsClosed=true);
OpportunitiesTriggerHandler handler = new
OpportunitiesTriggerHandler();

Field is not writeable:
handler.afterUpdate(new List<Opportunity>{o});
Opportunity.IsClosed
// test something
}

SObject fabrication limitations:
formula fields, rollup summaries,
system fields, subselects
SObject Decoupler - the decoupler
public virtual class OpportunityDecoupler {
public virtual Boolean getIsClosed( Opportunity o ) {
return o.IsClosed;
}
}
SObject Decoupler - the test decoupler
public virtual class TOpportunityDecoupler extends
OpportunityDecoupler {
@testVisible Map<Id,Boolean> IsClosedMap =
new Map<Id,Boolean>();
public override Boolean getIsClosed( Opportunity o ) {
return IsClosedMap.get(o.Id);
}
}
SObject Decoupler - the revised unit
public class OpportunitiesTriggerHandler {
OpportunityDecoupler decoupler;
@testVisible OpportunitiesTriggerHandler(
OpportunityDecoupler od ) {
this.decoupler = od;
}
public OpportunitiesTriggerHandler() {
this(new OpportunityDecoupler());
}

Constructor
injection
SObject Decoupler - the revised unit
public void afterUpdate(List<Opportunity> items) {
for(Opportunity item : items) {
if(decoupler.getIsClosed(item)) {
// do something
}
}
}
}
SObject Decoupler - the revised test
@isTest private class OpportunitiesTriggerHandlerTest {
@isTest static void myTest() {
TOpportunityDecoupler decoupler = new
TOpportunityDecoupler();
Opportunity o = new Opportunity(Id =
TestUtility.getFakeId(Opportunity.SObjectType));
decoupler.IsClosedMap.put(o.Id,true);

Fabrication of
SObject IDs
SObject Decoupler - the revised test
public with sharing class TestUtility {
static Integer s_num = 1;

}

public static String getFakeId(Schema.SObjectType sot) {
String result = String.valueOf(s_num++);
return sot.getDescribe().getKeyPrefix() +
'0'.repeat(12-result.length()) + result;
}

Fabrication of
SObject IDs
SObject Decoupler - the revised test
OpportunitiesTriggerHandler handler = new
OpportunitiesTriggerHandler(decoupler);
handler.afterUpdate(new List<Opportunity>{o});
// test something
}
SObject Decoupler - what did we do?
Mechanism for mocking non-writable SObject properties
•Access the SObject properties via a separate virtual class - the
decoupler
•Decoupler subclass mocks access to non-writable SObject
properties
•Inject the decoupler subclass in the test subject constructor
SObject Decoupler - useful for…
Mocking:
•Formula fields
•System fields
•Rollup summary fields
•Subselects
• Select (Select ... From OpportunityLineItems) From Opportunity
Tests and Testability
Testing strategy
• Test pyramid
Unit test principles
• What is a unit?
• Isolation
• Saturation
• Expectation
Unit test techniques
• Testability
Adapter - for managed classes
IHandleLockingRules

OpportunitiesTrigger
Handler

LockingRule
Handler
(wrapper)

LockingRules.
LockingRule
Handler
(managed class)

Test
LockingRuleHandler
implements
IHandleLockingRules
Adapter - managed class

global class
LockingRuleHandler
static void handleTrigger()
Adapter - interface
public interface IHandleLockingRules {
void handleAfterUpdate(Map<Id,sObject> oldMap,
Map<Id,sObject> newMap);
}
Adapter - wrapper
public class LockingRuleHandler implements
IHandleLockingRules {
public void handleAfterUpdate(Map<Id,sObject> oldMap,
Map<Id,sObject> newMap) {
LockingRules.LockingRuleHandler.handleTrigger();
}
}
Adapter - mock implementation
public class TLockingRuleHandler implements
IHandleLockingRules {
@testVisible Boolean calledHandleAfterUpdate;
public void handleAfterUpdate(Map<Id,sObject> oldMap,
Map<Id,sObject> newMap) {
calledHandleAfterUpdate = true;
}
}
Adapter - the unit
public class OpportunitiesTriggerHandler {
IHandleLockingRules lockingRules;
@testVisible OpportunitiesTriggerHandler(
IHandleLockingRules lr ) {
this.lockingRules = lr;
}
public OpportunitiesTriggerHandler() {
this(new LockingRuleHandler());
}

Constructor
injection
Adapter - the unit
public void handleAfterUpdate(Map<Id,sObject> oldMap,
Map<Id,sObject> newMap) {
lockingRules.handleAfterUpdate(oldMap, newMap);
}
Adapter - the test
Map<Id,Opportunity> oldMap …
Map<Id,Opportunity> newMap …
TLockingRuleHandler lockingRules = new
TLockingRuleHandler();
OpportunitiesTriggerHandler trig = new
OpportunitiesTriggerHandler(lockingRules);
trig.afterUpdate(oldMap,newMap);
system.assert(lockingRules.calledHandleAfterUpdate);
…
Adapter - what did we do?
Mock a managed class
•Create an interface defining our expectations of the managed
class
•Adapt the the managed class by wrapping and implementing
the interface
•Mock the production class by implementing the same interface
•Inject the mock implementation during unit test execution
In a nutshell…
Unit tests are foundational to an effective Apex testing strategy
Consider testability in the structure / design of your code
Units must be independent to be easily tested
Units can be made independent through fabrication and
substitution of connected resources
Going forward…
Tests and Testability on foobarforce.com
Sample code on Github
@stephenwillcock
Stephen Willcock
Director of Product
Innovation at FinancialForce.
com
@stephenwillcock
Tests and Testability: Apex Structure and Strategy

Contenu connexe

Tendances

Unit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by MinitestUnit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by MinitestHosang Jeon
 
QTP Slides Presentation.
QTP Slides Presentation.QTP Slides Presentation.
QTP Slides Presentation.tjdhans
 
What is UFT? HP's unified functional testing.
What is UFT? HP's unified functional testing.What is UFT? HP's unified functional testing.
What is UFT? HP's unified functional testing.Confiz
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)Jen Wong
 
Leveraging Existing Tests in Automated Test Generation for Web Applications
Leveraging Existing Tests in Automated Test Generation for Web ApplicationsLeveraging Existing Tests in Automated Test Generation for Web Applications
Leveraging Existing Tests in Automated Test Generation for Web ApplicationsSALT Lab @ UBC
 
Test in action week 4
Test in action   week 4Test in action   week 4
Test in action week 4Yi-Huan Chan
 
Qtp Basics
Qtp BasicsQtp Basics
Qtp Basicsmehramit
 
Qtp 92 Tutorial
Qtp 92 TutorialQtp 92 Tutorial
Qtp 92 Tutorialsasidhar
 
ALM Phase 2 - Test Configurations, Matrix, Libraries Training
ALM Phase 2 - Test Configurations, Matrix, Libraries TrainingALM Phase 2 - Test Configurations, Matrix, Libraries Training
ALM Phase 2 - Test Configurations, Matrix, Libraries TrainingChris Williams
 
Qtp Presentation
Qtp PresentationQtp Presentation
Qtp Presentationtechgajanan
 
Tdd & clean code
Tdd & clean codeTdd & clean code
Tdd & clean codeEyal Vardi
 
Qtp Training
Qtp TrainingQtp Training
Qtp Trainingmehramit
 
QTP Power Point Presentation
QTP Power Point PresentationQTP Power Point Presentation
QTP Power Point PresentationSVRTechnologies
 
Programmer testing
Programmer testingProgrammer testing
Programmer testingJoao Pereira
 
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The FutureQA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The FutureQAFest
 

Tendances (20)

Ppt Qtp
Ppt QtpPpt Qtp
Ppt Qtp
 
Unit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by MinitestUnit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by Minitest
 
QTP Slides Presentation.
QTP Slides Presentation.QTP Slides Presentation.
QTP Slides Presentation.
 
What is UFT? HP's unified functional testing.
What is UFT? HP's unified functional testing.What is UFT? HP's unified functional testing.
What is UFT? HP's unified functional testing.
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
 
10 Principles of Apex Testing
10 Principles of Apex Testing10 Principles of Apex Testing
10 Principles of Apex Testing
 
Leveraging Existing Tests in Automated Test Generation for Web Applications
Leveraging Existing Tests in Automated Test Generation for Web ApplicationsLeveraging Existing Tests in Automated Test Generation for Web Applications
Leveraging Existing Tests in Automated Test Generation for Web Applications
 
Test in action week 4
Test in action   week 4Test in action   week 4
Test in action week 4
 
Tdd & unit test
Tdd & unit testTdd & unit test
Tdd & unit test
 
Qtp Basics
Qtp BasicsQtp Basics
Qtp Basics
 
Best practices unit testing
Best practices unit testing Best practices unit testing
Best practices unit testing
 
Qtp 92 Tutorial
Qtp 92 TutorialQtp 92 Tutorial
Qtp 92 Tutorial
 
ALM Phase 2 - Test Configurations, Matrix, Libraries Training
ALM Phase 2 - Test Configurations, Matrix, Libraries TrainingALM Phase 2 - Test Configurations, Matrix, Libraries Training
ALM Phase 2 - Test Configurations, Matrix, Libraries Training
 
Qtp Presentation
Qtp PresentationQtp Presentation
Qtp Presentation
 
Tdd & clean code
Tdd & clean codeTdd & clean code
Tdd & clean code
 
Qtp Training
Qtp TrainingQtp Training
Qtp Training
 
QTP Power Point Presentation
QTP Power Point PresentationQTP Power Point Presentation
QTP Power Point Presentation
 
Programmer testing
Programmer testingProgrammer testing
Programmer testing
 
Unit testing, principles
Unit testing, principlesUnit testing, principles
Unit testing, principles
 
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The FutureQA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
 

Similaire à Tests and Testability: Apex Structure and Strategy

Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications nispas
 
Class9_SW_Testing_Strategies.pdf
Class9_SW_Testing_Strategies.pdfClass9_SW_Testing_Strategies.pdf
Class9_SW_Testing_Strategies.pdfFarjanaParvin5
 
John Kent - An Entity Model for Software Testing
John Kent - An Entity Model for Software TestingJohn Kent - An Entity Model for Software Testing
John Kent - An Entity Model for Software TestingTEST Huddle
 
Working with Legacy Code
Working with Legacy CodeWorking with Legacy Code
Working with Legacy CodeEyal Golan
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticLB Denker
 
Beginners overview of automated testing with Rspec
Beginners overview of automated testing with RspecBeginners overview of automated testing with Rspec
Beginners overview of automated testing with Rspecjeffrey1ross
 
Brief Introduction to Agile Software Testing
Brief Introduction to Agile Software TestingBrief Introduction to Agile Software Testing
Brief Introduction to Agile Software TestingYi Xu
 
Episode 5 - Writing unit tests in Salesforce
Episode 5 - Writing unit tests in SalesforceEpisode 5 - Writing unit tests in Salesforce
Episode 5 - Writing unit tests in SalesforceJitendra Zaa
 
Unit testing in Force.com platform
Unit testing in Force.com platformUnit testing in Force.com platform
Unit testing in Force.com platformChamil Madusanka
 
A Software Testing Intro
A Software Testing IntroA Software Testing Intro
A Software Testing IntroEvozon Test Lab
 
Database Unit Testing Made Easy with VSTS
Database Unit Testing Made Easy with VSTSDatabase Unit Testing Made Easy with VSTS
Database Unit Testing Made Easy with VSTSSanil Mhatre
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1Yi-Huan Chan
 
Agile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayAgile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayJordi Pradel
 
An Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnitAn Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnitweili_at_slideshare
 
Unit testing [4] - Software Testing Techniques (CIS640)
Unit testing [4] - Software Testing Techniques (CIS640)Unit testing [4] - Software Testing Techniques (CIS640)
Unit testing [4] - Software Testing Techniques (CIS640)Venkatesh Prasad Ranganath
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014FalafelSoftware
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Lecture #6. automation testing (andrey oleynik)
Lecture #6. automation testing (andrey oleynik)Lecture #6. automation testing (andrey oleynik)
Lecture #6. automation testing (andrey oleynik)Andrey Oleynik
 

Similaire à Tests and Testability: Apex Structure and Strategy (20)

Apex Unit Testing in the Real World
Apex Unit Testing in the Real WorldApex Unit Testing in the Real World
Apex Unit Testing in the Real World
 
Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications
 
Class9_SW_Testing_Strategies.pdf
Class9_SW_Testing_Strategies.pdfClass9_SW_Testing_Strategies.pdf
Class9_SW_Testing_Strategies.pdf
 
John Kent - An Entity Model for Software Testing
John Kent - An Entity Model for Software TestingJohn Kent - An Entity Model for Software Testing
John Kent - An Entity Model for Software Testing
 
Working with Legacy Code
Working with Legacy CodeWorking with Legacy Code
Working with Legacy Code
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
 
Beginners overview of automated testing with Rspec
Beginners overview of automated testing with RspecBeginners overview of automated testing with Rspec
Beginners overview of automated testing with Rspec
 
Brief Introduction to Agile Software Testing
Brief Introduction to Agile Software TestingBrief Introduction to Agile Software Testing
Brief Introduction to Agile Software Testing
 
Episode 5 - Writing unit tests in Salesforce
Episode 5 - Writing unit tests in SalesforceEpisode 5 - Writing unit tests in Salesforce
Episode 5 - Writing unit tests in Salesforce
 
Unit testing in Force.com platform
Unit testing in Force.com platformUnit testing in Force.com platform
Unit testing in Force.com platform
 
A Software Testing Intro
A Software Testing IntroA Software Testing Intro
A Software Testing Intro
 
Database Unit Testing Made Easy with VSTS
Database Unit Testing Made Easy with VSTSDatabase Unit Testing Made Easy with VSTS
Database Unit Testing Made Easy with VSTS
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1
 
Agile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayAgile Software Testing the Agilogy Way
Agile Software Testing the Agilogy Way
 
An Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnitAn Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnit
 
Test Levels & Techniques
Test Levels & TechniquesTest Levels & Techniques
Test Levels & Techniques
 
Unit testing [4] - Software Testing Techniques (CIS640)
Unit testing [4] - Software Testing Techniques (CIS640)Unit testing [4] - Software Testing Techniques (CIS640)
Unit testing [4] - Software Testing Techniques (CIS640)
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Lecture #6. automation testing (andrey oleynik)
Lecture #6. automation testing (andrey oleynik)Lecture #6. automation testing (andrey oleynik)
Lecture #6. automation testing (andrey oleynik)
 

Plus de Salesforce Developers

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSalesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceSalesforce Developers
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base ComponentsSalesforce Developers
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsSalesforce Developers
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaSalesforce Developers
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentSalesforce Developers
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsSalesforce Developers
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsSalesforce Developers
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsSalesforce Developers
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and TestingSalesforce Developers
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilitySalesforce Developers
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce dataSalesforce Developers
 
Lightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An IntroductionLightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An IntroductionSalesforce Developers
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPSalesforce Developers
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceSalesforce Developers
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureSalesforce Developers
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DXSalesforce Developers
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectSalesforce Developers
 

Plus de Salesforce Developers (20)

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component Performance
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base Components
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer Highlights
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX India
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local Development
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web Components
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web Components
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer Highlights
 
Live coding with LWC
Live coding with LWCLive coding with LWC
Live coding with LWC
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and Testing
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura Interoperability
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce data
 
Lightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An IntroductionLightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An Introduction
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCP
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in Salesforce
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data Capture
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DX
 
Get Into Lightning Flow Development
Get Into Lightning Flow DevelopmentGet Into Lightning Flow Development
Get Into Lightning Flow Development
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS Connect
 

Dernier

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
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
 
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
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
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
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
🐬 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
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
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
 
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
 
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
 
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
 
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
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
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
 

Dernier (20)

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
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
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
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
 
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
 
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
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
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
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
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...
 

Tests and Testability: Apex Structure and Strategy

  • 1. Tests and Testability Apex Structure and Strategy Stephen Willcock, FinancialForce.com, Director of Product Innovation @stephenwillcock
  • 2. All about FinancialForce.com Revolutionizing the Back Office #1 Accounting, Billing and PSA Apps on the Salesforce platform ▪ Native apps ▪ San Francisco HQ, 595 Market St ▪ R&D in San Francisco, Harrogate UK, and Granada ES ▪ We are hiring! Meet us at Rehab!
  • 3. Tests and Testability - overview Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 4. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 5. Testing strategy In an ideal world we would test… An entire system “end-to-end” Using different types of user With production data volumes With complex / varied data profiles All possible code paths SIMULTANEOUSLY!
  • 8. Test pyramid The test pyramid is a concept developed by Mike Cohn.... [the] essential point is that you should have many more lowlevel unit tests than high level end-to-end tests running through a GUI. http://martinfowler.com/bliki/TestPyramid.html
  • 9. Test pyramid Even with good practices on writing them, end-to-end tests are more prone to non-determinism problems, which can undermine trust in them. In short, tests that run end-to-end through the UI are: brittle, expensive to write, and time consuming to run. So the pyramid argues that you should do much more automated testing through unit tests than you should through traditional GUI based testing. http://martinfowler.com/bliki/TestPyramid.html
  • 10. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 11. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 12. Unit test principles - what is a unit? The smallest testable chunk of code Independent from other units and systems Uno
  • 13. Unit test principles - what is a unit?
  • 14. Unit test principles - what is a unit?
  • 15. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 16. Unit test principles - isolation https:// Uno Uno Uno Uno @ Uno Trigger Validation Rule Workflow Rule Uno Managed Apex Database Related Data …further dependencies
  • 17. Unit test principles - isolation Uno Uno Mocked resources Database
  • 18. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 19. Unit test principles - saturation The Force.com platform requires that at least 75% of the Apex Code in an org be executed via unit tests in order to deploy the code to production. You shouldn’t consider 75% code coverage to be an end-goal though Instead, you should strive to increase the state coverage of your unit tests Code has many more possible states than it has lines of code http://wiki.developerforce.com/page/How_to_Write_Good_Unit_Tests
  • 20. Unit test principles - saturation
  • 21. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 22. Unit test principles - expectation Unit test •Stakeholder: developers •Asks: does this code do what it says it will? System test •Stakeholder: Business Analyst •Asks: does this system fulfil my functional requirements?
  • 23. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 24. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 25. Unit test principles - testability
  • 26. Unit test principles - testability Well structured, Object Oriented code is likely to be testable: •Encapsulation - well defined inputs and outputs •Limited class scope •Limited class size •Limited method size TDD
  • 27. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 28. SObject fabrication Insert supporting data Evaluate and assert Read data Insert test data Database commit Trigger fires Triggered record update Unit test
  • 29. SObject fabrication - the unit trigger OpportunityLineItems on OpportunityLineItem (before insert) { for(OpportunityLineItem item : Trigger.new) { if(item.Description==null) item.Description = 'foo'; } }
  • 30. SObject fabrication - the test AccountId StageName OpportunityLineItem oli = new OpportunityLineItem ( insert new CloseDate Description=null ); Opportunity insert oli; insert new oli = [select Description from OpportunityLineItem where Account OpportunityId id=:oli.Id]; UnitPrice Quantity insert new insert new system.assertEquals('foo',oli.Description); PricebookEntryId PricebookEntry Product2 Select Id from Pricebook2
  • 31. SObject fabrication - the test a = new Account(…); insert a; o = new Opportunity(…); insert o; pb = [select Id from Pricebook2 … ]; p = new Product2(…); insert p; pbe = new PricebookEntry(…); insert pbe; oli = new OpportunityLineItem(…); insert oli; oli = [select … from OpportunityLineItem …]; system.assertEquals('foo',oli.Description);
  • 32. SObject fabrication - the revised unit trigger OpportunityLineItems on OpportunityLineItem (before insert) { new OpportunityLineItemsTriggerHandler().beforeInsert( Trigger.new ); } Testable code: break up the Trigger
  • 33. SObject fabrication - the revised unit public class OpportunityLineItemsTriggerHandler { public void beforeInsert(List<OpportunityLineItem> items) { for(OpportunityLineItem item : items) { if(item.Description==null) item.Description = 'foo'; } } } Avoid referring to Trigger variables in the handler Testable code: break up the Trigger
  • 34. SObject fabrication - the revised test OpportunityLineItem oli = new OpportunityLineItem( Description=null ); new OpportunityLineItemsTriggerHandler().beforeInsert( new List<OpportunityLineItem>{oli}); system.assertEquals('foo',oli.Description);
  • 35. SObject fabrication #2 - the unit public class OpportunityService { public void adjust(OpportunityLineItem oli) { oli.UnitPrice += (oli.UnitPrice * oli.Opportunity.Account.Factor__c); } }
  • 36. SObject fabrication #2 - the test Account a = new Account(Factor__c=0.1); Opportunity o = new Opportunity(Account=a); OpportunityLineItem oli = new OpportunityLineItem( Opportunity=o, UnitPrice=100); OpportunityService svc = new OpportunityService(); svc.adjust(oli); system.assertEquals(110,oli.UnitPrice);
  • 37. SObject fabrication - what did we do? Structured the code to make it easier to test •Trigger handler / Trigger Fabricated SObjects (including relationships) •In-memory •No database interaction
  • 38. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 39. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 40. Loose type coupling Use inheritance to “loosen” a relationship •Interface •Superclass Substitute a mock “sibling implementation” during unit tests
  • 42. Loose type coupling - the provider (test subject) public class Aggregator { List<OrderController.Item> items; public void setItems(List<OrderController.Item> items) { this.items = items; } public Decimal getSum() { Decimal result = 0; for(OrderController.Item item : this.items) result += item.getValue(); return result; } }
  • 43. Loose type coupling - the provider test List<OrderController.Item> testItems = new List<OrderController.Item>{ new OrderController.Item(…), … }; Aggregator testAggregator = new Aggregator(); testAggregator.setItems(testItems); system.assertEquals(123.456,testAggregator.getSum());
  • 44. Loose type coupling - the revised provider public class Aggregator { public interface IItem { Decimal getValue(); } public void setItems(List<IItem> items) {…}
  • 45. Loose type coupling - the revised provider public Decimal getSum() { Decimal result = 0; for(IItem item : items) result += item.getValue(); return result; } }
  • 46. Loose type coupling - the revised consumer public controller OrderController { … public class Item implements Aggregator.IItem {…} Aggregator a… List<Item> items… a.setItems(items); Decimal s = a.getSum();
  • 47. Loose type coupling - the revised provider test class TItem implements Aggregator.IItem { Decimal value; TItem(Decimal d) { value = d; } public getValue() { return value; } }
  • 48. Loose type coupling - the revised provider test List<TItem> testItems = new List<TItem>{ new TItem(100), new TItem(20.006), new TItem(3.45) }; Aggregator testAggregator = new Aggregator(); testAggregator.setItems(testItems); system.assertEquals(123.456,testAggregator.getSum());
  • 49. Loose type coupling - what did we do? OrderController.Item Aggregator.IItem TItem Aggregator Production Unit Test
  • 50. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 51. Dependency Injection Dependency Injection is all about injecting dependencies, or simply said, setting relations between instances Some people refer to it as being the Hollywood principle "Don't call me, we'll call you” I prefer calling it the "bugger" principle: "I don't care who you are, just do what I ask” http://www.javaranch.com/journal/200709/dependency-injection-unit-testing. html
  • 54. Dependency injection - interface public interface IAdjustOpportunities { void adjust(Opportunity o); }
  • 55. Dependency injection - provider public with sharing class OpportunityAdjuster implements IAdjustOpportunities { public void adjust(Opportunity o) { // the actual implementation // do some stuff to the opp } }
  • 56. Dependency injection - mock provider public with sharing class TOpportunityAdjuster implements IAdjustOpportunities { @testVisible Opportunity opp; @testVisible Boolean calledAdjust; public void adjust(Opportunity o) { opp = o; calledAdjust = true; } } @testVisible
  • 57. Dependency injection - consumer public class OpportunityController { IAdjustOpportunities adjuster; @testVisible OpportunityController( IAdjustOpportunities a, ApexPages.StandardController c ) { this.adjuster = a; … }
  • 58. Dependency injection - consumer public OpportunityController( ApexPages.StandardController c) { this(new OpportunityAdjuster(), c); } … public void makeAdjustment() { adjuster.adjust(opp); }
  • 59. Dependency injection - consumer test Opportunity opp = new Opportunity(…); ApexPages.StandardController sc = new ApexPages.StandardController(opp); TOpportunityAdjuster adjuster = new TOpportunityAdjuster(); OpportunityController oc = new OpportunityController(adjuster, sc); oc.makeAdjustment(); system.assert(adjuster.calledAdjust); system.assertEquals(opp,adjuster.opp); Constructor injection
  • 60. Dependency injection - what did we do? • Loosen the coupling to a provider class in a consumer class • Mock the provider class • Inject the mock provider implementation into the consumer via a new @testVisible constructor on the consumer class to test the consumer class
  • 61. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 62. SObject Decoupler - the unit public class OpportunitiesTriggerHandler { public static void afterUpdate(List<Opportunity> items) { for(Opportunity item : items) { if(item.IsClosed){ // do something } } }… }
  • 63. SObject Decoupler - the test @isTest private class OpportunitiesTriggerHandlerTest { @isTest static void myTest() { Opportunity o = new Opportunity(IsClosed=true); OpportunitiesTriggerHandler handler = new OpportunitiesTriggerHandler(); Field is not writeable: handler.afterUpdate(new List<Opportunity>{o}); Opportunity.IsClosed // test something } SObject fabrication limitations: formula fields, rollup summaries, system fields, subselects
  • 64. SObject Decoupler - the decoupler public virtual class OpportunityDecoupler { public virtual Boolean getIsClosed( Opportunity o ) { return o.IsClosed; } }
  • 65. SObject Decoupler - the test decoupler public virtual class TOpportunityDecoupler extends OpportunityDecoupler { @testVisible Map<Id,Boolean> IsClosedMap = new Map<Id,Boolean>(); public override Boolean getIsClosed( Opportunity o ) { return IsClosedMap.get(o.Id); } }
  • 66. SObject Decoupler - the revised unit public class OpportunitiesTriggerHandler { OpportunityDecoupler decoupler; @testVisible OpportunitiesTriggerHandler( OpportunityDecoupler od ) { this.decoupler = od; } public OpportunitiesTriggerHandler() { this(new OpportunityDecoupler()); } Constructor injection
  • 67. SObject Decoupler - the revised unit public void afterUpdate(List<Opportunity> items) { for(Opportunity item : items) { if(decoupler.getIsClosed(item)) { // do something } } } }
  • 68. SObject Decoupler - the revised test @isTest private class OpportunitiesTriggerHandlerTest { @isTest static void myTest() { TOpportunityDecoupler decoupler = new TOpportunityDecoupler(); Opportunity o = new Opportunity(Id = TestUtility.getFakeId(Opportunity.SObjectType)); decoupler.IsClosedMap.put(o.Id,true); Fabrication of SObject IDs
  • 69. SObject Decoupler - the revised test public with sharing class TestUtility { static Integer s_num = 1; } public static String getFakeId(Schema.SObjectType sot) { String result = String.valueOf(s_num++); return sot.getDescribe().getKeyPrefix() + '0'.repeat(12-result.length()) + result; } Fabrication of SObject IDs
  • 70. SObject Decoupler - the revised test OpportunitiesTriggerHandler handler = new OpportunitiesTriggerHandler(decoupler); handler.afterUpdate(new List<Opportunity>{o}); // test something }
  • 71. SObject Decoupler - what did we do? Mechanism for mocking non-writable SObject properties •Access the SObject properties via a separate virtual class - the decoupler •Decoupler subclass mocks access to non-writable SObject properties •Inject the decoupler subclass in the test subject constructor
  • 72. SObject Decoupler - useful for… Mocking: •Formula fields •System fields •Rollup summary fields •Subselects • Select (Select ... From OpportunityLineItems) From Opportunity
  • 73. Tests and Testability Testing strategy • Test pyramid Unit test principles • What is a unit? • Isolation • Saturation • Expectation Unit test techniques • Testability
  • 74. Adapter - for managed classes IHandleLockingRules OpportunitiesTrigger Handler LockingRule Handler (wrapper) LockingRules. LockingRule Handler (managed class) Test LockingRuleHandler implements IHandleLockingRules
  • 75. Adapter - managed class global class LockingRuleHandler static void handleTrigger()
  • 76. Adapter - interface public interface IHandleLockingRules { void handleAfterUpdate(Map<Id,sObject> oldMap, Map<Id,sObject> newMap); }
  • 77. Adapter - wrapper public class LockingRuleHandler implements IHandleLockingRules { public void handleAfterUpdate(Map<Id,sObject> oldMap, Map<Id,sObject> newMap) { LockingRules.LockingRuleHandler.handleTrigger(); } }
  • 78. Adapter - mock implementation public class TLockingRuleHandler implements IHandleLockingRules { @testVisible Boolean calledHandleAfterUpdate; public void handleAfterUpdate(Map<Id,sObject> oldMap, Map<Id,sObject> newMap) { calledHandleAfterUpdate = true; } }
  • 79. Adapter - the unit public class OpportunitiesTriggerHandler { IHandleLockingRules lockingRules; @testVisible OpportunitiesTriggerHandler( IHandleLockingRules lr ) { this.lockingRules = lr; } public OpportunitiesTriggerHandler() { this(new LockingRuleHandler()); } Constructor injection
  • 80. Adapter - the unit public void handleAfterUpdate(Map<Id,sObject> oldMap, Map<Id,sObject> newMap) { lockingRules.handleAfterUpdate(oldMap, newMap); }
  • 81. Adapter - the test Map<Id,Opportunity> oldMap … Map<Id,Opportunity> newMap … TLockingRuleHandler lockingRules = new TLockingRuleHandler(); OpportunitiesTriggerHandler trig = new OpportunitiesTriggerHandler(lockingRules); trig.afterUpdate(oldMap,newMap); system.assert(lockingRules.calledHandleAfterUpdate); …
  • 82. Adapter - what did we do? Mock a managed class •Create an interface defining our expectations of the managed class •Adapt the the managed class by wrapping and implementing the interface •Mock the production class by implementing the same interface •Inject the mock implementation during unit test execution
  • 83. In a nutshell… Unit tests are foundational to an effective Apex testing strategy Consider testability in the structure / design of your code Units must be independent to be easily tested Units can be made independent through fabrication and substitution of connected resources
  • 84. Going forward… Tests and Testability on foobarforce.com Sample code on Github @stephenwillcock
  • 85. Stephen Willcock Director of Product Innovation at FinancialForce. com @stephenwillcock