
Tips and Best Practices for Testing Salesforce Integrations
Salesforce testing will help you validate your customized Salesforce integrations and functionalities with other enterprise applications. A good test covers all Salesforce modules from accounts to leads, from opportunities to reports, and from campaigns to contacts. As is the case with all tests, there is a good (effective and efficient) way of doing a Salesforce test and a bad way. So, what is Salesforce testing good practice?
- Use the Right Testing Tools – Salesforce testing happens in the browser or in an eclipse-based environment. Both the latest browsers and eclipse have great debugging tools and you can combine these with test classes for very helpful results. However, if you need more, The Apex Interactive Debugger (or simply Apex) by Force.com should be used. Note you can also use Salesforce Lightning Inspector, a chrome extension, to specifically test Salesforce Lightning. Apex is a Force.com platform proprietary programming language that bears great similarities with Java. It is an object oriented, case-insensitive, strongly types programming language that follows curly-brackets and dot-notation syntax. You can use Apex to execute programmed functions during most Force.com processes, including custom links and buttons, updates, deletions, and record insertion event handlers through Visualforce page custom controllers or scheduling.
- Use Proper Naming Conventions – Proper naming of your test methods before you start writing tests is very important. The test method name should have three parts. These are nameOfMethod (name of the individual method you are testing such as insert/update/delete/undelete when testing a trigger, information about TestPath which is flexible such as null contact if you are testing that the contact is null, and valid when testing a positive/negative path.
- Ensure 100% Coverage – Although the standard Salesforce directive is that unit test should have a coverage of 75% of your code (minus test classes, calls to System.debug and test methods) and you will not be able to deploy Apex code or package AppExchange apps, you should note that this is just a standard and your aim should be 100% coverage. Test all the positive/negative cases and for data that is present and not present. Other important tips when it comes to code coverage are:
- You should run tests to refresh code coverage numbers since these numbers are not refreshed when the Apex code is updated until tests are rerun.
- If there has been an update in the organization since the last test run, there is a risk that the code coverage numbers will be incorrect. Rerun the tests for the right estimate.
- The code coverage percentage does not include code coverage from managed packages tests, with the only exception being when these tests cause the triggers to fire.
- Coverage depends on the total number of code lines. If you add or delete lines of code, you will affect the percentage.
- Test Cases in Classes and Controllers – In Salesforce development, most developers create separate classes and controller files for each function. This is done to make coding more organized, easier, reusable, and portable. You should, however, note that while this is easier, it is not more efficient. You will achieve portability if the test code is in the original class and controller code itself since you will not miss out on any test class when migrating from sandbox to production.
- Use System.assert() – In Apex, System.assert() is used to check conditions. This is an important functionality since it allows you to determine if a particular function has been performed by the method as expected. You should use System.assertEquals() and System.assertNotEquals() between critical functionalities not only helps you to determine if the code has been executed as it should, but to also ensure no data is written erroneously if the code goes wrong.
- ComprehensiveTest – Testing should cover everything. You should do functional testing, load testing, security testing, and deployment testing.
- Unit Tests – You should have unit tests to verify that individual records produce the correct and expected result. While using a giant test that covers the entire code may seem like a good idea, note that the results generated will be harder to debug and failure will be harder to understand. A unit test should cover a small subset of the functionality being tested.
- Test Bulk Cases – A good test code (trigger, exception, or class) can be involved for up to several hundred records (200 for Apex). You should take advantage of this and test not only individual records, but also bulk cases.
- Positive Tests – Test to ensure if the expected behavior occurs through all expected permutation. The test should verify that the user correctly filled out the form and that he/she did not go over the limits.
- Negative Tests – Test the negative cases to ensure error messages are produced correctly. Examples of such negative cases are not being able to specify negative amounts and not being able to add future dates. Negative tests are important because correct handling when things go south can make all the difference.
- Automate Testing – Traditionally, Salesforce testing was manual. You should consider automated testing as this offers more advantages. These include:
- Manual testing makes you susceptible to mistakes since testing is by humans and not robots. Robots excel at repetitive activities while humans make mistakes due to boredom, reduced concentration and consistency, and a tendency to cut corners.
- Manual testing is repetitive, formulaic and tiring. The testing team is better off doing work that is more exploratory.
- Execute each Code Logic Branch – When using conditional logic (when you have included ternary operators), each branch of the code logic should be executed.
- Use Invalid and Valid Inputs for Calls to Methods – Calls to methods should be made using both invalid and valid inputs.
- Complete Tests – Ensure that the tests complete successfully – they should not through any exceptions unless the errors are expected. Handle all exceptions caught – catching them is not good enough.
- Use ORDER BY Keywords – To ensure your records are returned in the order you expect them, use the ORDER BY keywords.
- Don’t Assume Record IDs are Arranged Sequentially – Avoid the common mistake of assuming record IDs are arranged in sequential order. The IDs are not in ascending order, unless you’ve inserted multiple records with the same request.
- Call Test.startTest() and Test.stopTest() – When you run an Apex unit test, you will get more than the 75% code coverage that is mandatory in Salesforce. You should call stopTest before assertions to force asynchronous codes that might still be running to finish. Run fresh queries for final results since other code might change data. UsingTest.startTest() and Test.stopTest() ensures you sandbox the test inside its governor limits. This way, the setup code you use will not interfere and give you false negatives or positives surrounding the governor limits. Test.stopTest() also ensures that @future calls will complete for testing.
- Readability – Readability is very important in unit tests. The test names should include the specific action to be taken and the expected result. The method should be descriptive and short. The method should be such that it can be reusable across different tests.
- Build Large Test Data Sets before startTest – Since your tests will be running in different sandbox and production environments, build large test data sets before you call startTest to ensure the test has full execution limits. By default, Salesforce Github runs tests isolated from production data. When you need system data such as a Profile, query to get the right thing for that specific environment.
- Generate Your Own Test Data – The test data you use should be generated in the test. You can generate this data using @testSetup annotation and a TestUtils class to not only ensure you have the right data, but to also ensure all the tests are run on a developer sandbox with no requirement for data.
- Avoid no-op AKA null operations – Many testers use no-op AKA null operations. These are useless codes that do nothing. Since they are already in your code base, they will add to your coverage percentage.
- Parallel Test Execution – When you start tests from the Salesforce user interface or the Developer Console, the tests will run in parallel. This is an important feature as it speeds up test run time. You should, however, note that this can lead to data contention issues and if you suspect this might happen, turn off parallel execution. The most common causes of data contention issues that often lead to UNABLE_TO_LOCK_ROW errors are:
- When tests are meant to update the same records at the same time. Updating of the same records usually happens when tests do not create their own data.
- When there is a deadlock in tests that are running in parallel and they try to create records that have matching index field values. A deadlock will occur when 2 running tests have queued to roll back data (this occurs when 2 tests input records that have the same unique index field values in different orders).
- To turn off parallel test execution, go to Setup, enter Apex Test, go to Apex Test Execution Options dialog, select Disable Parallel Apex Testing, click OK.
Hire a pro for the job since he will have the experience and training necessary to do a good test, which also gives you peace of mind. Hiring a pro allows you to concentrate on your core business. It also saves you money since you will not need an in-house team for the job.