Unit Tests are vital to the success of your system, but they can be time consuming and sometimes they can feel like they just slow you down. So how do you limit the time you spend on them whilst maximising their value? By turning them into living, accurate and self proving documentation that your developers can rely on, that's how! We'll cover techniques that will both ensure you get the most out of the time spent on unit tests, and help you to spend less time on them too.
Hi, welcome everyone. Rob Baillie - Senior Technical Consultant at makepositive, a platinum partner.
I’ve been working as a developer for just under 20 years, 5 years within the Salesforce ecosystem - and most importantly for this talk - for at least 15 years with Unit Testing in one form or another.
And today I’m going to talk to you about Unit Testing, and most specifically, about how to generate the best value out of them.
But anyway, before we start, I should set some context just in case anyone here hasn’t started down their journey with Salesforce or Unit Testing yet.
So - let’s set that context for people who may be new to Salesforce
Finish this by 2:00
First up - what’s Apex? It’s *the* programming that you use when building functionality *within* the Salesforce platform that’s beyond the ability of standard configuration. It’s essentially the Salesforce platform’s Domain Specific Language - It’s essentially Java like with some simplifications and some very useful abstractions that come from being a part of the Salesforce Platform - but at its heart it’s an Object Oriented language.
What’s Unit Testing? Well, when we write Apex, Salesforce requires us to write more Apex that tests the code we’ve written - to make sure the functionality works.
These are unit tests.
They’re code that exists solely to test other code
So hang on - when you write code in Salesforce, you have to write twice as much? - first the functionality, and then the test for that functionality?
Yes. Yes you do.
And that’s why it’s so important to focus on why you’re writing unit tests when you do it - so you get the best value out of it.
And that’s what I’m going to talk about
I should point out that most of what I say will be fairly generic and can apply to any any type of unit testing, minus a couple of little Apex specific bits - so that’s worth bearing in mind.
So, with that in mind...
Why is Unit Testing such a good idea? Why do we do it?
Finish by: 3:15
Well, there are three main aspects to it, from my perspective. The first two are what people usually talk about when they talk about Unit Testing. The third is something I feel passionate about, but I think is often missed
Firstly - the most basic level - we want to test that the code we’ve built does what we expect it to do. We prove the functionality. Then, once we’ve built it, we want to ensure that it continues to do that, and that whenever it stops doing it that the developer that caused it to change behaviour knows about it. We ensure continuity / stop regression Then, the big thing for me - when it comes to getting that extra value, is that we want to document the intended behaviour of the code - we want to be clear about which behaviour we actively put into our system, as opposed to which behaviours our system accidentally exhibits. We document our intent
Finish by: 5:15
And so if we do this, what are we hoping to achieve? We fill find bugs earlier in our development process The longer it takes us to find a bug in our system, the more expensive it is to fix it - there are plenty of studies out there that prove that. Unit Tests help us to find our bugs really early, and therefore cheaper to fix.
We will Stop Accidental Changes in Behaviour from happening. It’s not unusual for a change in one area to cause an unexpected change of behaviour in another area. Unit Tests can help us spot that happening and ensure that those changes are desired and intended.
It will form a collective memory As developers and BAs roll onto our projects, make decisions and roll off it can be hard to keep track of all those decisions. Good Unit Tests describe all those decisions in terms of their effects on functionality - throughout the whole of a system’s lifespan. They can be especially useful in a consultancy setup, where you *know* that all the developers are going to be gone when you disengage from the Implementation Partner.
It is, in essence 100% Accurate Documentation that actively checks that it remains accurate. The great thing about using Unit Tests as documentation is that it is guaranteed to be accurate - it checks its own accuracy. If the behaviour changes so that the test is not longer correct, it fails and it forces you to either change the behaviour back, or change the documentation to match the behaviour. Not a lot of other documentation will do that for you
And because we have all those things, it Increases our Confidence to Change the system, which can seriously extend the lifespan of it.
OK - so that’s what Unit Tests are, or at least can be - and they’re some pretty lofty benefits
But that’s easy to say - how do we actually get there - what do we need to do?
Finish by 6:30
Well, as I said right at the start, we really need to keep our focus on why we’re writing Unit Tests in the first place, and hopefully from that we’ll drive the right behaviours.
What are those behaviours?
Firstly, we need to get good at testing for the right things For example - if we want to find bugs with our tests, we have to test for the bugs we haven’t found yet
And second up is the main focus of this talk - my main take away - we want to re-frame the way we think about tests so that they become READABLE documentation for the system.
I mean, let’s face it - there’s not much point in having 100% accurate documentation that no-one can understand. But if we want to do that, we’re probably going to need a bit of a strategy on how to approach writing tests.
Now, there’s a lot of material out there on testing the right things, and so I’m not going to dwell on that too long before I move onto the documentation part - but let’s just have a little look at some core concepts.
Keep focused on what’s written - Finish by 9:00
I said earlier that we want to “Prove the functionality we’ve built” - and I chose the word ‘functionality very much on purpose’.
You’ll hear mention of Code Coverage - the percentage of lines of code that are executed by your tests.
Now whilst that can be a valuable metric in some situations - particularly from Salesforce’s perspective, I have a particular problem with developers thinking about tests in those terms, because it’s not the CODE that’s important - it’s the FUNCTIONALITY.
If we focus on just testing the ‘CODE’ we can miss a lot of bugs, behaviours and missing code.
So Instead I like to think what do I need to do to test the whole of the functionality we’ve built, or been asked to build..
Think about your tests up front. Don’t just dive in and code - actually stop, think, write them down in plain english before you start to write the actual code Thinking about your tests in isolation helps you to come up with all the important variations you need to test for. Once you get into the code, you get much more focused on getting the job done - so give yourself a chance and take a step back. You can come back and add more, that’s fine. But just split the thought process out. Thinks about tests / write some tests / think about tests / write some tests.
Don’t just test the happy path - that is, what the code does when it’s all working - test for failure What happens if I pass invalid values into this method, nulls, empty strings, an Id of a record that doesn’t exist.
Don’t just test for when things happen, test for when they don’t, or shouldn’t happen. We want to regularly email some marketing material out to a list of contacts who have asked for if. If a contact has said they don’t ever want that email, we really shouldn’t send the email to them. We should test for that case. Almost all the time, the case where things *shouldn’t* happen is every bit as important as when it should.
Think - “What could go wrong?”. What have I forgotten about? What will *real* data actually look like when real users get hold of the system and it’s full of migrated data. What are those funny edge cases that are valid, but a bit unexpected?
Once we’ve got a good handle on the things to test, we can start to think about the big one...
Writing your tests as documentation.
And this is the bit that really gives you the long term value - gives you that ‘collective memory’.
Finish looking by: 12:15
But before I start talking about that, I’d like to show you some code. Probably a fairly typical unit test in a lot of environments - and one that probably works very well for many people.
Go over the test…
The problem is, that isn’t easy to understand. It takes effort and it doesn’t tell you a HUGE amount. When this test goes wrong, it’s going to be tough on the developer who has to fix it.
So how can we improve that?
Finish by 13:15
So - the first thing I’d say is - Do what you can to Express Meaning in your tests. We want to explain the behaviour of our system in a way that developers can understand, and you need to *intentionally* do that.
Use names to express meaning - particularly variable and constant names In fact, don’t forget to use variables and constants. Instead of using literal values, use a constant to describe what that value represents in the context of the test. Give methods names that describe what the test is - this all helps as documentation to them the tests clearer.
Do things in a logical order Much like any other code - the order you do things in has a massive impact on how readable it is. Make sure you do things like declare variables near where you use them, put helper methods out of the way.
Good documentation takes the reader on a journey, and unit tests should be the same Start off with the simple cases, describe the essence of the code as early as possible, and then introduce the complexities. Introduce the complexities in a meaningful order, tell the important stories first.
Finish by: 14:45 Be Concise Only do what you need to test your scenario - do nothing more - anything that could be removed and have no impact on the efficacy of the test is just a distraction. Get rid of it. Hide things that are immaterial. Put things behind helper methods. For example, if you need to create objects with mandatory fields then do that inside helper methods or data factories, or hide your factories behind helpers. In short, only expose the fields that are important in the test. Only set up the data you need. If you don’t need to the data to set the test up, don’t create it. If you don’t need data to be inserted, don’t insert it. And as I say, limit what you can see about the data creation Test one thing at a time, put each test case into its own method, split them up - it makes them much clearer - Then, as I’ve already said, put them in an order that makes sense to the reader
Finish by: 16:15
Be Precise Be very clear about what you’re testing Splitting your test up into clear Setup of the test (the fixture) The call to the thing you’re testing And then the assertion of the result of that call. Salesforce has ‘startTest’ and ‘stopTest’ that you should use to pinpoint the important part of the test. And then when you’ve run your test, assert for precise values You’re in control of the data, the scenario, the code - you should pretty much always be able to say *exactly* what the result is of a method call. Use assertEquals when you can. != null just isn’t good enough.
Finish by 19:00
So with those points in mind, let’s take a look at the same test, rewritten as if it was documentation.
Finish by: 20:00
OK, so that’s what we’d like to be able to do in order to get some real long term value out of our tests, and make future developers’s lives easier. But how do we get there.
Well, much like any other code - have standards - and have standards that are specific to unit tests. Take some time to think about what you want out of your Unit Tests and write standards that support that.
Then include them in your code reviews and ensure people follow those standards, and that you help people to learn how to write better tests.
And if you’re not sure how to approach Unit Testing in this way, seek out advice and learn from your community peers - and if you’re not sure who you can turn to, you’re in luck...
I have a GIT repo that goes with talk - it has the two examples from this talk, as well as some intermediate steps of evolution that illustrate the points more clearly.
It also includes some heavily annotated versions of them that I really hope will be useful. as well as a couple of other bonus examples, like a data factory.
But also, there’s a reminder that Salesforce has 900+ Community Groups around the world
They’re volunteer run and organised, and in general are thankfully organised by people much cleverer than me.
The great thing is that they’ve full of people who *really* know what they’re talking about and are really happy to talk about anything to do with working with Salesforce, in the industry in general, and just chatting. Great thing is, they all know that they can learn from you too. They’re great collaborative events.
Honestly, whether this is the first time you’ve heard of Salesforce, or you’ve been working with in for 20 years - if you’ve never been to one of these events you should try it out - you *will* learn something and meet some really interesting people.
The great thing is, London is a bit of a hub - so if you’re local then you’re lucky to have 8 Community Groups here.
If you like this talk, and the other talks in the dev theatre, the Salesforce Developers one should be an automatic choice - there’s some seriously clever people who love to share their knowledge and I’d highly recommend it - so go check that out.
And because we just can’t get enough of the community group goodness, we have Community Conferences too! These are 1-2 day events planned and hosted with lots of love by Community Group Leaders It all started years ago when Eric Dreshfield was frustrated he couldn’t go to Dreamforce, so he decided to create his own - now known as MidWest Dreamin’ They’re such awesome learning and networking experiences, lots of community members have even started to plan vacations around them
London’s Calling and DreamOlé have already happened this year. But you can still attend one of the other 4 EMEA region conferences: YeurDreamin (Netherlands), CzechDreamin, French Touch Dreamin, or North Africa Dreamin.
There’s also Inspire East - I think it’s October 4th, in Cambridge.
Thank you for listening. I hope it’s been useful.
Getting the best value out of your unit tests
Getting the best value out of your Unit Tests
Unit Tests as Documentation - Expo Developer Theatre - 12:30pm
Robert Baillie, Senior Technical Consultant - makepositive - @BobaliciousBob
Salesforce World Tour, London, 23rd May
Getting the best value out of your Unit Tests
Unit Tests as Documentation
Robert Baillie, Senior Technical Consultant - makepositive
Senior Technical Consultant
Getting the best value out of your Unit Tests
Unit Tests as Documentation
Give me some context...
• Domain Specific Language used to customise Salesforce.
• Java-like, Object Oriented.
• Abstractions for things like database access.
What’s Unit Testing?
• Required whenever we write Apex.
• It’s Apex that tests other Apex.
• Runs whenever we deploy changes to our Salesforce Orgs.
• We have minimum requirements for the amount we do.
What do we need to do?
Test for the right things
Make sure our tests are / documentation is readable
Testing the right things
Plan our tests up front
Don’t just test the “Happy Path”
Test for when things shouldn’t happen
Think “What can go wrong when the users get hold of it?”
Have standards for your tests
Include Unit Tests in your code reviews
Seek advice and learn
Ok, Ok, but how do get there..?
GitHub Repository with examples:
I have example code...
Trailblazer Community Groups
Community Group Leaders
Meetings per month
Meet peers, learn Salesforce together, build your network, and find mentors
TrailblazerCommunityGroups.com Louise Lockie
Women in Tech Leader
Connect with our Awesome London Groups
8 Groups to Explore
- Salesforce Developers
- Salesforce Admins
- B2B Marketers
- B2C Marketers
- Women in Tech
- Higher Education
Trailblazer Community Conferences
30+ 1-2 day conferences built by and for the community with thought leadership,
peer-peer learning and awesome networking
Big Sky Dreamin'
True North Dreamin'
French Touch Dreamin'
North Africa Dreamin’
DownUnder Dreaming Brisbane
DownUnder Dreaming Melbourne
DownUnder Dreaming Sydney
14 June 2019
16 Aug. 2019
20 Sept. 2019
18 Oct. 2019