Before Salesforce introduced @testSetup annotation in 2015, I used to create common data in a method and call it in every test method.
Ex:
@isTest
private class clsAccountTest {
private static Account testAccount;
private static void createCommonData(){
testAccount = new Account(Name= 'Avinash', BillingPostalCode = '97214');
insert testAccount;
}
@isTest static void itShouldAskForZipCode(){
createCommonData();
//testAccount is accessible.
testAccount.BillingPostalCode = '12345';
update testAccount;
}
}
Now, with @testSetUp, it would look like:
@isTest
private class clsAccountTest {
private static Account testAccount;
@testSetup static void commonData() {
testAccount = new Account(Name= 'Avinash', BillingPostalCode = '97214');
insert testAccount;
System.Debug('****SOQL Queries issued****'+limits.getQueries()); //returns 5
System.Debug('****DML Statements issued****'+limits.getDMLStatements()); // returns 4. Issued 1 in testSetUp and it caused 3 more in Account trigger.
}
@isTest static void itShouldAskForZipCode(){
System.Debug('****SOQL Queries issued****'+limits.getQueries()); //return 5
System.Debug('****DML Statements issued****'+limits.getDMLStatements()); //return 4
createCommonData();
//testAccount is not avaialble, so you have to query for it.
testAccount = [SELECT Id, Name FROM Account WHERE Name = 'Avinash' LIMIT 1];
testAccount.BillingPostalCode = '12345';
update testAccount;
}
}
What do we gain by using this other than less execution time? The Number of SOQL statements, DML statements etc., generated in the testSetUp method are assigned to each and every test method. In fact, it forces us to use more queries as the static variables are not accessible in test methods.
In this answer, the user said that DML statements issued within the testSetUp method are not counted against governor limits, but the DML statements caused by it in the triggers will be counted. I tested this by inserting a record of an object that doesn't have any trigger code and that statement is not correct. Even the DML statements issued within the testSetUp method are counted against governor limits of each and every test method.
I'm wondering if there are any advantages other than less execution time.
Best Answer
To be honest, the increase in speed is about the only tangible benefit to us (as developers).
Salesforce themselves arguably sees more benefit from people using this annotation than we developers (directly) do. If it's faster for us, that means that it also places less load on Salesforce's pods.
As others (including yourself) have noted, it doesn't save on DML or SOQL compared to having a non-annotated static setup method. As another negative (noted by @KeithC), using an
@testSetup
annotated method means that you don't even have access to the IDs of the records that you're creating. This ends up causing us to use more SOQL queries for each test.The other benefits that @SebastianKessel pointed out are good points (separating test setup from the test proper, re-usability), but we'd get the same benefit from just having a separate static setup method (without the annotation).
I continue to use @testSetup because, while the benefits to me may not be very noticeable at times, it doesn't really negatively impact me to use it.
I'll end with the pattern that I use to work around the fact that we can't get at the ids of records that are created in an @testSetup method without querying.
+edit: To be clear, this pattern does still perform extra query/queries that wouldn't be needed if we weren't using
@testSetup
. There isn't any way around that. The point is to provide useful information (record Ids) to individual tests in a central method using as few queries as possible.