why we Test ?
1.Tests provide assurance of functionality.
2.Tests reduce cost of change.
3.Tests encourage modular,reusable code.
4.Tests help identify engineering and architectural bugs.
5.Tests help document expected behavior.
6.Test + code = less likely to produce bugs.
Principle #1 :
A Test without Assert methods isn't a test it's a liability.
Three Assert methods built-in
System.Assert(boolean-expression,'friendly message')
System.AssertEquals(expect,actual,'friendly message')
System.AssertNotEquals(expect,actual,'friendly message')
Every test method should include at least one assertion.
Good test methods includes more than one.
The most robust,and helpful test methods include two sets of Asserts.
Assert that you properly setup all your test data.
Assert that the given test data was properly mutated by your code.
Principle #2 :
Start (then) Stop , Collaborate and Listen
Test.startTest() and Test.stopTest() help facilitate testing.
Isolates your code from the proper setup of the test(s).
startTest() resets DML,CPU Time and other governor limits,ensuring any limits you hit come from your tested code.
stopTest() forces asynchronous code to complete.
Principle #3 (Positive Tests) :
you should write 'Positive Tests'.
Positive tests prove the expected behavior, which is to say they prove it does what you think it does.
ex :
System.assertEquals(12,testValue,'Expected 5+7 to equal 12');
Principle #4 (Negative Tests) :
Negative tests prove that your code properly handles exceptions and errors.
The pattern works by calling method within a try/catch block in the test.
catch only the expected type of exception in the catch block.
Less intuitive but more powerful !.
At the very least, negatively test methods that utilize user data.
ex :
Boolean didcatchProperException = false;
Test.startTest();
try{
examplecode.divide(1,0);
} catch(exampleCodeException AWesomeEception){
didcatchProperException =true;
}
Test.stopTest();
System.assert(didcatchProperException,'Properly caught custom Exception);
Principle #5 (User Tests) :
User based tests prove your security model works like you think it does.
Tests with Users of different Roles/Profiles and Permission sets !.
The pattern works like this : Create a user with a given profile.
As needed assign permission sets.Test both positive and negative users.
ex (Positive User Test):
exampleCode drWho = new exampleCode();
User u = AwesomeTestLib.getUserWithProfile('jediProfile');
Account a =(Account) TestFactory.createSObject(new Account());
Integer result;
system.runAs(u){
Test.startTest();
result = drWho.getBankAccount(a);
Test.stopTest();
}
System.assertNotEquals(result,null,'Expected the Doctor to have access to bank ');
ex (Negative User Test) :
exampleCode dalerk = new exampleCode();
User u = AwesomeTestLib.getUserWithProfile('DalerkProfile');
Account a =(Account) TestFactory.createSObject(new Account());
Integer result;
system.runAs(u){
Test.startTest();
result = dalerk.getBankAccount(a);
Test.stopTest();
}
System.assertEquals(result,null,'Expected Dalerk to be blocked');
ex (Testing with Permission Set)
exampleCode Claraoswald = new exampleCode();
User u = AwesomeTestLib.getUserWithProfile('Standard User');
UtilityClass.AssignUserToPermissionSet(u,'Companion');
Account a =(Account) TestFactory.createSObject(new Account());
Integer result;
system.runAs(u){
Test.startTest();
result = Claraoswald.canAccessTardis(a);
Test.stopTest();
}
System.assertNotEquals(result,null,'Expected ClaraoOswald who has Companion to have access to the Tardis');
Principle #6 (Use your own data) :
Always build your own test data.
If you created the data,you can precisely assert against it.
Unless you have to,never use @isTest(seeAllData=true)
List of Acceptable Reasons to use @seeAllData =true.
Reason : you're unit testing Approval Processes.
TestFactory, An open source test data factory.
Url : https://github.com/dhoechst/Salesforce-Test-Factory
ex :
Account a =(Account)TestFactory.createSobject(new Account());
Opportunity o = (Opportunity)TestFactory.createSObject(new Opportunity(AccountId = a.Id));
Account[] aList=(Account[])TestFactory.createSObjectList(new Account(),200);
Principle #7 (Use a domain specific helper lib) :
Use a sane naming convention. i.e: Get* returns generated test data matching the method name !.
Mark your test helper class as @isTest to ensure it's never called by live code.
Principle #8 (Mocking) :
Integration v. Unit tests
Integration tests test code in an execution context -
i.e. setup some data and execute the code within the context.
Unit tests focus on a single unit of code,not necessarily a complete function.
Mocks allow us to write true unit tests by 'mock' objects.
You get to setup the mock, and it's responses.
Unit Test w/Mocks
Calls a mocked service
Returns exactly what you asked it to.
use the excellent and amazing fflib_ApexMocks.
Code to interfaces so you can Mock it good.
Principle #9 (Write for testing) :
keep your methods to no more than 20 lines.
Keep method arguments to a minimum - no more than four.
Write your Visualforce controllers to use a single wrapper object.
Principle #10 (Use Continuous Integration):
Continuous Integration is the process that enforces a full and complete test run is triggered every time someone commit to your source repository. You are using Git right?
A number of tools are available for CI on the Salesforce1 platform.
Travis.ci,Drone.io,Jenkins,Bamboo and Codeship are some examples.
No comments:
Post a Comment