jueves, 29 de noviembre de 2012

Introducción a Spock - Parte 2


Un poco de Feature Methods Blocks...


Estos simpáticos bloques son los que encontramos dentro de nuestros métodos de prueba. Los que tenemos al día de hoy son:

import spock.lang.*;

class MySecondSpecification extends Specification {

   //Setup: (or Given:)
   //Expect:
   //When:
   //Then:
   //Where:
      //and:
      //and:
   //Cleanup:

}

Un repaso rápido de que significa cada uno...

  • Setup: Se explica por si mismo, aquí deberíamos colocar todo lo relativo al setup de la prueba.
  • Expect: Es algo similar a lo que haría un assert en el viejo JUnit, se espera un estimulo y su correspondiendo respuesta. 
  • When/Then: Autoexplicativo también!
  • Where: Es en algun sentido similar al Expect pero tiene un poco mas de maleabilidad para evaluacion de tablas, listas y otras cosas mas. También se puede combinar con el and: si es necesario para que nuestro código quede mas limpio.
  • Cleanup: Lo típico, cierre de conexiones, archivos,  o lo que sea necesario.

Nuestros Features Methods deberían contener al menos un bloque sino el método no sera considerado como tal.


Fields...

Tenemos 2 tipos de fields, los "shareables" y los "no shareables". Los "shareables" son aquellos que son costos de instanciar y que necesitamos compartirlos a través de todos las pruebas, como puede ser una conexión a una base de datos.

Por otro lado los "no shareables" son aquellos objetos que no nos interesa compartir su estado a través de las distintas pruebas. Hay que tener en cuenta un punto muy importante y es que estos se "reinstancian" con la ejecución de cada prueba.


class SharedOrNotSharedSpecification extends Specification {

   @Shared expensiveResource = new expensiveResource()
   cheapResource = new cheapResource()

   .
   .
   .

}



lunes, 20 de agosto de 2012

Introducción a Spock - Parte 1


El articulo escrito a continuación es un mini tutorial para que rápidamente puedan comenzar a ser productivos en el uso del framework y esta dirigido principalmente a desarrolladores con conocimientos de Java, Groovy y JUnit.

Yendo al punto, empezamos con el tema...

¿Que es Spock?

"...es un framework de pruebas y especificación para aplicaciones Java y Groovy..."

Fuera de esta definición formal veremos mas adelante que Spock tiene una gran base de JUnit a nivel conceptual y practica, por lo que para quienes lo usen debería ser fácil tomar el conocimiento y llevarlo a la practica.

Para una definición mas formal, ver esto: Definicion de spockframework.org

Specifications...

Las especificaciones son básicamente el corazon de Spock y es el lugar donde vamos a crear nuestros test dentro. Estas especificaciones veremos que describen el comportamiento de determinadas características de nuestro interés, propiedades, aspectos y algunas cosas mas. Estas pruebas pueden variar desde el comportamiento de una clase concreta hasta una parte de un sistema aplicativo de nuestro interés.

Ejemplo de un a especificación concreta:

  import spock.lang.*;

class MyFirstSpecification extends Specification {
   //Feature Method #1
   //Feature Method #2
   //Feature Method #3
}

Todas las especificaciones siempre deben extender de spock.lang.Specification

Un aspecto muy importante de Spock es que si escribimos las especificaciones con suma consciencia, las mismas pueden ser de mucha ayuda como información para otros. Podemos sacar una gran ventaja especialmente sobre especificaciones de alto nivel ya que podemos utilizarlas como documentación para otras personas que no posean fuertes conocimientos técnicos. Esto es gracias a que el lenguaje natural provisto por Groovy junto con Spock hace que las especificaciones sean altamente legibles y entendibles para terceros.

Además una buena estrategia de agrupación de pruebas puede ayudar no solo a otros a entender los casos de uso del negocio en cuestión, sino que puede ayudar hasta al mismo desarrollador a darse cuenta si esta entendiendo el problema que esta resolviendo. Veamos un ejemplo concreto:

//Feature Method example

def "Login fails if incorrect details submitted" () {
 
 when: "a user visits then login page"
       def loginPage = LoginPage.open()

 and: "enters their details incorrectly"
      loginPage.loginWith("someUsername", "badPassword")

 then: "they should see an error message"
       loginPage.loginError == LoginPage.LOGIN_FAILED_MSG

 and: "ther should not be logged in"
      !HomePage.open().isLoggedIn() 
}

Feature Methods...

Un Feature Method es básicamente el lugar donde vamos a escribir nuestra prueba. Conceptualmente los Feature Methods constan de 4 fases, veamos...
  1. Realizamos el setup del Feature Method
  2. Proveemos del "estimulo"
  3. Se hace el match contra la respuesta esperada del sistema
  4. Hacemos el cleanup del Feature Method
Y obviamente una Specification puede tener varios Feature Methods dentro.


Si ya te cansaste de leer...

 ...y quieres empezar a hacer tus propias pruebas (algo que recomiendo) pueden hacerlo sin instalar nada aun. Para esto tienen las siguientes herramientas online: