04 septiembre 2019

Testing con Spring Boot

Los casos de prueba son importantes para el desarrollo de las aplicaciones, por lo cual, no solo verifican el código si no que verifican si realmente funciona correctamente, asegurando que deban realizar todo lo que esperan que realicen. 


En este artículo, se explicara un ejemplo con dos tipo de casos diferente, donde podrán escribir pruebas, para asegurarnos de que el código no se rompa o falle a medida que la aplicación vaya evolucionando. Se pueden escribir pruebas antes o después de que se haya escrito el código.

Si retrocedemos hace aproximadamente 12 años, encontraríamos un proceso de prueba en su mayoría conducido por muchos ingenieros de prueba. Pero con el aumento de JUnit, la adopción de servidores de integración continua (CI), grande cantidades de librerías de prueba y servicios integrados de cobertura de prueba, Puede ver la adopción generalizada de pruebas automatizadas.

Mencionare la metodología TDD, como puede ayudar en la buenas practicas del desarrollo de software.

Test-Driven Development (TDD)


Consiste en escribir pruebas automatizadas que verifiquen si el código realmente funciona. TDD se centra en el desarrollo con los requisitos bien definidos en forma de pruebas. Cada proceso de desarrollo incluye pruebas de forma automática o manual. Las pruebas automatizadas dan como resultado un ciclo de desarrollo general más rápido. TDD eficiente es más rápido que el desarrollo sin pruebas. La cobertura de prueba integral proporciona confianza en el desarrollo de la aplicación y esta confianza permite la refactorización de la aplicación. La refactorización promueve el desarrollo ágil; Es fácil descubrir fallas y las corrige. Las pruebas te hacen pensar en tu diseño. Si su código es difícil de probar, entonces el diseño debe reconsiderarse. Un caso de prueba te ayuda a concentrarte en lo que importa. Te ayuda a no escribir código que no necesita y encuentra problemas temprano durante el desarrollo.

Ejemplo

Spring Boot agrega automáticamente la dependencia “Test” cuando creamos el proyecto de desde la página Spring Initializr , agregando dicha dependencia al archivo “pom.xml” como se puede observar en la figura 1. 

1
2
3
4
5
<dependency>           
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>
Figura 1
 
Por otro lado Spring Boot proporciona muchas librerias útiles que nos pueden servir para realizar pruebas, como son JUnit, Mockito, AssertJ y otras más. 

Acá dejo una breve definición de cada librería, con el objetivo que el lector tenga una idea y en el caso que quiera investigar o profundizar más en el tema: 
  • JUnit: Esto está relacionado con las pruebas unitarias de aplicaciones Java
  • JSONassert: Esta librería se utiliza para hacer valer en JSON - support.
  • AssertJ: Es una biblioteca de afirmaciones.
  • Mockito: Es un framework de trabajo para crear Mocks en los tests unitarios escritos en Java.
  • Hamcrest: Esta biblioteca está relacionada con restricciones o predicados
  • Spring Test y Spring Boot Test: Añaden utilidades y soporte de pruebas de integración para aplicaciones con Spring Framework y Spring Boot.
  • JsonPath: XPath para JSON.
Además de que estas diversas bibliotecas de prueba se suministran automáticamente, también se incluyen muchas dependencias opcionales. Esto significa que se pueden agregar a la lista de dependencias de nuestro proyecto sin especificar la versión. Las dependencias opcionales se enumeran a continuación:
  • HTMLUnit: kit de herramientas de prueba para salidas en HTML
  • Selenium: automatización del navegador para pruebas de UI
  • Flapdoodle: base de datos MongoDB integrada para pruebas
  • H2: base de datos SQL integrada para pruebas
  • Spring REST Docs: genera documentación REST utilizando pruebas automatizadas

Si observa la Figura 2, la estructura de proyecto, tiene creado su propio paquete para las clases de prueba:
Figura 2

Creando Pruebas Unitarias


Comenzamos creando nuestro primer caso de prueba, en este caso estamos utilizando un JUnit, que es una libreria popular de pruebas unitarias basada en Java como lo mencione anteriormente. El siguiente código fuente muestra la estructura de ejemplo test en una clase de Spring Boot. 

  • La anotación @SpringBootTest especifica que es una clase de prueba regular que ejecuta pruebas basadas en Spring Boot. 
  • La anotación @Test antes del método define a JUnit que es el método que se puede ejecutar como un caso de prueba. 
  • La anotación @RunWith(SpringRunner.class) proporciona un Spring ApplicationContext y obtiene beans inyectados en su instancia de prueba, como se puede observar la Figura 3.

@SpringBootTest
public class TestCustomerApplicationTests {

        @Test
        public void contextLoads() { 
 
        }
}
Figura 3

Continuamos con nuestro caso de prueba, que en este paso, se probará la funcionalidad principal de la aplicación antes de crear cualquier caso de prueba formal. Abrimos la clase de prueba TestCustomerApplicationTests que fue creada en la aplicación. Hay un método de prueba llamado contextLoads donde vamos agregar la prueba. La siguiente prueba comprueba que la instancia del controlador que se crea e inyecta con éxito, como se puede observar la Figura 4:

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestCustomerApplicationTests {


 @Autowired
 private CustomerController controller;

 @Test
 public void contextLoads() {
  assertThat(controller).isNotNull();
 }

}
Figura 4

Para ejecutar pruebas en el IDE Intellij, nos ubicamos en el explorador de proyectos, presionamos clic derecho en la clase TestCustomerApplicationTest y seleccionamos Run | ‘TestCustomerApplicationTest’ del menú, como se muestra en la Figura 5.

Figura 5

Ahora nos ubicamos en la pestaña JUnit en la parte inferior del IDE, para observar los resultados de la prueba como se muestran en esta pestaña, para este caso, fue exitoso, como se puede observar en la Figura 6. 

Figura 6

Continuamos con el Caso de prueba # 2 

Para realizar este caso # 2, vamos a descargar la versión de inicio del proyecto, con el objetivo que ya se encuentra creadas algunas clases que vamos a utilizar en el ejemplo. Creamos la prueba unitaria para nuestro repositorio de “Customer”, con el objetivo de probar las operaciones CRUD. Creamos una nueva clase llamada CustomerRepositoryTest dentro del paquete de TestCustomer. Utilizamos la anotación @DataJpaTest en vez de la anotación @SpringBootTest, con la finalidad que se puedea usar si la prueba se enfoca solo en componentes JPA. Al usar esta anotación, la base de datos H2, Hibernate y Spring Data se configuran automáticamente para la prueba. El registro de SQL también está activado. Las pruebas son transaccionales por defecto y se retrotraen al final del caso de prueba. TestEntityManager se usa para manejar las entidades persistentes y está diseñado para usarse en pruebas. Puede ver el código fuente de la clase de prueba JPA en la figura 7:

@RunWith(SpringRunner.class)
@DataJpaTest
public class CustomerRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private CustomerRepository repository;
}
Figura 7


Adicionamos el primer caso de prueba de la operación CRUD, en este caso vamos probar  el guardar "save" de un cliente nuevo a la base de datos. Se crea un nuevo objeto de Cliente y se guarda en la base de datos con el método persistAndFlush, proporcionado por TestEntityManager. Luego, verificamos que la identificación del cliente no puede ser nula  y si se guarda correctamente. El siguiente código fuente como se puede observar en la Figura 8, muestra el método del caso de prueba. Agregue el siguiente código de método a su clase CustomerRepositoryTest:


    @Test
    public void saveCustomer() {
        Customer customer = new Customer("Mark", "Heckler", "Calle 5", "New York", 35);
        entityManager.persistAndFlush(customer);
        assertThat(customer.getId()).isNotNull();
    }

Figura 8


El segundo caso de prueba vamos a probar la eliminación "delete" de clientes de la base de datos. Creamos un nuevo objeto de cliente y se guarda en la base de datos. Luego, todos los clientes se eliminan de la base de datos y finalmente, el método de consulta findAll() debería devolver una lista vacía. El siguiente código fuente como se puede observar en la Figura 9, muestra el método del caso de prueba. Agregue el siguiente código de método a su clase CustomerRepositoryTest:

    @Test
    public void deleteCustomer() {
        entityManager.persistAndFlush(new Customer("Omar", "Berroteran", "Calle 6", "Managua", 40));
        entityManager.persistAndFlush(new Customer("Elena", "Aguirre", "Calle 7", "Barranquilla", 23));

        repository.deleteAll();
        assertThat(repository.findAll()).isEmpty();
    }
Figura 9

Ejecutamos los casos de prueba y verifique la pestaña JUnit, para comprobar que las pruebas fueron exitosas como se puede observar en la figura 10:

Figura 10

Conclusión 

Una buena practica al desarrollar aplicaciones es implementar y usar las pruebas unitarias, las ventajas es que son fácil de implementar, comprender y se pueden reutilizar.


Referencias


  • Libro: Hands-On Full Stack Development with Spring Boot 2.0 and React, Segunda Edicion, By Juha Hinkula. Siquieres adquirirlo visita Aquí
  • Libro: Mastering Spring Boot 2.0, By Dinesh Rajput. Si quieres adquirirlo visita Aquí 


28 julio 2019

Hola Mundo Scala para Desarrolladores en Java


Scala es un lenguaje de programación multi-paradigma moderno, donde integra fácilmente las programación funcional y Orientada a Objeto. Es compilado por Java bytecode donde permite que el código resultante pueda ejecutarse en la Java JVM.

Las características más importantes de Scala son las siguientes:
  • Se puede combinar las librerías de Java con Scala, la ventaja que se pueden trabajar con ambos paradigmas (OOP y FP), por lo tanto, podemos tomar lo mejor de cada uno.
  • Es un lenguaje de tipado seguro que incorpora objetos orientados y programación funcional en un lenguaje extremadamente conciso, lógico, poderoso y de alto nivel. 
  • Scala es un lenguaje de programación puramente orientado a objetos donde cada valor es un objeto y cada operación es una llamada a un método. Por lo tanto, soporta arquitectura de componentes avanzados a trasvés de clases y traint. Abstracción, encapsulamiento, polimorfismo, recolección de basura y demás características de la programación orientada a objetos son totalmente soportados, pero con un toque más elegante, seguro y fácil de implementar. 
  • Scala también es un lenguaje de Programación Funcional, por lo cual es un estilo de desarrollo de software que enfatiza las funciones que no dependen del estado del programa. El código funcional es más fácil de probar y reutilizar, más sencillo de paralelizar y menos propenso a errores que otros códigos. Scala es un lenguaje emergente de JVM que ofrece un fuerte soporte para FP. Su sintaxis familiar y su interoperabilidad transparente con Java hacen de Scala un gran lugar para comenzar a aprender (FP). 
          Apesar de que el paradigma funcional fue mayormente usado en el sector de investigación
          y la academia y no para la industria. Actualmente la FP ha tomado mucho interés en muchos              lenguajes de programación debido a la manera que simplifica ciertos problemas de diseño,                  especialmente la concurrencia.

Instalar Scala
Descarga Scala en la siguiente url: https://www.scala-lang.org/download/

Ejemplo
En este ejemplo vamos a crear el famoso “HolaMundo” que por cierto, es muy simple. Utilizando el IDE Intellij.

Primer Paso: Creamos un nuevo proyecto en scala como se muestra en la Figura 1.

Figura 1

Segundo Paso: Seleccionamos en el  el lenguaje de programación "Scala" como segundo seleccionamos el "sbt" como se puede observar en la Figura 2.

Figura 2

Tercer Paso: Colocamos el nombre del proyecto y la ruta, ojo no se nos olvide seleccionar la opción de Scala source, como se puede observar en la Figura 3.

Figura 3

Cuarto Paso: Estructura del proyecto en "Scala", como se puede observar en la Figura 4.

Figura 4

Quinto Paso: En este paso seleccionamos la opción "Scala Class", como se puede observar en la Figura 5.

Figura 5

Agregamos el nombre, en este ejemplo colocamos "HolaMundo" y seleccionamos el paquete "Object", como se puede observar en la Figura 5.1.

Figura 5.1

Sexto Paso: En este ejemplo de Scala se realizara de dos formas diferentes.

Primera Forma: Como pueden observar en la Figura 6, la estructura del código es muy similar a la de Java, si nos ponemos analizar, para los desarrolladores antiguo en Java de pronto se le hace un poco extraño la declaración Object,  esta declaración introduce lo que se conoce como objeto singleton, que es una clase con una sola instancia, por ejemplo la clase HolaMundo se declara como una instancia también llamada del mismo nombre. Esta instancia es creada por demanda, en otras palabras, la primera vez que es utilizada. Por lo tanto, se define un método main,  notamos que dicho método no es declarado como static, esto hace referencia que los miembros estaticos(metodo o campos) no existen en Scala. Por otra parte tenemos un (Array de objeto de String), es decir, en el caso que se requiera ejecutar desde una linea comando toma los argumentos como parámetros. Por otra parte no es necesario declarar dentro del método main un tipo de retorno.

object HolaMundo{

  def main(args: Array[String]): Unit =
  {
           println("Hola Mundo")
  }
}
Figura 6

Segunda Forma: Agregamos la funcionalidad App “trair”, se puede utilizar para convertir rápidamente los objetos en programas ejecutables, como se puede observar en la Figura 7.

object HolaMundo2 extends App {

  println("Hola Mundo 2")
}
Figura 7

Ahora debería tener las palabras "Hola Mundo" en la consola en la parte inferior del IDE.

REFERENCIAS: