Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I have some test classes on my system that rely on a heavy precondition setup method. However, most of the data generated in that precondition is readonly for all tests and can be used on all tests.

I want to have this data generated just once and then used by all tests, just like jUnit's @BeforeClass annotation works. This way, I can run this heavy process only once on this class, instead of one per method (there can be easily 10 test methods in this class).

However, I discovered and asserted myself that if I use static variables, or a static { ... } initializer, the variables are cleared and the initializer gets run for every test method.

Does anyone know if there's a way to implement something like this?

share|improve this question
    
Can you confirm that you are talking about in-memory data here not data inserted into the database? –  Keith C May 2 at 21:35
    
Ok, sorry, I checked again and data created on static call does get rolled back from DB (unlike I originally thought). I'll edit my question to remove it. –  Pablo Venturino May 2 at 21:52

1 Answer 1

up vote 6 down vote accepted

If you are talking about setting up data in the database, then there is nothing to allow you to share the data between test methods: any database activity is rolled back per test method.

(There is the ability to expose tests to existing data via the @isTest(SeeAllData=true) but it is hardly ever a good idea to make use of that.)

So the normal approach is to accept the performance cost of building all the data per test method. (Or compromise and test a sequence of operations in one test method.) Tests often take a few seconds each to run if database operations are involved and large sets of tests can take many minutes to run - just a fact of life on the platform.

To avoid code duplication, write an inner class inside your test class, and invoke that at the start of each test method. That inner class can use whatever patterns you like to setup the data (e.g. builder), and can provide other methods or class references to help with other parts of the tests such as assertions. So your test class might end up looking like this:

@isTest
private class MyTest {
    private class Builder {
        Builder all() {
            insert ...
            insert ...
            insert ...
            return this;
        }
    }
    @isTest
    static void test1() {
        new Builder().all();
        ...
    }
    @isTest
    static void test2() {
        new Builder().all();
        ...
    }
}

PS Also see eyescream's comment below about re-use in tests through using the public rather than private modifier in tests.

share|improve this answer
3  
Test classes don't have to be private, this Eclipse's default is rubbish. That inner class (or simply a helper method) can me marked public. If you mark the test class public too you can call SomeTestClass1.prepareTestData(); from another test class! So you're getting code reusability. And since it's usable only in test classes - doesn't count against your code usage –  eyescream May 2 at 22:42
    
+1 for SomeTestClass1.prepareTestData(); –  EricSSH May 2 at 22:50
    
@eyescream Fair comment and you are right that we often just follow the defaults without thinking too much. In many cases sharing test setup code is a good thing. But in other cases shared test setup code can become pretty ugly as various (diverse) needs are factored in. So keeping the test setup private and tied only to the test methods in one class can be also be a good way to go. (Cohesion matters in tests too.) Remembering we have a choice I'd say is the key point. PS I find test setup methods become ugly quickly for non-trivial setup - setup classes evolve more cleanly. –  Keith C May 2 at 22:59
    
There's no silver bullet for this one I guess. Personally I hate hunting all my "prepareTestDatas()" when a new required field or validation rule has to be added... Balance between copy-pastiness, trusting fellow devs to not abuse your nice data factory and the time to architect a nice method that for example inserts a whole nice set (Account, Oppty, Opp Line Items, Quote...) –  eyescream May 2 at 23:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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