Empiece a realizar un seguimiento de su progreso
Inicio de Trailhead
Inicio de Trailhead
Estimación de tiempo

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 pruebas de Apex permite escribir código y ejecutar pruebas para clases y desencadenadores de Apex en la Plataforma Lightning. 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 solamente se puede escribir en un entorno de sandbox o una organización de desarrollador, pero no 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 AppExchange de​Lightning Platform. 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. A continuación se indican las ventajas de las pruebas de unidad de Apex:

  • Garantizar que las clases y los desencadenadores de Apex funcionen según lo esperado.
  • Disponer de un conjunto de pruebas de regresión que se puedan 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.
  • Cumplir 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.
  • Entrega de aplicaciones de alta calidad a la organización de producción, lo que aumenta la productividad de los usuarios de producción.
  • Entrega de aplicaciones de alta calidad a suscriptores de paquetes, lo que aumenta la confianza de los clientes.
Nota

Nota

Antes de cada actualización de servicio principal, Salesforce ejecuta todas las pruebas de Apex en su nombre a través de un proceso denominado Martillo de Apex. El proceso Martillo se ejecuta en la versión actual y la versión siguiente y compara los resultados de prueba, Este proceso garantiza que el comportamiento en su código personalizado no se altere como resultado de actualizaciones de servicios. El proceso Martillo elige organizaciones de forma selectiva y no se ejecuta en todas las organizaciones. Los problemas encontrados se clasifican basándose en algunos criterios. Salesforce se esfuerza en solucionar todos los problemas antes de cada versión nueva.

Mantener la seguridad de sus datos es nuestra máxima prioridad. No visualizamos o modificamos ningún dato en su organización y todas las pruebas se realizan en una copia que se ejecuta en un centro de datos seguro.

Requisito de cobertura de código para la implementación

Para poder implementar su código o paquete para AppExchange de Lightning Platform, como mínimo el 75% del código Apex debe estar cubierto por pruebas, todas las cuales se 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.

Sintaxis de métodos de prueba

Los métodos de prueba no aplican argumentos y tienen la siguiente sintaxis:

@isTest static void testName() {
    // code_block
}

Además, un método de prueba puede tener esta sintaxis:

static testMethod void testName() {
    // code_block
}

El uso de la anotación isTest en lugar de la palabra clave testMethod es más flexible, ya que puede especificar parámetros en la anotación. Describiremos uno de estos parámetros más adelante.

Dado que la visibilidad de un método no es importante, la declaración de un método de prueba como público o privado no supone ninguna diferencia, ya que el marco de pruebas siempre puede acceder a los métodos de prueba. Por este motivo, los modificadores de acceso se omiten en la sintaxis.

Los métodos de prueba se deben definir en clases de prueba, las cuales son clases anotadas con isTest. En esta clase de ejemplo se muestra una definición de una clase de prueba con un solo método de prueba.

@isTest
private class MyTestClass {
    @isTest static void myTest() {
        // code_block
    }
}

Las clases de prueba pueden ser privadas o públicas. 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 clases de fábrica de datos de prueba, lo cual se describe más adelante.

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.

  1. En Developer Console, haga clic en File | New | Apex Class (Archivo | Nuevo | Clase de Apex), ingrese TemperatureConverter para el nombre de clase y, a continuación, haga clic en OK (Aceptar).
  2. 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);
        }
    }
  3. Pulse Ctrl+S para guardar la clase.
  4. Repita los pasos anteriores para crear la clase TemperatureConverterTest. Agregue lo siguiente para esta clase.
    @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 mediante la llamada al método System.assertEquals() y se aplican dos parámetros: el primero es el valor esperado y el segundo es el valor real. Hay otra versión de este método en la que se aplica un tercer parámetro, que es una cadena que describe la comparación realizada, la cual se usa en testBoilingPoint(). Esta cadena opcional se registra si se produce un error de afirmación.

Vamos a ejecutar los métodos de esta clase.

  1. En Developer Console, haga clic en Test | New Run (Prueba | Nueva ejecución).
  2. En las clases de prueba, haga clic en TemperatureConverterTest.
  3. Para agregar todos los métodos de prueba de la clase TemperatureConverterTest para la ejecución de la prueba, haga clic en Add Selected (Agregar selección).
  4. Haga clic en Run (Ejecutar).
  5. 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 estas pruebas incluyen marcas de verificación verdes.
    Inspeccionar resultados de pruebas en la consola de desarrollador

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 probada (clase TemperatureConverter) tiene una cobertura del 100%, como se muestra en la imagen.

Ver porcentaje de cobertura de código en la consola de desarrollador
Nota

Nota

Siempre que modifique el código Apex, vuelva a ejecutar las pruebas para actualizar los resultados de la cobertura de código.

Un problema conocido de la consola de desarrollador impide la actualización correcta de la cobertura de código al ejecutar un subconjunto de pruebas. Para actualizar todos los resultados de su cobertura de código, use Test (Prueba) | Run All (Ejecutar todo) en lugar de Test | New Run (Nueva ejecución).

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 los valores de temperatura negativos.

La clase de prueba TemperatureConverterTest no cubre las entradas no válidas ni las condiciones de límite. Las condiciones de límite están relacionadas con los valores mínimos y máximos. En este caso, el método de conversión de temperatura acepta un decimal, lo que permite el uso de números altos y superiores a los valores dobles. En el caso de las entradas no válidas, no hay ningún valor de temperatura no válido, sino que la única entrada no válida es null. ¿Cómo controla el método de conversión este valor? 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. Puede modificar el método FahrenheitToCelsius() para buscar una entrada no válida y devolver null en este caso y, a continuación, agregar una prueba 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.

  1. 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.');
        }
  2. Para ejecutar 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).

    La afirmación de testBoilingPoint() no surte efecto y genera un error grave (excepción de tipo AssertException que no se puede capturar).

  3. 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, como se puede ver en esta imagen.

    Inspeccionar resultados de una prueba con errores en la consola de desarrollador
  4. Para ver el mensaje de error de esta prueba incorrecta, haga doble clic en la columna de errores de dicha prueba. Verá lo siguiente. El texto descriptivo junto a Assertion Failed: es el texto que incluimos 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 Plataforma Lightning 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 dan lugar a 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;
    }
}
Nota

Nota

El operador de igualdad (==) realiza comparaciones de cadenas sin distinción entre mayúsculas y minúsculas para eliminar la necesidad de convertir la cadena a minúsculas primero. Esto significa que pasar 'ca' o 'Ca' cumplirá la condición de igualdad con el literal de cadena 'CA'.

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 la consola de desarrollador 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%. Si abre esta clase en la consola de desarrollador, verá seis líneas azules (cubiertas) y dos líneas rojas (no cubiertas), como se muestra en esta imagen.

Líneas cubiertas para la clase TaskUtil en la consola de desarrollador

El motivo por el que la línea 5 no se ha cubierto 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 se ha cubierto 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, la cobertura de código para TaskUtil es 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.

  1. En Developer Console, seleccione Test (Prueba) | New Run (Nueva ejecución).
  2. Ingrese TempConverterTaskUtilSuite como nombre del conjunto y, a continuación, haga clic en OK (Aceptar).
  3. Seleccione TaskUtilTest, mantenga pulsada la tecla Ctrl y seleccione TemperatureConverterTest.
  4. Para agregar las clases seleccionadas al conjunto, haga clic en >.

    Ventana de modificación del conjunto de pruebas con dos clases de prueba seleccionadas
  5. Haga clic en Guardar.
  6. Seleccione Test (Prueba) | New Suite Run (Nueva ejecución de conjunto).
  7. Seleccione TempConverterTaskUtilSuite, y, a continuación, haga clic en > para mover TempConverterTaskUtilSuite a la columna de conjuntos de prueba seleccionados.
  8. Haga clic en Run Suites (Ejecutar conjuntos).
  9. 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.

Creación de 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.

Nota

Nota

Aunque no es una mejor práctica, hay ocasiones en las que un método de prueba necesita acceso a los datos preexistentes. Para acceder a los datos de la organización, anote el método de prueba con @isTest(SeeAllData=true). Los métodos de prueba de ejemplo de esta unidad no tienen acceso a los datos de la organización y, por lo tanto, no usan el parámetro SeeAllData.

Más información...

  • Puede ahorrar hasta 6 MB de código Apex en cada organización. Las clases de prueba anotadas con @isTest no 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. Para garantizar los resultados esperados, use Test.setFixedSearchResults() para definir los registros que va a devolver la búsqueda.