[SalesForce] How to test apex code that is driven by formula fields (Best Practice)

Question

Are there any best practices out there for testing apex code that is driven by formula fields so that changes to the formula field formula don't break your test?

Background

Good test methods shouldn't break when administrators make changes. While impossible, it's nice to get as close as possible to this ideal.

Formula fields make this tricky. In order to get a predictable (deterministic) result from your test you often need to ensure the formula field has a particular value.

One option is to have your test to "know" the formula field syntax, and setup the data to ensure you get a desired value in the formula field. Downside is now whenever that formula field changes, you're test breaks.

Another option is a Test.isRunningTest() switch in your code that alters the logic code to bend around the formula. Downside is it's easy to write a test that gives you an all clear, but is broken for end user.

Neither of these is great, has anyone out there run into this and found something that works for them?

Practical Example

This obviously won't matter in a lot of cases, since formula fields don't really change much, but to give it some context, imagine the following scenario loosely based on a project I'm working on.

You've got a trigger that creates a project assignment record based on changes to a parent project record that lists who is on a project, for how long, and what their roles are. The project assignment has an end date field you need to populate. The logic to determine the end date is complicated, i.e. (if project end date is null, then project start date + 20, unless progress is greater than 50%, in which case it's project start date + 10), and the requestor expects there going to need to tweak it several times to get the end date right. So you create formula field, "Project Assignment End Date" to encapsulate the logic, and your trigger just looks at the formula field, doesn't have to worry about what the logic is, and the requestor can make changes without calling the developer in. It's working great, but now you need to write your test methods. How do you go about it so you have a test method that truly tests your code, but doesn't break the first time an admin makes a change?

An even better example would be using a formula field as configuration to drive code, in which case it becomes a must tests can't break on changes, and important that you can test that some version of the formula works.

Best Answer

First, thank you, Ralph, for asking this question and putting yourself out there. As a matter of communication I don't mean to call you out on anything at all, but I want to give a detailed, (hopefully) thoughtful answer to a detailed, thoughtful question.

Are there any best practices out there for testing apex code that is driven by formula fields so that changes to the formula field formula don't break your test?

As someone who'd asked the same question myself, I think I understand why you posted to Stack Exchange. However, I believe a better question is, "How can I make sure critical formula fields are tested properly to protect against unintended consequences?"

I believe you should want changes to formula fields to break Apex tests, especially when your app logic depends on those formula fields. Imagine having an Apex class to create the output that the formula field currently produces. In that case you're forced to write an Apex test for that other class, and in the app logic that you are writing you would rely on proper test coverage of the other class.

A formula field is simply another means of automating business logic. And just like other means, such as Apex, Visual Workflow, JavaScript, workflow rules or Process Builder, a formula field used as a critical automation component should have adequate test coverage.

So, regarding this idea:

Good test methods shouldn't break when administrators make changes.

I believe that good test methods should break when administrators (or developers) make changes that impact the app logic that you've implemented. I think this is the only way to sustainably work in a team environment with multiple admins and devs.

Recommendations

All that to say I support both recommendations from NSjonas and Bobby White.

... treat the Formula Field as though it were a stand alone class and ensure that you have adequate code coverage for all of the branches that are implicit in it.

-- Bobby White

I would recommend de-coupling the class with the actual instance of the object if possible. That way you can test the branch conditions individually by passing whatever value you want into the code.

-- NSjonas