10

Background: My org has reached almost 750 unique un-managed classes and triggers. Until now, we had been adhering to the 1:1 test class to class school of thought. Now, we are at the point where we end up writing almost identical test classes just to cover 2, or 3, or 4 separate apex classes. We have a large number of validation rules that have to be met, therefore we often need to write ~40 lines to insert a single object.

Recently, we ran into a a situation where a new validation rule broke many different test classes; if we had a single test class, we would only have to update one file rather than many.

My Question: What are the pros and cons of creating a handful of test classes that cover numerous classes and triggers? Is there any improvement/degradation in speed during deployment?

  • Hello, Nick, are you finding that the tests break during the part where test data is being staged before Test.startTest()? Or are tests actually breaking somewhere between Test.startTest() and Test.stopTest() or during final validation/assertion of outcomes? – Marty C. Apr 28 '15 at 0:58
9

Using one single class usually isn't practical (there is a 1MB limit per class, which you can easily exceed when you're pushing 2MB of live code), using one test class per live class or trigger may also be counterproductive. A unit test should reflect actual usage, so sometimes a better way to form tests would be feature-based testing.

For example, let's say you build a complex process involving leads and how they're eventually converted to accounts. You might combine all of those tests into a single class, so they're localized. It's also terribly convenient if each class happens to encapsulate a single feature, because then you do have unit tests that align with classes, while also aligning with features.

However, using one class per feature can result in a mess of functions in a single class (i.e. a God object), so try to be as granular as you can. It's acceptable to have several classes for a single feature, especially if Visualforce controllers, etc are in play. Just try to keep related functionality close to each other.

It's probably more important to be consistent. If you have one test class per main class and trigger, name them in a similar convention, so nothing gets lost or misses coverage. There's nothing quite as frustrating as trying to figure out why a certain class is not covered in parts, and you have to find all the various classes that are involved.

Now, to address your specific problem: having a validation rule break dozens or even hundreds of tests at once. It's useful to have one or more utility classes that specifically support testing. This reduces the probability that a single breaking change will cause endless frustration. For example, let's say that you create accounts for virtually every single test. You can combine this logic into a single utility class:

@isTest public class AccountTestData {
    public static Account createTestAccount() {
        return new Account(Name='Test123', Industry='Tech');
    }
}

Because these methods aren't marked as @isTest or testMethod, they won't run when you run all tests, but they will consolidate your data creation to a single class. Going back to this example, let's say you add a validation rule that phone numbers are now required. Instead of having to replace hundreds of instances of a new account creation, you now only have to go to a single source:

        return new Account(Name='Test123', Industry='Tech', Phone='(555) 555-5555');

Depending on the size of the objects you need to construct, you might want to create a single utility class, such as "UnitTestData", or you might break them into smaller units of work, such as "AccountTestData" and "ContactTestData."

In this way, introducing a breaking change to a well-used object can be managed in the most simple manner possible.

| improve this answer | |
  • This is excellent. I think that creating utility methods for commonly used objects is a wonderful idea. This solves the issue, while keeping the code neatly organized. – Nick Apr 28 '15 at 12:25
  • Yes exactly with the test utilities. You can even accomplish it generically and maintain all required fields in one place! – Adrian Larson Apr 28 '15 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.