Applying Test Driven Development (TDD) on Salesforce Development with Apex — Part 1
I thought I’d share some of my experiences with TDD and guide you through how I apply it to Development on the Salesforce platform.
I know that TDD might not be for everyone, I have recognized that people have different views about this.. some people might think “oh not another fuzzy agile flubdub…” and some people might be completely happy with how they write code and how their team is functioning. I’m just here to give my perspective, some tips and tricks and maybe I’ll help or inspire one or a few of you reading this.
TDD’s role in Salesforce Development
I think us developers in the Salesforce-industry have a special relationship to unit testing and the precious 75% code coverage limit that allows us to deploy code to production. Ever since i started developing on the platform 6 years ago I’ve seen countless times (myself counting) people struggling to push code to production at the last minute and finish off that last percentage of code coverage to be able to successfully ship that functionality out to the users.. And once it’s live, your teammates sanity checks the functionality and you are relieved and think “Oh It works!”. Fast forward and the users start rolling in and so does the zendesk tickets the day after..
The debugging syndrome
Something that I used to do and I see many developers do this today is you write the code and then you test it in the UI and if it doesn’t work, you’ll debug your code, insert x number of “System.debug(‘AccountLIist = ’ + accountList); or console.log statements and figure out where the problem is. This is very time consuming and increases the risk of you missing the actual weakness of your code. According to studies, 50% of development time is spent on fixing bugs or “making your code work”.
TDD to the rescue..
How does TDD work?
In short, the TDD methodology works like this:
- Write Test — Before you implement your code, write a test that will prove that the functionality does not work or simply does not exist. It could also be a test that proves that some functionality is working but shouldn’t work, e.g. code that should be removed.
- Run the test. — The test should fail since the code has not yet been implemented. If the test passes, review your test again.
- Implement the code and make sure the test passes. — Write the code that will fulfill the functionality defined in the in the test, the run the test until the test passes.
- Refactor — Refactor the code and make sure it does its job well and efficient. Since the test is now passing, you will know if you break something.
A Practical example using Apex.
Let’s go through a simple example of how the above can look like.
Imagine the following requirement: “When an Opportunity is created, the name of the Opportunity should be changed to the name of the Account”. This can easily be done without writing code, but we’ll do it through code for this example.
So let’s start with writing the test. We can start writing the test immediately in any test class, for this purpose I’ve created a test class called “OpportunityTriggerTest”, but this class could be named anything, it depends on in which class the code will be implemented.
I’ll write my test according to the requirements:
I’ll run my test and it will fail since the code hasn’t been implemented yet. I get the following failing test result:
Without thinking too much about how my code looks, I’ll implement the functionality and solve the problem — and make sure that the test passes.
I’ll run my tests again and verify that it passes.
Now when I know that the test passes and the functionality works, I can start refactoring my code to make sure it aligns with the team’s view on how the trigger logic should be implemented. In this case I’ll leverage a helper class to separate this code from the trigger.
I’ll call this function from the trigger:
If I run the same test as earlier, it will go through. To go one step further, I will create a test class for the trigger helper class and will test the helper class method with the following code.
Leverage return values!
Make sure you return something in your methods. This makes testing so much easier, see what I did above? Even though the method could’ve been have had a return type of “void” — I still made it return a list of those records that were modified. This is to make it easier to test!
TDD can be applied to all kinds of Salesforce Development/Configuration.
Creating a new Flow or automating stuff through Process builder? Write a unit test. Developing a REST-API using a rest resource, write a unit test where you first define the entities, the different accessible methods and return values. TDD is a mindset and a process and is not limited to any programming language.
In the next part I’ll be sharing more examples of how TDD can be used as a powerful tool when building integrations on the Salesforce platform.