2

We have ~5k unit test running for 6-8 hrs. I want to bring down the runtime. Main contributor is the DMLs in the testsetup and DMLs in the actual class. I want to replace it with Stubbing wherever possible to reduce the total runtime.

Example:

Case object has ~50 field updates done through trigger. I will write pure unit test for each field updates in trigger using stubbing and avoid DMLs. But these field updates should also be tested as the whole trigger runs. At the same time Apex testing time should be reduced.

Questions:

  • Does these field updates need to be Apex tested using unit tests with DMLs?
  • Are there any guidelines for the scope of how much integration testing should be done through Apex testing in this scenario?
2
  • 3
    This question is a nice one from the perspective of discussion of best practice. However, that sort of thing is better covered on the Salesforce developer forums since SFSE is aimed at less opinionated, more concrete technical Q&A. As such I'm suggesting it be closed.
    – Phil W
    Jan 20, 2021 at 17:21
  • 3
    We are having a similar issue and our philosophy is that when you are testing service layers which operate against records, only the current state of those records should matter, not how they got there. You might need some level of flow testing to cover gaps, but bypassing all triggers or the database wherever possible is the only way to bring down that run time.
    – Adrian Larson
    Jan 20, 2021 at 17:21

1 Answer 1

2

As Phil commented, this type of question is primarily opinion-based, so I think you will get multiple answers.


For me, a unit test should test a single piece of the code, like a specific method, regardless of its usage in the business process. The unit test serves the purpose of asserting that this unit of code works as intended given multiple inputs.

To exemplify, say that a method has a signature that allows the developer to call it with a list of Ids of a certain object type. The test would likely test the method for what happens when the method is called with a null parameter, an empty list, a single item on the list and multiple elements on the list. This could be a method to handle something that happens with a specific record, like an account or case, for example.

Now, this method does nothing on its own, it has to be applied somewhere (like a trigger). Then you have the integration test, to assert that the method is called by your trigger when your code does some DML operation on said object. This is when you test the integration between your business logic, trigger and method.

To be honest, I'm not a fan of testing an entire process in a piece of test. Think about a sales process starting from product registration, to opportunity, order and contract. I don't think it makes much sense to test the whole process at once, because the test can get really big and difficult to maintain (especially if there can be multiple scenarios for your app, imagine writing hundreds of lines just to set the scenario up, and then having to modify a couple of parameters just to test a slightly different scenario).


Applying this to your scenario, I would say to try to write the code in a way that you can specify which field and value are being changed, and then assert that the attribution of value happens as intended in a unit test. If it works for one field, it should work for all the others. You can write just a couple of tests to assert that the types work as intended (for string/number/date/datetime fields). This way, you don't need to test all 50 or more scenarios, because they will all call the same method that was previously tested.

Not the answer you're looking for? Browse other questions tagged .