@testSetup en Spring ’15

Seguramente ya le habéis echado un vistazo a las notas de la última Release de Salesforce, Spring ’15.

En esta reléase aparece una nueva notación @testSetup.

Esta nueva notación va asociada a métodos en los cuales serán creado los datos que mas adelante los diferentes métodos test existentes en la clase pueden utilizar durante su ejecución.

Lo que conseguimos entonces es un código mucho más limpio sin repetición de creación de datos por cada método test ejecutado, y si ya esa creación se había implementado usando un método especifico para dicha de creación de datos siendo llamado desde el método test a ejecutar, ahora esta llamada ya no será necesaria.

Podemos tener mas de un método con @testSetup en una clase, pero lo que no podemos asegurar es el orden en el que se ejecutarán. Luego debemos hacer la creación de datos independiente.

La siguiente pregunta que nos puede cruzar por la mente es volúmenes. ¿Quiere decir esto que se han incrementado?, ¿que la creación de datos no ocurre en el mismo contexto de ejecución de nuestro método test?

Esta vez tengo que decir que tristemente, la creación de datos ocurre en el mismo contexto con lo cual no hay incremento de limites.

Si queremos que estos aumenten debemos como ya hacíamos anteriormente usar Test.startTest() para ello.

Luego la mayor ventaja de esta notación es ayudarnos a tener un código más limpio, no repeticiones de código y hacer una carga de datos compatible para todos los métodos test de la clase.

A continuación os dejo una clase test y su correspondiente log para que veáis el orden de ejecución y limites.

Hasta Pronto!


@isTest

private class MyTest

{

   @testSetup

   static void createData()

   {

      System.debug('Enter in createData Method1: testSetup::'+Limits.getDMLStatements()+'::'+Limits.getLimitDMLStatements());

      Account newAccount = new Account(Name='Account1');

      insert newAccount;

      System.debug('Enter in createData Method2: testSetup::'+Limits.getDMLStatements()+'::'+Limits.getLimitDMLStatements());

   }

   static testMethod void testData1()

   {

      Test.startTest();

      System.debug('Enter in testData1::'+Limits.getDMLStatements()+'::'+Limits.getLimitDMLStatements());

      Account newAccount = [Select Name From Account];

      System.assertEquals('Account1', newAccount.Name);

      System.debug('Enter in testData12::'+Limits.getDMLStatements()+'::'+Limits.getLimitDMLStatements());

      Test.stopTest();

   }

   static testMethod void testData2()

   {

       System.debug('Enter in testData2::'+Limits.getDMLStatements()+'::'+Limits.getLimitDMLStatements());

       Account newAccount = [Select Name From Account];

       System.assertEquals('Account1', newAccount.Name);

       System.debug('Enter in testData22::'+Limits.getDMLStatements()+'::'+Limits.getLimitDMLStatements());

   }

}

El Orden de Ejecución ha sido entonces:

1. createData

2. testData1

3. testData2

Debug Log:


33.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
17:14:58.094 (94312697)|EXECUTION_STARTED
17:14:58.094 (94394637)|CODE_UNIT_STARTED|[EXTERNAL]|01pB0000000HolG|myTest.createData
17:14:58.094 (94810652)|METHOD_ENTRY|[2]|01pB0000000HolG|myTest.myTest()
17:14:58.094 (94821557)|METHOD_EXIT|[2]|myTest
17:14:58.094 (94952980)|SYSTEM_METHOD_ENTRY|[7]|Limit.getDmlStatements()
17:14:58.095 (95001929)|SYSTEM_METHOD_EXIT|[7]|Limit.getDmlStatements()
17:14:58.095 (95048420)|SYSTEM_METHOD_ENTRY|[7]|String.valueOf(Object)
17:14:58.095 (95070797)|SYSTEM_METHOD_EXIT|[7]|String.valueOf(Object)
17:14:58.095 (95085582)|SYSTEM_METHOD_ENTRY|[7]|Limit.getLimitDmlStatements()
17:14:58.095 (95097514)|SYSTEM_METHOD_EXIT|[7]|Limit.getLimitDmlStatements()
17:14:58.095 (95114023)|SYSTEM_METHOD_ENTRY|[7]|String.valueOf(Object)
17:14:58.095 (95129705)|SYSTEM_METHOD_EXIT|[7]|String.valueOf(Object)
17:14:58.095 (95151621)|SYSTEM_METHOD_ENTRY|[7]|System.debug(ANY)
17:14:58.095 (95160524)|USER_DEBUG|[7]|<b>DEBUG|Enter in createData Method1: testSetup::0::150</b>
17:14:58.095 (95167447)|SYSTEM_METHOD_EXIT|[7]|System.debug(ANY)
17:14:58.096 (96543628)|DML_BEGIN|[9]|Op:Insert|Type:Account|Rows:1
17:14:58.183 (183682155)|DML_END|[9]
17:14:58.183 (183738203)|SYSTEM_METHOD_ENTRY|[10]|Limit.getDmlStatements()
17:14:58.183 (183780544)|SYSTEM_METHOD_EXIT|[10]|Limit.getDmlStatements()
17:14:58.183 (183815295)|SYSTEM_METHOD_ENTRY|[10]|String.valueOf(Object)
17:14:58.183 (183835500)|SYSTEM_METHOD_EXIT|[10]|String.valueOf(Object)
17:14:58.183 (183847113)|SYSTEM_METHOD_ENTRY|[10]|Limit.getLimitDmlStatements()
17:14:58.183 (183866985)|SYSTEM_METHOD_EXIT|[10]|Limit.getLimitDmlStatements()
17:14:58.183 (183884620)|SYSTEM_METHOD_ENTRY|[10]|String.valueOf(Object)
17:14:58.183 (183900710)|SYSTEM_METHOD_EXIT|[10]|String.valueOf(Object)
17:14:58.183 (183919237)|SYSTEM_METHOD_ENTRY|[10]|System.debug(ANY)
17:14:58.183 (183926903)|USER_DEBUG|[10]|DEBUG|<b>Enter in createData Method2: testSetup::1::150</b><b>
</b>17:14:58.183 (183932859)|SYSTEM_METHOD_EXIT|[10]|System.debug(ANY)
17:14:58.173 (183961154)|CUMULATIVE_LIMIT_USAGE
17:14:58.173|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 1 out of 150
Number of DML rows: 1 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10

17:14:58.173|CUMULATIVE_LIMIT_USAGE_END

17:14:58.183 (183993101)|CODE_UNIT_FINISHED|myTest.createData
17:14:58.185 (185131883)|EXECUTION_FINISHED
17:14:58.194 (194178721)|EXECUTION_STARTED
17:14:58.194 (194189708)|CODE_UNIT_STARTED|[EXTERNAL]|01pB0000000HolG|myTest.testData1
17:14:58.194 (194429563)|METHOD_ENTRY|[2]|01pB0000000HolG|myTest.myTest()
17:14:58.194 (194439177)|METHOD_EXIT|[2]|myTest
17:14:58.194 (194581006)|SYSTEM_METHOD_ENTRY|[14]|system.Test.startTest()
17:14:58.196 (196410911)|SYSTEM_METHOD_EXIT|[14]|system.Test.startTest()
17:14:58.196 (196436313)|SYSTEM_METHOD_ENTRY|[15]|Limit.getDmlStatements()
17:14:58.196 (196533282)|SYSTEM_METHOD_EXIT|[15]|Limit.getDmlStatements()
17:14:58.196 (196565724)|SYSTEM_METHOD_ENTRY|[15]|String.valueOf(Object)
17:14:58.196 (196584800)|SYSTEM_METHOD_EXIT|[15]|String.valueOf(Object)
17:14:58.196 (196599347)|SYSTEM_METHOD_ENTRY|[15]|Limit.getLimitDmlStatements()
17:14:58.196 (196611356)|SYSTEM_METHOD_EXIT|[15]|Limit.getLimitDmlStatements()
17:14:58.196 (196627750)|SYSTEM_METHOD_ENTRY|[15]|String.valueOf(Object)
17:14:58.196 (196643767)|SYSTEM_METHOD_EXIT|[15]|String.valueOf(Object)
17:14:58.196 (196662091)|SYSTEM_METHOD_ENTRY|[15]|System.debug(ANY)
17:14:58.196 (196668968)|USER_DEBUG|[15]|DEBUG|<b>Enter in testData1::0::150</b><b>
</b>17:14:58.196 (196674433)|SYSTEM_METHOD_EXIT|[15]|System.debug(ANY)
17:14:58.196 (196828389)|SOQL_EXECUTE_BEGIN|[16]|Aggregations:0|SELECT Name FROM Account
17:14:58.207 (207955957)|SOQL_EXECUTE_END|[16]|Rows:1
17:14:58.208 (208227438)|SYSTEM_METHOD_ENTRY|[17]|System.assertEquals(ANY, ANY)
17:14:58.208 (208283470)|SYSTEM_METHOD_EXIT|[17]|System.assertEquals(ANY, ANY)
17:14:58.208 (208299244)|SYSTEM_METHOD_ENTRY|[18]|Limit.getDmlStatements()
17:14:58.208 (208328115)|SYSTEM_METHOD_EXIT|[18]|Limit.getDmlStatements()
17:14:58.208 (208360341)|SYSTEM_METHOD_ENTRY|[18]|String.valueOf(Object)
17:14:58.208 (208379606)|SYSTEM_METHOD_EXIT|[18]|String.valueOf(Object)
17:14:58.208 (208390294)|SYSTEM_METHOD_ENTRY|[18]|Limit.getLimitDmlStatements()
17:14:58.208 (208401225)|SYSTEM_METHOD_EXIT|[18]|Limit.getLimitDmlStatements()
17:14:58.208 (208417086)|SYSTEM_METHOD_ENTRY|[18]|String.valueOf(Object)
17:14:58.208 (208433053)|SYSTEM_METHOD_EXIT|[18]|String.valueOf(Object)
17:14:58.208 (208448370)|SYSTEM_METHOD_ENTRY|[18]|System.debug(ANY)
17:14:58.208 (208455254)|USER_DEBUG|[18]|DEBUG|<b>Enter in testData12::0::150</b>
17:14:58.208 (208460659)|SYSTEM_METHOD_EXIT|[18]|System.debug(ANY)
17:14:58.208 (208476092)|SYSTEM_METHOD_ENTRY|[19]|system.Test.stopTest()
17:14:58.210 (210157421)|SYSTEM_METHOD_EXIT|[19]|system.Test.stopTest()
17:14:58.200 (210186511)|CUMULATIVE_LIMIT_USAGE
17:14:58.200|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 1 out of 150
Number of DML rows: 1 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10

17:14:58.200|TESTING_LIMITS
17:14:58.200|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 1 out of 100
Number of query rows: 1 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10

17:14:58.200|CUMULATIVE_LIMIT_USAGE_END

17:14:58.210 (210235275)|CODE_UNIT_FINISHED|myTest.testData1
17:14:58.211 (211251838)|EXECUTION_FINISHED
17:14:58.260 (260437301)|EXECUTION_STARTED
17:14:58.260 (260456749)|CODE_UNIT_STARTED|[EXTERNAL]|01pB0000000HolG|myTest.testData2
17:14:58.260 (260792341)|METHOD_ENTRY|[2]|01pB0000000HolG|myTest.myTest()
17:14:58.260 (260803454)|METHOD_EXIT|[2]|myTest
17:14:58.260 (260915130)|SYSTEM_METHOD_ENTRY|[24]|Limit.getDmlStatements()
17:14:58.260 (260967160)|SYSTEM_METHOD_EXIT|[24]|Limit.getDmlStatements()
17:14:58.261 (261006042)|SYSTEM_METHOD_ENTRY|[24]|String.valueOf(Object)
17:14:58.261 (261028543)|SYSTEM_METHOD_EXIT|[24]|String.valueOf(Object)
17:14:58.261 (261043955)|SYSTEM_METHOD_ENTRY|[24]|Limit.getLimitDmlStatements()
17:14:58.261 (261058175)|SYSTEM_METHOD_EXIT|[24]|Limit.getLimitDmlStatements()
17:14:58.261 (261074889)|SYSTEM_METHOD_ENTRY|[24]|String.valueOf(Object)
17:14:58.261 (261091042)|SYSTEM_METHOD_EXIT|[24]|String.valueOf(Object)
17:14:58.261 (261113424)|SYSTEM_METHOD_ENTRY|[24]|System.debug(ANY)
17:14:58.261 (261122513)|USER_DEBUG|[24]|DEBUG|<b>Enter in testData2::1::150</b><b>
</b>17:14:58.261 (261128396)|SYSTEM_METHOD_EXIT|[24]|System.debug(ANY)
17:14:58.261 (261325197)|SOQL_EXECUTE_BEGIN|[25]|Aggregations:0|SELECT Name FROM Account
17:14:58.264 (264020860)|SOQL_EXECUTE_END|[25]|Rows:1
17:14:58.264 (264157839)|SYSTEM_METHOD_ENTRY|[26]|System.assertEquals(ANY, ANY)
17:14:58.264 (264206417)|SYSTEM_METHOD_EXIT|[26]|System.assertEquals(ANY, ANY)
17:14:58.264 (264221077)|SYSTEM_METHOD_ENTRY|[27]|Limit.getDmlStatements()
17:14:58.264 (264249128)|SYSTEM_METHOD_EXIT|[27]|Limit.getDmlStatements()
17:14:58.264 (264276258)|SYSTEM_METHOD_ENTRY|[27]|String.valueOf(Object)
17:14:58.264 (264294737)|SYSTEM_METHOD_EXIT|[27]|String.valueOf(Object)
17:14:58.264 (264306009)|SYSTEM_METHOD_ENTRY|[27]|Limit.getLimitDmlStatements()
17:14:58.264 (264316703)|SYSTEM_METHOD_EXIT|[27]|Limit.getLimitDmlStatements()
17:14:58.264 (264332518)|SYSTEM_METHOD_ENTRY|[27]|String.valueOf(Object)
17:14:58.264 (264348607)|SYSTEM_METHOD_EXIT|[27]|String.valueOf(Object)
17:14:58.264 (264363269)|SYSTEM_METHOD_ENTRY|[27]|System.debug(ANY)
17:14:58.264 (264369412)|USER_DEBUG|[27]|DEBUG|<b>Enter in testData22::1::150</b>
17:14:58.264 (264374741)|SYSTEM_METHOD_EXIT|[27]|System.debug(ANY)
17:14:58.254 (264399759)|CUMULATIVE_LIMIT_USAGE
17:14:58.254|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 1 out of 100
Number of query rows: 1 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 1 out of 150
Number of DML rows: 1 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10

17:14:58.254|CUMULATIVE_LIMIT_USAGE_END

17:14:58.264 (264433109)|CODE_UNIT_FINISHED|myTest.testData2
17:14:58.265 (265477515)|EXECUTION_FINISHED

 

 

 

6 thoughts on “@testSetup en Spring ’15

  1. Quiere decir, que está parte del código donde declaramos el @testSetup es manejado como un bloque estático en la clase, lo cuál hará que todas las variables tengan una sola instancia, es correcto esto ?

    • Hola Jefferson,
      Gracias por tu seguimiento y por tu pregunta.
      Podríamos decir que se trata como un bloque estático ( de hecho tiene esa notación) Sin embargo no podemos acceder a las variables el método directamente, como por ejemplo en este caso newAccount que debemos hacer una consulta a base de datos para poder recuperarla.

      Ahora, aquí está la gracia de este método, si se modificase el registro de tipo Account (newAccount) , por ejemplo cambiar el nombre esto solamente tendría efecto en el contexto del método test que se esta ejecutando en ese momento. Todos los otros métodos test no se verían afectados por el cambio realizado al registro en un determinado método.

      Un pequeño ejemplo:

      @testSetup
      static void createData()
      {
      Account newAccount = new Account(Name='Account1');
      insert newAccount;
      }

      static testMethod void testData1()
      {

      System.debug(‘Entra en testData1’);
      Account newAccount = [Select Name From Account];

      newAccount.Name = ‘patata’;
      update newAccount;
      System.assertEquals('patata', newAccount.Name);
      }

      static testMethod void testData2()
      {
      System.debug(‘Entra en testData2’);
      Account newAccount = [Select Name From Account];
      // tras ejecutarse el metodo anterior todo se restaura a los valores originales con los que se hizo la carga de datos
      System.assertEquals('Account1', newAccount.Name);
      }

      Espero haber aclarado la duda, muchas gracias de nuevo!

  2. Muy buen post Cristina, además me parece un añadido bastante útil para, como comentas, simplificar y clarificar código y poder reutilizar registros.
    Pero tengo una duda que no se si se ha aclarado ya en otra entrada, ¿si tu creas la clase con seeAllData=true, puedes seguir usando esta nueva anotación?

    Un saludo!

    • Hola Javi,
      Gracias por el seguimiento y la pregunta. Y como hemos hablado no te preocupes por lo de Cristina ya me ha pasado en otras ocasiones 😛 .. pero que no vuelva a ocurrir!! Jejeje.
      Muy buena pregunta, hay varias consideraciones a tener en cuenta:
      1.- Cuando se usa sellAllData=true no se pueden tener métodos @testSetup. Solamente están permitidos cuando los test están aislados de los datos reales de la org.
      2.- Cuando un método @testSetup falla, por una excepción DML por ejemplo, la clase entera falla, no se ejecutan los siguientes métodos test.
      3.- Cuando un método @testSetup llama a otro método que no es de tipo test, no se calcula la cobertura de método que no es test.

      Espero haber aclarado la duda 🙂
      Hasta pronto!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s