Información general sobre pruebas de unidad de Apex
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Describir las ventajas clave de las pruebas de unidad de Apex.
- Definir una clase con métodos de prueba.
- Ejecutar todos los métodos de prueba en una clase e inspeccionar los errores.
- Crear y ejecutar un conjunto de clases de prueba.
Pruebas de unidad de Apex
El marco de trabajo de pruebas de Apex permite escribir y ejecutar pruebas para desencadenadores y clases de Apex. Las pruebas de unidad de Apex le permiten garantizar la alta calidad de su código Apex y cumplir los requisitos para la implementación de Apex.
Las pruebas son la clave para el desarrollo correcto a largo plazo y un componente decisivo del proceso de desarrollo. El marco de pruebas de Apex facilita la prueba del código Apex. El código Apex solo se puede escribir en un sandbox o una organización de desarrollador, pero no en una organización de producción. El código Apex se puede implementar en una organización de producción desde un sandbox. Además, los desarrolladores de aplicaciones pueden distribuir el código Apex a los clientes desde sus organizaciones de desarrollador mediante la carga de paquetes para Salesforce AppExchange. Además de ser esenciales para garantizar la calidad, las pruebas de unidad de Apex son además requisitos para la implementación y distribución de Apex.
Las pruebas de unidad de Apex generan mejores códigos. El marco de trabajo de pruebas de Apex:
- Garantiza que los desencadenadores y las clases de Apex funcionen según lo esperado.
- Dispone de un conjunto de pruebas de regresión que se pueden volver a ejecutar cada vez que se actualicen las clases y los desencadenadores para garantizar que las actualizaciones futuras que realice en la aplicación no afecten a la funcionalidad existente.
- Cumple los requisitos de cobertura de código para la implementación de Apex para producción o la distribución de Apex a los clientes mediante paquetes.
- Ofrece aplicaciones de alta calidad a la organización de producción, lo que aumenta la productividad de los usuarios de producción.
- Ofrece aplicaciones de alta calidad a suscriptores de paquetes, lo que aumenta la confianza de los clientes.
Requisito de cobertura de código para la implementación
A fin de poder implementar su código o paquete para Salesforce AppExchange, como mínimo el 75 % del código Apex debe estar cubierto por pruebas y todas deben aprobar. Además, cada desencadenador debe tener determinada cobertura. Aunque la cobertura de código sea un requisito para la implementación, no escriba pruebas solamente para cumplir este requisito. Asegúrese de probar casos de uso en su aplicación, lo que incluye casos de pruebas positivas y negativas, y el procesamiento masivo y de un solo registro.
Clase de prueba y sintaxis de métodos de prueba
Las clases de prueba de Apex se anotan con @isTest. Las clases de prueba se pueden definir con modificadores de acceso privado o público. Si va a usar una clase de prueba para pruebas de unidad únicamente, declárela como privada. Las clases de prueba públicas se suelen usar para las clases de fábrica de datos de prueba, que vamos a abarcar en la unidad Crear datos de prueba para pruebas de Apex. Las clases que se definen como @isTest deben ser clases de nivel superior.
En la clase de prueba, los métodos de prueba también se definen con la anotación @isTest. La visibilidad de un método de prueba no es importante, de modo que la declaración de un método de prueba como público o privado no supone ninguna diferencia, ya que el marco de trabajo de pruebas siempre puede acceder a los métodos de prueba. Por este motivo, los modificadores de acceso se omiten en la sintaxis del método.
En este ejemplo de código podemos ver una definición de una clase de prueba con un método de prueba.
@isTest
private class MyTestClass {
@isTest static void myTest() {
// code_block
}
}La anotación @isTest puede llevar varios modificadores entre paréntesis, que están separados por un espacio. Hablaremos brevemente sobre la anotación @isTest(seeAllData=true) en la unidad Crear datos de prueba para pruebas de Apex.
Ejemplo de prueba de unidad: Probar la clase TemperatureConverter
El siguiente ejemplo sencillo es una clase de prueba con tres métodos de prueba. El método de clase que se prueba obtiene la temperatura en grados Fahrenheit como una entrada. Convierte este valor de temperatura en grados Celsius y devuelve el resultado convertido. Vamos a agregar la clase personalizada y su clase de prueba.
- En Developer Console, haga clic en File (Archivo) | New (Nuevo) | Apex Class (Clase de Apex) e ingrese
TemperatureConverterpara el nombre de clase y, a continuación, haga clic en OK (Aceptar).
- Sustituya el cuerpo de clase predeterminado por el siguiente.
public class TemperatureConverter { // Takes a Fahrenheit temperature and returns the Celsius equivalent. public static Decimal FahrenheitToCelsius(Decimal fh) { Decimal cs = (fh - 32) * 5/9; return cs.setScale(2); } } - Pulse Ctrl+S para guardar la clase.
- Repita los pasos anteriores para crear la clase
TemperatureConverterTest. Sustituya el cuerpo de clase predeterminado por el siguiente.@isTest private class TemperatureConverterTest { @isTest static void testWarmTemp() { Decimal celsius = TemperatureConverter.FahrenheitToCelsius(70); System.assertEquals(21.11,celsius); } @isTest static void testFreezingPoint() { Decimal celsius = TemperatureConverter.FahrenheitToCelsius(32); System.assertEquals(0,celsius); } @isTest static void testBoilingPoint() { Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212); System.assertEquals(100,celsius,'Boiling point temperature is not expected.'); } @isTest static void testNegativeTemp() { Decimal celsius = TemperatureConverter.FahrenheitToCelsius(-10); System.assertEquals(-23.33,celsius); } }
La clase de prueba TemperatureConverterTest verifica si el método funciona según lo esperado mediante la llamada a dicho método con distintas entradas para la temperatura en grados Fahrenheit. Cada método de prueba verifica un solo tipo de entrada: temperatura alta, punto de congelación, punto de ebullición y valor de temperatura negativo. Las verificaciones se realizan llamando al método System.assertEquals() que solo lleva dos parámetros. El primer parámetro es el valor esperado y el segundo es el valor real. Este método también acepta un tercer parámetro, que es una cadena que describe la comparación. Este tercer parámetro opcional se usa en el ejemplo testBoilingPoint(). La cadena especificada se registra si se produce un error de afirmación.
Vamos a ejecutar los métodos de esta clase.
- En Developer Console, haga clic en Prueba | Nueva ejecución.
- En Clases de prueba, haga clic en TemperatureConverterTest.
- Si desea agregar todos los métodos de prueba de la clase
TemperatureConverterTestpara la ejecución de la prueba, haga clic en Add Selected (Agregar selección).
- Haga clic en Ejecutar.
- En la ficha Tests (Pruebas), puede ver el estado de las pruebas a medida que se ejecutan. Amplíe la ejecución de pruebas y vuelva a ampliarla hasta poder ver la lista de pruebas individuales ejecutadas. Todas incluyen marcas de verificación verdes, lo que indica que se aprobaron todas las pruebas.

Una vez ejecutadas las pruebas, la cobertura de código se genera automáticamente para las clases y los desencadenadores de Apex de la organización. Puede comprobar el porcentaje de cobertura de código en la ficha Tests (Pruebas) de la consola de desarrollador. En este ejemplo, la clase TemperatureConverter tiene una cobertura del 100 %, como se muestra en la imagen.

Aunque un solo método de prueba puede tener como resultado la cobertura completa de la clase TemperatureConverter, es importante probar con distintas entradas para garantizar la calidad del código. Obviamente, no es posible verificar cada punto de datos, pero puede probar puntos de datos comunes y distintos intervalos de entrada. Por ejemplo, puede verificar el paso de números positivos y negativos, valores de límite y valores de parámetros no válidos para confirmar un comportamiento negativo. Las pruebas para la clase TemperatureConverter permiten verificar puntos de datos comunes, como el punto de ebullición y congelación, así como la temperatura positiva y negativa.
Sin embargo, la clase de prueba TemperatureConverterTest actualmente no abarca las condiciones de límite ni las entradas no válidas. Las condiciones de límite son los valores mínimos y máximos que el método puede manejar. Para las entradas no válidas, considere qué sucede si null (nulo) pasa como argumento para FahrenheitToCelsius(). En este caso, cuando el tiempo de ejecución de Apex elimina la referencia a la variable de parámetro para evaluar la fórmula, genera System.NullPointerException. Para solucionar este error, puede modificar el método FahrenheitToCelsius() para verificar entradas no válidas y devolver null (nulo) en ese caso. Luego, agregue un método de prueba a la clase TemperatureConverterTest para verificar el comportamiento de la entrada no válida.
En este punto, todas las pruebas se aprueban dado que la fórmula de conversión usada en el método de clase es correcta. Sin embargo, este es un proceso aburrido. Vamos a simular un error solamente para ver qué sucede cuando una afirmación genera un error. Por ejemplo, vamos a modificar la prueba de punto de ebullición y a pasar un valor esperado falso para el punto de ebullición en grados Celsius (0 en lugar de 100). Esto genera un error del método de prueba correspondiente.
- Cambie el método de prueba
testBoilingPoint()por lo siguiente:@isTest static void testBoilingPoint() { Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212); // Simulate failure System.assertEquals(0,celsius,'Boiling point temperature is not expected.'); } - Para realizar la misma ejecución de prueba, haga clic en la última ejecución en la ficha Tests (Pruebas) y, a continuación, haga clic en Test (Prueba) | Rerun (Volver a ejecutar) en la barra de navegación. La afirmación de
testBoilingPoint()no surte efecto y genera un error grave (AssertExceptionque no se puede capturar).
- Para comprobar los resultados de la ficha Tests (Pruebas), expanda la última prueba ejecutada. La ejecución de pruebas indica una de cuatro pruebas con errores. Para obtener más información sobre el error, haga doble clic en la prueba ejecutada. Los resultados detallados se muestran en una ficha independiente.
- Para ver el mensaje de error de esta prueba incorrecta, haga doble clic en la columna de errores de dicha prueba. El mensaje de error incluye el texto que brindamos en la declaración
System.assertEquals():System.AssertException: Assertion Failed: Boiling point temperature is not expected.: Expected: 0, Actual: 100.00
Los datos de estos métodos de prueba son números y no registros de Salesforce. Encontrará más información sobre cómo probar los registros de Salesforce y configurar los datos en la siguiente unidad.
Aumentar la cobertura de código
Al escribir pruebas, intente alcanzar la máxima cobertura de código posible. Evite alcanzar una cobertura de tan solo el 75 %, ya que esta es la cobertura mínima que requiere Salesforce para las implementaciones y los paquetes. Cuantos más casos de prueba cubren las pruebas, mayor es la probabilidad de que el código sea consistente. En ocasiones, incluso después de escribir métodos de prueba para todos los métodos de clase, la cobertura de código no es del 100%. Una causa común es que no se cubren todos los valores de datos para la ejecución de código condicional. Por ejemplo, algunos valores de datos tienden a ser ignorados si el método de clase tiene declaraciones if que producen distintas ramas para su ejecución en función de si se cumple la condición evaluada. Asegúrese de que los métodos de prueba representan estos valores distintos.
En este ejemplo se incluye el método de clase getTaskPriority(), el cual contiene dos declaraciones if. La tarea principal de este método es devolver un valor de cadena de prioridad basado en el estado de un prospecto determinado. El método valida el estado primero y devuelve null si el estado no es válido. Si el estado es CA, el método devuelve 'High'. En caso contrario, devuelve 'Normal' para cualquier otro valor de estado.
public class TaskUtil {
public static String getTaskPriority(String leadState) {
// Validate input
if(String.isBlank(leadState) || leadState.length() > 2) {
return null;
}
String taskPriority;
if(leadState == 'CA') {
taskPriority = 'High';
} else {
taskPriority = 'Normal';
}
return taskPriority;
}
}Esta es la clase de prueba para el método getTaskPriority(). El método de prueba simplemente llama a getTaskPriority() con un solo estado (NY).
@isTest
private class TaskUtilTest {
@isTest
static void testTaskPriority() {
String pri = TaskUtil.getTaskPriority('NY');
System.assertEquals('Normal', pri);
}
}Vamos a ejecutar esta clase de prueba (TaskUtilTest) en Developer Console y a comprobar la cobertura de código para la clase TaskUtil correspondiente que cubre esta prueba. Una vez ejecutada la prueba, la cobertura de código para TaskUtil se indica como un 75%.
Abra la clase TaskUtil en Developer Console. Si aún no lo ha hecho, cambie la configuración desde Code Coverage (Cobertura de código): De None (Ninguna) a Code Coverage: All Tests (Cobertura de código: todas las pruebas). Con esta configuración, verá seis líneas azules (cubiertas) y dos líneas rojas (no cubiertas), como se muestra en esta imagen.

El motivo por el que la línea 5 no está cubierta es que nuestra clase de prueba no contenía ninguna prueba para pasar un parámetro de estado no válido. De forma similar, la línea 11 no está cubierta porque el método de prueba no ha pasado 'CA' como estado. Vamos a agregar dos métodos de prueba para cubrir estos casos. A continuación se muestra la clase de prueba completa después de agregar los métodos de prueba testTaskHighPriority() y testTaskPriorityInvalid(). Si vuelve a ejecutar esta clase de prueba con Test (Probar) | Run All (Ejecutar todo) o Test (Probar) | New Run (Nueva ejecución), la cobertura de código para TaskUtil será del 100 %.
@isTest
private class TaskUtilTest {
@isTest
static void testTaskPriority() {
String pri = TaskUtil.getTaskPriority('NY');
System.assertEquals('Normal', pri);
}
@isTest
static void testTaskHighPriority() {
String pri = TaskUtil.getTaskPriority('CA');
System.assertEquals('High', pri);
}
@isTest
static void testTaskPriorityInvalid() {
String pri = TaskUtil.getTaskPriority('Montana');
System.assertEquals(null, pri);
}
}Crear y ejecutar un conjunto de pruebas
Un conjunto de pruebas es una recopilación de clases de prueba de Apex que se ejecutan conjuntamente. Por ejemplo, cree un conjunto de pruebas que ejecute cada vez que prepare una implementación o que Salesforce lance una nueva versión. Configure un conjunto de pruebas en la consola de desarrollador para definir un conjunto de clases de prueba que pueda ejecutar conjuntamente de forma regular.
Ahora tiene dos clases de prueba en su organización. Estas dos clases no están relacionadas, pero vamos a suponer de momento que sí lo están. Suponga que hay casos en los que desea ejecutar estas dos clases de prueba, pero no desea ejecutar todas las pruebas de la organización. Cree un conjunto de pruebas que contenga ambas clases y, a continuación, ejecute las pruebas del conjunto.
- En Developer Console, seleccione Prueba | Nuevo conjunto.
- Ingrese
TempConverterTaskUtilSuitecomo nombre del conjunto y, a continuación, haga clic en OK (Aceptar).
- Seleccione TaskUtilTest, mantenga pulsada la tecla Ctrl y seleccione TemperatureConverterTest.
- Para agregar las clases seleccionadas al conjunto, haga clic en >.

- Haga clic en Guardar.
- Seleccione Prueba | Nueva ejecución de conjunto.
- Seleccione TempConverterTaskUtilSuite y, a continuación, haga clic en > para mover
TempConverterTaskUtilSuitea la columna Selected Test Suites (Conjuntos de prueba seleccionados).
- Haga clic en Run Suites (Ejecutar conjuntos).
- En la ficha Tests (Pruebas), puede controlar el estado de las pruebas a medida que se ejecutan. Amplíe la ejecución de pruebas y vuelva a ampliarla hasta poder ver la lista de pruebas individuales ejecutadas. Al igual que en el caso de una ejecución de métodos de prueba individuales, puede hacer doble clic en los nombres de los métodos para ver los resultados detallados de las pruebas.
Crear datos de prueba
Los registros de Salesforce creados en métodos de prueba no se confirman para la base de datos. Estos se revierten una vez que finaliza la ejecución de la prueba. Este comportamiento de reversión es de utilidad para las pruebas porque no necesita limpiar los datos de prueba después de ejecutar la prueba.
De forma predeterminada, las pruebas de Apex no tienen acceso a los datos preexistentes de la organización, a excepción del acceso a objetos de configuración y metadatos, como los objetos de usuario o perfil. Configure los datos de prueba para las pruebas. La creación de datos de prueba aumenta la consistencia de las pruebas y permite evitar errores generados por la ausencia o el cambio de los datos de la organización. Puede crear datos de prueba directamente en el método de prueba o mediante una clase de prueba de utilidad, como verá más adelante.
Más información
- Puede usar la extensión de Apex de Salesforce para Visual Studio Code a fin de ejecutar pruebas de Apex y verificar la funcionalidad de su código.
- Puede ahorrar hasta 6 MB de código Apex en cada organización. Las clases de prueba anotadas con
@isTestno cuentan para este límite.
- Aunque los datos de prueba se revierten, no se usa ninguna base de datos independiente para las pruebas. Por lo tanto, en el caso de determinados sObjects que tienen campos con restricciones de exclusividad, la inserción de registros de sObject duplicados genera un error.
- Los métodos de prueba no permiten el envío de emails.
- Los métodos de prueba no pueden hacer llamadas a servicios externos. Puede usar llamadas ficticias en las pruebas.
- Las búsquedas SOSL realizadas en una prueba devuelven resultados vacíos. A fin de garantizar los resultados esperados, use
Test.setFixedSearchResults()para definir los registros que va a devolver la búsqueda.
Recursos
- Guía del desarrollador de Apex: Mejores prácticas sobre las pruebas
- Guía del desarrollador de Apex: ¿Qué son las pruebas de unidades de Apex?
- Guía del desarrollador de Apex: Aislamiento de los datos de prueba desde los datos de organización en las pruebas de unidad
- Ayuda de Salesforce: Comprobación de la cobertura del código
Preparación para el reto práctico
Para completar el desafío práctico de esta unidad, deberá crear una nueva clase de Appex denominada VerifyDate con el siguiente código:
public class VerifyDate {
//method to handle potential checks against two dates
public static Date CheckDates(Date date1, Date date2) {
//if date2 is within the next 30 days of date1, use date2. Otherwise use the end of the month
if(DateWithin30Days(date1,date2)) {
return date2;
} else {
return SetEndOfMonthDate(date1);
}
}
//method to check if date2 is within the next 30 days of date1
private static Boolean DateWithin30Days(Date date1, Date date2) {
//check for date2 being in the past
if( date2 < date1) { return false; }
//check that date2 is within (>=) 30 days of date1
Date date30Days = date1.addDays(30); //create a date 30 days away from date1
if( date2 >= date30Days ) { return false; }
else { return true; }
}
//method to return the end of the month of a given date
private static Date SetEndOfMonthDate(Date date1) {
Integer totalDays = Date.daysInMonth(date1.year(), date1.month());
Date lastDay = Date.newInstance(date1.year(), date1.month(), totalDays);
return lastDay;
}
}