¡Descubra las novedades de MISRA C:2012 AMD3 y cómo obtener la cobertura MÁS AMPLIA con C/C++test 2022.2! Ver a pedido >>

Tutorial de JUnit: Configuración, escritura y ejecución de pruebas unitarias de Java

Por Nathan Jakubiak

6 de diciembre de 2022

8  min leer

Comprenda los conceptos básicos y amplíe su práctica de pruebas unitarias como un profesional con este tutorial.

¿Quiere saltarse los conceptos básicos y ver cómo automatizar la generación de pruebas unitarias para lograr una cobertura de código superior al 60 % en menos de 5 minutos? Echa un vistazo a Jtest >>

¿Qué son las pruebas unitarias?

Primero hablemos un poco sobre que es la prueba unitaria y por qué es importante en general.

La prueba unitaria es una forma de prueba de caja blanca en la que los casos de prueba se basan en la estructura interna. El probador elige entradas para ejercer rutas particulares a través del código y configura afirmaciones que validan la salida. El propósito de las pruebas unitarias es examinar los componentes individuales o piezas de métodos/clases para verificar la funcionalidad, asegurando que el comportamiento sea el esperado.

El alcance exacto de una "unidad" a menudo se deja a la interpretación, pero una buena regla general es definir una unidad como la menor cantidad de código necesaria para realizar una tarea independiente, por ejemplo, un solo método o clase.

Hay una buena razón por la que limitamos el alcance cuando realizamos pruebas unitarias: si construimos una prueba que valida una parte amplia de un proyecto, cambiamos el enfoque de la funcionalidad de un solo método a las interacciones entre diferentes partes del código. Si la prueba falla, no sabemos por qué falló. Nos quedamos preguntándonos si el punto de falla estaba dentro del método que nos interesaba o dentro de las dependencias asociadas con ese método.

Conceptos básicos de JUnit: Introducción a JUnit y uso de la automatización para crear pruebas unitarias

¿Qué es JUnit?

JUnit es el marco de pruebas unitarias de Java más popular. Un marco de código abierto, se utiliza para escribir y ejecutar pruebas automatizadas repetibles.

Como con cualquier otra cosa, el marco de prueba JUnit ha evolucionado con el tiempo. JUnit 4.0 se lanzó en 2006 y 5.0 se lanzó en 2017. Al momento de escribir este artículo, la última versión es 5.9.1. JUnit 5.x ha abordado muchas de las limitaciones anteriores de JUnit y se ha convertido en el marco de pruebas de unidades de Java más sólido.

Esta publicación de blog cubrirá el uso de JUnit 4 y 5.

Cómo configurar las pruebas de JUnit

Así que vamos a sumergirnos de lleno. Estos son los pasos para configurar JUnit.

Los IDE más comunes, como Eclipse e IntelliJ, ya tendrán instalada la integración de pruebas JUnit de manera predeterminada. Si no usa un IDE y tal vez depende únicamente de un sistema de compilación como Maven o Gradle, la instalación de JUnit 4/5 se maneja a través del archivo pom.xml o build.gradle, respectivamente.

Es importante tener en cuenta que JUnit 5 se dividió en 3 módulos, uno de los cuales es un módulo antiguo que admite la anotación/sintaxis de JUnit 4 y 3. El uso de JUnit 3 es muy bajo en este punto y generalmente solo se ve en proyectos mucho más antiguos.

Unidad 5

Debido a la forma modular de JUnit 5, se usa un BOM para importar todos los módulos y dependencias de JUnit. Si solo se necesitan módulos específicos, se pueden especificar grupos o artefactos individuales en su lugar.

Para agregar JUnit 5 a Maven, agregue lo siguiente a pom.xml:

<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>

Para Gradle, agregue lo siguiente al archivo build.gradle:

apply plugin: 'java'

dependencies {
implementation 'org.junit:junit-bom:5.9.1'
}

Unidad 4

Para agregar JUnit 4 a Maven, agregue lo siguiente a pom.xml.

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>

Para Gradle, agregue lo siguiente a build.gradle:

apply plugin: 'java'

dependencies {
testCompile 'junit:junit:4.13'
}

Si necesita agregar manualmente JUnit a la ruta de clase para la prueba de JUnit, debe hacer referencia directamente a los archivos jar sin formato, aunque esto no suele ser necesario. JUnit 4 tiene el jar disponible para descargar directamente. Junit 5 (mientras escribo esto) actualmente no tiene el archivo jar precompilado, pero puede compilar fácilmente el código y generar los jar. JUnit 4 tiene el jar disponible para descargar directamente.

Mejore las pruebas unitarias para Java con automatización: mejores prácticas para desarrolladores de Java

Pruebas unitarias de escritura: la anatomía de un JUnit

Ahora que hemos hablado un poco sobre la configuración de JUnit, pasemos a la construcción y ejecución de estas pruebas. Para ilustrar mejor la creación de JUnits, comenzaremos con algo básico. En el siguiente ejemplo de prueba JUnit, tenemos un método simple (izquierda) que convierte Fahrenheit a Celsius y una prueba JUnit (Derecho) escrito para probar nuestro método. He numerado las partes clave de la prueba JUnit y discutiré cada parte en detalle a continuación.

Piezas 1 y 2

Estas son importaciones para las clases y paquetes JUnit utilizados por la prueba unitaria. Las importaciones se pueden especificar como clases individuales, pero normalmente se especifican como paquetes completos mediante asteriscos. De cualquier manera funciona: el nivel de granularidad de las importaciones es una cuestión de preferencia.

Parte

Esto define el inicio de nuestra clase de prueba. Lo importante a tener en cuenta aquí es la convención de nomenclatura utilizada para la clase, que es ClassNameTest. Esta convención de nomenclatura no es necesaria, pero es la forma más común de nombrar las clases JUnit porque el nombre describe de manera sucinta el propósito de la clase de prueba unitaria y qué clase está probando.

Parte

Aquí vemos nuestra primera sintaxis específica de JUnit: la anotación @Test. Las anotaciones son extremadamente importantes al crear JUnits. Así es como el marco JUnit identifica las partes importantes de la prueba unitaria. En nuestro ejemplo, la anotación @Test le dice a JUnit que el método public void al que está adjunto se puede ejecutar como un caso de prueba.

Hay muchas otras anotaciones, pero algunas de las más comunes son las siguientes.

  • @Before identifica un método que debe ejecutarse antes de cada método de prueba en la clase. Por lo general, se usa para actualizar o restablecer el estado necesario para que los métodos de prueba se ejecuten correctamente.
  • @After identifica un método que debe ejecutarse después de cada método de prueba en la clase. Se puede utilizar para restablecer variables, eliminar archivos temporales, etc.
  • @Ignore especifica que no se debe ejecutar un método de prueba.
  • @BeforeClass identifica un método que debe ejecutarse una vez antes de ejecutar cualquier método de prueba.
  • @AfterClass identifica un método que debe ejecutarse una vez después de ejecutar todos los métodos de prueba.

Parte

Una vez más, tenga en cuenta la convención de nomenclatura testMethodName, Donde nombreMétodo es el nombre del método que se está probando en la clase bajo prueba.

Parte

En primera Dado que los sección de la prueba, construimos una nueva instancia de la clase bajo prueba y la inicializamos según corresponda. Esto es necesario ya que el método de prueba necesita llamar al método bajo prueba para probarlo. En nuestro ejemplo, no se necesita ninguna otra inicialización más allá de instanciar la clase, pero en muchos casos, es posible que se deba realizar una configuración adicional, como inicializar objetos para pasar al constructor o llamar a métodos que configuran el estado de la clase bajo prueba.

Parte

El Cuándo La sección de la prueba incluye la inicialización de variables que deben pasarse al llamar al método que se está probando y luego llamar al método de prueba (parte 8). Las variables deben recibir valores significativos que hagan que la prueba ejerza las partes del método de prueba que nos interesan. Tenga en cuenta que si una variable es un objeto, se puede crear una instancia o burlarse de ella.

Parte

Si el método bajo prueba devuelve un valor, debe capturarse en una variable para que se pueda afirmar su valor.

Parte

Las pruebas unitarias solo son valiosas si incluyen afirmaciones que validan que el método que se está probando devuelve el valor correcto y/o ajusta el estado de otros objetos como se esperaba. Sin aserciones, no tiene verificación, y su prueba es, en el mejor de los casos, una prueba de humo que brinda retroalimentación solo cuando se lanza una excepción.

Los métodos de aserción JUnit, que se incluyen en la clase org.junit.jupiter.api.Assertions en JUnit 5 y la clase org.junit.Assert en JUnit 4, se usan comúnmente para determinar el estado de aprobación/rechazo de los casos de prueba. El marco JUnit solo informa las afirmaciones fallidas. Al igual que con las anotaciones, hay muchas opciones de afirmación.

En nuestro ejemplo JUnit anterior, usamos el método assertEquals (esperado, real, delta). El primer argumento es:

  • El gastos esperados, que define el autor de la prueba.
  • El salida real, que es el valor de retorno del método que se llama
  • El delta, que permite una desviación aceptable entre los valores esperados y reales. Este delta es específico del hecho de que estamos validando el valor de un tipo doble.
¡Vea Parasoft Jtest en acción!

Cómo ejecutar un JUnit

¡Elige tu propia aventura! Aquí, veremos tres formas de ejecutar JUnits: directamente desde la línea de comandos, desde el IDE (Eclipse e IntelliJ) y usando sistemas de compilación (Maven y Gradle).

Cómo ejecutar un JUnit desde la línea de comandos

Para ejecutar un JUnit directamente desde la línea de comandos, necesita algunas cosas:

  • JDK en tu camino
  • Los archivos jar de JUnit
  • Los casos de prueba

El comando es el siguiente. Este ejemplo es para JUnit 4.

java -cp /path/to/junit.jar org.junit.runner.JUnitCore <test class name>

Nota: La ejecución de una prueba desde la línea de comandos suele realizarse desde un proceso de CI/CD que se ejecuta en un sistema de compilación como Jenkins o Azure DevOps.

Cómo ejecutar un JUnit desde el IDE

eclipsar

Dentro del Explorador de paquetes, busque su prueba JUnit. Haga clic con el botón derecho y seleccione Ejecutar como > Prueba JUnit. Esto ejecutará su prueba e informará los resultados dentro de la vista JUnit Eclipse.

IntelliJ

Ejecutar una prueba en IntelliJ es similar a Eclipse. En la ventana Proyecto, localice su prueba, haga clic con el botón derecho y seleccione Ejecutar 'testName'. Al igual que Eclipse, se abrirá una ventana JUnit con los resultados de la prueba.

Cómo ejecutar un JUnit usando sistemas de compilación

Maven

Maven ha simplificado la ejecución de pruebas unitarias. Asegúrese de estar en la ubicación adecuada desde su línea de comandos y de que el proyecto pom.xml esté configurado correctamente. Luego puede ejecutar lo siguiente para ejecutar sus JUnits.

Para ejecutar todo el conjunto de pruebas:

mvn test

Para ejecutar una(s) prueba(s) única(s)/específica(s):

mvn -Dtest=TestName test

Gradle

Gradle, como maven, ha simplificado la ejecución de pruebas.

Para ejecutar todo el conjunto de pruebas:

gradlew test

Para ejecutar una(s) prueba(s) única(s)/específica(s):

gradlew -Dtest.single=testName test

Nota: Maven y Gradle son sus propias bestias. Lo que se muestra aquí es mínimo para cubrir los conceptos básicos. Consulte su documentación si desea obtener más información.

Continuando con las pruebas unitarias

Nuestro ejemplo se ejecutó a través de una prueba de unidad simple y, por supuesto, esto es solo el comienzo de la prueba de unidad. Los métodos más complejos que deben probarse pueden llamar a métodos en clases dependientes o conectarse a sistemas externos como una base de datos. En este tipo de casos, puede ser deseable aislar el código a través de burlón.

La simulación ayuda a aislar unidades de código para que nuestras pruebas unitarias puedan centrarse solo en la clase/método específico que se está probando. El marco más común utilizado para burlarse en las pruebas JUnit es Mockito.

Para obtener más información sobre la burla, lea la publicación de mi colega: Cómo automatizar una prueba unitaria de Java, incluidas las burlas y las afirmaciones.

Entonces, si las pruebas unitarias son tan importantes, ¿por qué no todos las hacen de manera consistente? Bueno, las pruebas unitarias no son fáciles de implementar. También se necesitan muchas habilidades de desarrollo. Los desarrolladores tienden a no disfrutar mucho de las pruebas unitarias. Se necesita compromiso y tiempo para mantener las suites de prueba.

Pero los beneficios de las pruebas unitarias son claros.

Es necesario asegurarse de que el código previamente escrito continúe funcionando a medida que el código evoluciona y se agrega nueva funcionalidad a la aplicación. Las pruebas unitarias generalmente se ejecutan rápido y son efectivas para detectar regresiones introducidas en el código. Las pruebas unitarias son un requisito general para garantizar que las aplicaciones continúen funcionando según lo previsto. Es una forma rápida de obtener comentarios sobre los cambios en el código antes de integrarlos en la aplicación.

Por lo tanto, es útil implementar potentes herramientas de prueba de unidades como Prueba J de Parasoft eso puede remediar muchos de los desafíos asociados con las pruebas JUnit y ahorrar tiempo valioso a los desarrolladores.

Parasoft Jtest impulsado por IA Asistente de prueba unitaria permite a los usuarios generar rápidamente conjuntos de pruebas que cubren el 60 % o más del código de su aplicación con una sola acción. Cuando la creación de pruebas alcanza los límites de lo que se puede automatizar por completo, Unit Test Assistant ofrece flujos de trabajo y recomendaciones que ayudan a los usuarios a crear pruebas manualmente de manera más eficiente.

Además, el módulo de análisis de impacto de las pruebas acelera el tiempo de ejecución de las pruebas unitarias dentro de los procesos de CI/CD o el IDE al identificar y ejecutar solo el subconjunto del conjunto de pruebas unitarias que se necesita para validar los cambios de código recientes.

Vea de primera mano cómo automatizar la generación de pruebas unitarias para lograr una cobertura de código superior al 60 % en menos de 5 minutos.

Por Nathan Jakubiak

Nathan es director sénior de desarrollo en Parasoft. Él y sus equipos desarrollan capacidades de productos en las áreas de pruebas de API (SOAtest), virtualización de servicios (Virtualize), gestión de entornos de prueba (CTP), pruebas de interfaz de usuario (Selenic) y análisis estático y pruebas unitarias (Jtest y C++test) . Nathan ha estado en Parasoft desde 2000 y posee varias patentes relacionadas con las pruebas de software. Supervisa la arquitectura de productos y lidera varios equipos de desarrollo distribuidos que utilizan la metodología ágil Scrum. Nathan dirige a sus equipos para crear soluciones de software bien diseñadas y de alta calidad con procesos de desarrollo que tengan sentido.

Reciba las últimas noticias y recursos sobre pruebas de software en su bandeja de entrada.