dreamforce campfire - apex testing tips and tricks
TRANSCRIPT
Useful Apex Development Tools
Daniel BallingerSalesforce MVP
@FishOfPrey | fishofprey.com
• Running anonymous apex in a testing context• Running a single test method in isolation• Adding eval() support to Apex• Catching the uncatchable• Becoming an MVP• Dreamforce 2015
Topics
• Idea Exchange - Running anonymous apex in a testing contextSystem.TypeException: Cannot call test methods in non-test context
• Avoid side effects - built in isolation and rollback• Run single test methods
– Faster turn around– See the log from the individual test case– Avoid encountering log size limit
Objective - circa 2012
The hard way - Using the Metadata API
• Test class and test method must be public
@IsTest public class Foo {
// Many other test methods here
public static testMethod void bar() { System.Debug(LoggingLevel.Debug,'Example Foo.bar() method'); // Assertions and testing stuff } }
Existing Apex Test Class
• Create a wrapper class and call the test method
• Zip generated files• Metadata API deploy()
– DeployOptions• checkOnly = true• runTests = array with generated class name• testLevel = RunSpecifiedTests (v34.0)
• DebuggingHeader to control logging for transaction
@IsTest public class FooWrapper { public static testMethod void barWrapper() { Foo.bar(); } }
FooWrapper.cls
FooWrapper.cls-meta.xml
Demo
Running a single test method via the Metadata API
The easy way - REST API
• REST API only at this stage (Summer `15)• Accepts classIds (01p) and test method names• Support for:
– @testSetup annotation– private methods
• Winter `16 Dev Console
POST /runTestsAsynchronous/
Body { "tests":[ { "classId":"<classId 1>", "testMethods":[ "testMethod1", "testMethod2", "testMethod3" ] }, { "classId":"<classId 2>", "testMethods":[ "testMethod1", "testMethod2" ] } ]}
Demo
Running a single test method via the REST API
• The same technique can be used for anonymous apex• Deploy it as an Apex Test
Anonymous Apex in a testing context
Demo
Testing context anonymous apex
• An alternative view of Apex test execution to highlight failures– Focus on failures first – successes are just noise
• Filter to select the tests you want to run• Ability to start a new test run from previous result *• Rerun the last selection *• Start single method runs *• Monitor progress using the Streaming API
Running Apex tests
* Winter `16Developer
Console
• An alternative view of Apex test execution to highlight failures– Focus on failures first – successes are just noise
• Filter to select the tests you want to run• Ability to start a new test run from previous result *• Rerun the last selection *• Start single method runs *• Monitor progress using the Streaming API
Running Apex testsDeveloper Console Test Results
• An alternative view of Apex test execution to highlight failures– Focus on failures first – successes are just noise
• Filter to select the tests you want to run• Ability to start a new test run from previous result *• Rerun the last selection *• Start single method runs *• Monitor progress using the Streaming API
Running Apex testsApex Test Execution
Demo
Running Apex Tests
• Separate callout context can have rollback.• A way of increasing limits. • Structured data can be returned using JSON• Handle uncatchable exceptions
– System.LimitException – System.ProcedureException
http://www.fishofprey.com/2014/11/adding-eval-support-to-apex.html
Adding eval() support to Apex
Winter `16Unlimited Callouts
to Internal Salesforce URLs
Request<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:apex="http://soap.sforce.com/2006/08/apex"> <soapenv:Header> <apex:DebuggingHeader> <apex:categories> <apex:category>Apex_code</apex:category> <apex:level>ERROR</apex:level> </apex:categories> <apex:debugLevel>NONE</apex:debugLevel> </apex:DebuggingHeader> <apex:SessionHeader> <apex:sessionId>00D700000000001!AQoAQGrYU000NotARealSessionIdUseYourOwnswh4QHmaPFm2fRDgk1zuXcVvWTfB4L9n7BJf</apex:sessionId> </apex:SessionHeader> </soapenv:Header> <soapenv:Body> <apex:executeAnonymous> <apex:String>Integer i = 314159; System.debug(LoggingLevel.Error, i);</apex:String> </apex:executeAnonymous> </soapenv:Body> </soapenv:Envelope>
Response<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/08/apex" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Header> <DebuggingInfo> <debugLog>31.0 APEX_CODE,ERROR Execute Anonymous: Integer i = 314159; System.debug(LoggingLevel.Error, i); 13:24:24.027 (27564504)|EXECUTION_STARTED 13:24:24.027 (27573409)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex 13:24:24.028 (28065096)|USER_DEBUG|[1]|ERROR|314159 13:24:24.028 (28098385)|CODE_UNIT_FINISHED|execute_anonymous_apex 13:24:24.029 (29024086)|EXECUTION_FINISHED</debugLog> </DebuggingInfo> </soapenv:Header> <soapenv:Body> <executeAnonymousResponse> <result> <column>-1</column> <compileProblem xsi:nil="true"/> <compiled>true</compiled> <exceptionMessage xsi:nil="true"/> <exceptionStackTrace xsi:nil="true"/> <line>-1</line> <success>true</success> </result> </executeAnonymousResponse> </soapenv:Body> </soapenv:Envelope>
Demo
Apex eval()
Limit Bypass technique• What if you could catch
the uncatchable?• https://twitter.com/ca_peterson/
status/629057120931962885
// https://gist.github.com/capeterson/860984f889a56f1adf06public class Unbreakable { public static String somethingFragile() { while(true) { List<Account> a = [SELECT id FROM Account LIMIT 1]; } return null; }
// Attempt to serialize this private String it { get { return somethingFragile(); } } public static void catchTheUncatchable() { String val; try { //The system namespaced JSON.serialize implementation catches *any* type, //and surfaces it as a JSONException, which we can catch back in apex land val = JSON.serialize(new Unbreakable()); } catch(JSONException e) { System.debug(LoggingLevel.INFO, 'A LimitException was caught as a JSONException! \n' + e); } }}
Demo
Uncatchable
Deploying multiple files at once
• Creating Metadata API deploy package
Becoming an MVP• Presented at Auckland User Group - 2014• Presented at Dreamforce 2014• Wsdl2Apex Hackathon• Helped numerous people with SOAP integrations• Answered and asked questions on Salesforce
StackExchange • Blogged – FishOfPrey.com• Tweeted• Feedback to the Salesforce Docs team• Visual Studio - Salesforce Connected Services
Dreamforce 2015 Sessions
• Welkin Suite• Meet the developers• Foosball IoT
• My unconference/campfire conversation9 am DevZone
Q&A• Download: free FuseIT SFDC Explorer Tool
http://www.fuseit.com/explorer
www.fuseit.com@FishOfPrey
www.fishofprey.com