Consider a case where your organization currently uses Salesforce.com for its Customer Relationship Management (CRM) solution and it is becoming apparent that your future business goals are not going to be met by continuing to use built-in Salesforce functionality. Alternatively, imagine you lead a team of developers with the intention of writing applications for the Salesforce AppExchange. In either case, you are seeking benefit from branching out from built-in Salesforce functionality with custom Apex code. Here are some things to think about when making the transition.
Generally any cloud based platform imparts some restrictions on the custom code uploaded to their servers in order to ensure extremely reliable service to their users. For Salesforce’s Force.com platform, this means that all custom code that is written must be adequately unit tested and achieve 75% code coverage before being deployed to a production environment or placed on the Force.com AppExchange. Code coverage is a simple metric, expressed as a percentage, which describes the degree to which the code of a program has been tested. In the context of Apex code, this percentage is calculated by dividing the number of lines of Apex code executed when your test methods run by the total number of Apex code lines.
If your development team is accustomed to test driven development or writing unit tested code, then this requirement may be simple to fulfill. If your team has no experience writing unit tests, or the philosophy of test driven development is unfamiliar, then special care needs to be applied in the execution of this requirement. Here are some possible challenges in writing properly tested code Apex code.
My organization has a limit as to how many megabytes of custom code we’re allowed to store on the server, are these unit tests going to count toward that total?
The short answer is no. Although your test methods are in fact Apex code, if you remember to tag your test methods with the @isTest annotation, Salesforce will not count your test methods toward your organization’s total code allocation. If this annotation is omitted, Salesforce will count test methods toward your organization’s total, so be sure to add this annotation before all your test methods as shown below.
Using the @isTest annotation
If 75% code coverage is the minimum requirement, should it be our policy to settle for the minimum requirement or should we strive for as close to 100% code coverage as possible?
There are some special situations that could prevent you from ever reaching 100% code coverage with your unit tests. These scenarios will be covered a bit later. We can first focus on why striving for near 100% code coverage is considered best practice. To begin, if unit tests are written correctly, they assure that the code you write is indeed functioning as intended. For example, if a test method only covers three out of the four possible logic branches of a method within your application, you are essentially agreeing to take the chance that the method may operate improperly 25% of the time. Secondly, if you find that you are struggling to get 100% code coverage for a particular section of code, there stands a very good chance that your code is a good candidate for refactoring. The process of unit testing lends itself to the production of code that is modular, flexible, and extensible because monolithic code sections are naturally not amenable to the process of unit testing.
Finally, consider a situation where you need to augment a mission critical component of your application and get it deployed as quickly as possible. If your team has made the decision to hover right at the 75% code coverage requirement, the new, un-tested feature may drop your code coverage to 73%, for example. Now one of your developers is stuck writing at least one unit test to become compliant, therefore extending the time before the new code is up and running in production. On the other hand, if your team committed to near 100% code coverage, your feature would be able to be pushed into production right away, and the unit testing could be taken care of afterward. This is somewhat of an extreme situation, and goes against the test driven methodology, but it is worth noting. The take away message here is to focus on getting as close to 100% code coverage as possible. Your solution will be better for the effort.
There are some restrictions Salesforce has in place that prevent all code from being covered by unit testing. How should we overcome this?
As mentioned earlier, 100% code coverage may not be a realistic option. One example of this situation arises when the custom code you write is consuming one or more third party web services. The Force.com platform clearly has no control over these web services: the data they return, when they fail, when they are down for maintenance, etc. For this reason, Salesforce cannot predict the impact of calling a third party web service. As a result, your team will not be allowed to invoke a third party web service from within a unit test. So how do we develop a unit test that provides the appropriate coverage? The answer lies in how you structure the code that makes up the web service logic. The key is to create a function that does nothing but invoke the web service, making it as small as possible. Next, push all logic that involves either building the web service request, or handling the web service response, into separate functions. This minimizes the amount of code that the unit test is not capable of covering. You may now ask yourself, “If I am unable to invoke a web service from a test method (and thus get a response), how am I supposed to test the logic than handles the web service response?” Unfortunately, your developers are going to have to build every possible type of response object you expect to see, from scratch, within the test method(s) to simulate responses from the web service.
We are required to write unit tests for all our custom Apex code. Is it possible for our team to write these tests after the development of the code is finished or should we consider a full blown test driven development approach?
Of course the answer to this question depends on your team and various project considerations, but test driven development should be strongly considered when doing any sort of complex, custom Salesforce development. Test driven development is a software development methodology that begins with a developer writing a failing unit test. The test is a way of defining the functional goals of a given piece of code before the implementation is actually written. The next step is for the developer to produce code that passes the unit test. The merits of this development style can (and will) be argued, but there is no way around writing unit tests for production Apex code, so this approach will generally yield favorable results. If your team decides against using a test driven development approach when implementing custom Salesforce functionality, be absolutely sure to constantly assess how easily the code that is being written can be tested. Do not let the care given to unit testing be given in retrospect. This can save your team lots of time, refactoring code just to make it testable can be a huge time sink.
The code coverage requirements imparted by the Salesforce production environment should not be considered as a hindrance to your goals. Instead, these requirements should be seen as an opportunity to ensure a quality, robust solution. Test driven development can lead to reduced implementation time because the test methods impose requirements that are constantly in the minds of the developers, leading to lower occurrences of code defects. In addition, you can be confident that the final implementation of your solution works exactly as intended. These topics just scratch the surface of custom Salesforce development and the test driven development process, but hopefully it has been a catalyst for your own thoughts and considerations regarding your organization’s desired custom Salesforce functionality.
Build meaningful customer relationships and accelerate delivery with Salesforce Solutions