Post on 08-Jul-2015
description
MADRID · NOV 21-22 · 2014
Desarrollo de pruebas en Java EE
José Manuel López DoñaArquitecto Software en Sopra@josemanlopez
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014
EPIC FAIL!
¡Espera! ¿Realmente las necesito?
main()
MADRID · NOV 21-22 · 2014
Si desarrollas pruebas en el código
PRUEBAS DRY, SOLID, ...
MADRID · NOV 21-22 · 2014
Requisitos previos, conocer bien:
● Las técnicas de desarrollo / frameworks / librerías que se estén utilizando
● Metodologías, conceptos y herramientas para desarrollar pruebas: TDD/BDD, Mocks, Stubs, Spies, Mockito, EasyMocks, etc.
MADRID · NOV 21-22 · 2014
Si, si… suena bien, pero...
Lo intenté y Java EE no me lo puso fácil
Java developer
MADRID · NOV 21-22 · 2014
JNDICMPEJB2
StrutsHibernate Spring
JSFJPAEJB3
Seam CDI
Evolución del desarrollo en Java EE
Arquillian
Servicios de contenedor
ModeloPOJO
Inyección dedependencias
Integración frameworks
Facilidad enel desarrollo
Facilidad para probar
Fuente: http://www.slideshare.net/nukeevry1/arquillian
MADRID · NOV 21-22 · 2014
Tipos de pruebas (automáticas)
● Pruebas unitarias
● Pruebas de integración
○ Infraestructura (contenedor / servidor de aplicaciones)
○ Con otros sistemas/aplicaciones
● Pruebas funcionales
MADRID · NOV 21-22 · 2014
Java EE 7
CDI Extensions
Web Fragments
Servlet 3.1
JSF 2.2JSP 2.3EL 3.0
JAX-WS 2.2JAX-RS 2.0 JSON 1.0 WebSocket
1.0
CDI 1.1 Interceptors 1.0JTA 1.2
Managed Beans 1.0
JPA 2.1 JMS 2.0
Common Annotations 1.1 Concurrency 1.0
EJB 3.2
JCA 1.7 Batch 1.0
Bean
Val
idat
ions
1.1
¿MOCKS PARA TODO?
MADRID · NOV 21-22 · 2014
Arquitectura de pruebas en Java EE
Test CaseArquillian
Core + Extensions
ShrinkWrap
Unit Testing FrameworkJunit / TestNG
CoverageJaCoCo
Maven
ContainerTomEE Embedded
OpenWebBeans
Embedded DatabaseDerby
MADRID · NOV 21-22 · 2014
Arquillian: características
● Pruebas reales Java EE sin necesidad de mocks
● IDE friendly: ejecución de JUnit (o TestNG) desde el IDE o Maven
● Test enriquecidos: uso de características Java EE y extensiones
● Control del classpath: micro-despliegues en las pruebas
● Depuración de las pruebas desplegadas en servidor
● Contenedor agnóstico: múltiples adaptadores
MADRID · NOV 21-22 · 2014
Arquillian: configuración proyecto
● Incluir dependencias en fichero pom.xml○ Importar arquillian core, extensiones y runtimes
○ Crear maven profiles para tener diferentes runtimes
● Configurar el fichero arquillian.xml para sobrescribir valores por defecto (opcional)
MADRID · NOV 21-22 · 2014
Arquillian: desarrollo de pruebas
● Crear testcase con JUnit
● Incluir las clases bajo prueba usando ShrinkWrap
● Programar los métodos de pruebas @Test
● Ejecutar la prueba JUnit desde Maven / IDE
MADRID · NOV 21-22 · 2014
Arquillian: código ejemplo test@RunWith(Arquillian.class)public class GreeterTest {
@InjectGreeter greeter;
@Deployment (name="GreeterTest") public static JavaArchive createDeployment() { return ShrinkWrap.create(JavaArchive.class) .addClass(Greeter.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); }
@Test public void should_create_greeting() { Assert.fail("Not yet implemented"); }}
MADRID · NOV 21-22 · 2014
Arquillian: ejecución de test (IDE)
MADRID · NOV 21-22 · 2014
.addPackages(true, Filters.exclude(".*Test.*|.*Mock.*"),"com.project");
Arquillian: ¿cuantas clases meto?
¿Todas? ¿Puedo?
● Tamaño JAR/WAR de pruebas
● Delimitar alcance de la pruebas
● Consideraciones rendimiento (p.e. contexto JPA)
● Si se usa embedded solo incluir clases aplicación
MADRID · NOV 21-22 · 2014
Arquillian: adaptadores runtimes
● Diferentes tipos:
○ Contenedor CDI (Weld, OpenWebBeans)
○ Contenedor EJB (OpenEJB 3.1)
○ Servidor de aplicaciones (Glassfish, JBoss, WAS, WebLogic,
TomEE, etc.)
● Diferentes formas de ejecución
○ Embedded
○ Managed
○ Remote
MADRID · NOV 21-22 · 2014
Arquillian: adaptadores runtimes
Runtime Tiempo total (seg.) Tiempo test (seg.)
glassfish-embedded 3.1.2.2 25 1,3
openwebbeans-embedded 1.1.6 5,8 0,03
jbossas-managed 7.1.1 20,4 0,3
wlp-managed 8.5.1.1 31,9 2,3
tomee-embedded 1.6.0 10,5 0,25
Resultados de ejecutar 10 veces una prueba de una inyección de un EJB con @Inject.
MADRID · NOV 21-22 · 2014
Arquillian modos de ejecución
● Servidor
● Cliente (@RunAsClient).
○ Ejemplo: WS REST (Arquillian REST Extension)
○ Ambos modos son posibles a la vez
MADRID · NOV 21-22 · 2014
Context and Dependency Injection
● @Inject
● @Produce
● @Alternative, @Specializes
MADRID · NOV 21-22 · 2014
Creación de alternativas (deploy)@Alternative@Specializes@Stereotype@Retention(RUNTIME)@Target(TYPE)public @interface Mock {}
<beans> <alternatives> <stereotype>org.mycompany.testing.Mock</stereotype> </alternatives></beans>
@Mockpublic class MockLoginService extends LoginService { ... }
MADRID · NOV 21-22 · 2014
Producción de alternativas (runtime)
@Mock @ProducesLoginService produceMockLoginService() {
LoginService login = mock(LoginService.class);
Mockito.when(login.validate(“user1”, “pass_invalid”) .thenReturn(RESULT.FAIL);
Mockito.when(login.validate(“user1”, “pass_valid”) .thenReturn(RESULT.SUCCESS);
return login;}
MADRID · NOV 21-22 · 2014
Algunos ejemplos de mocks
● FacesContext ➜ valores en la request/session
● Servicios Web (JAX-WS / JAX-RS)
○ Unmarshal (XML/JSON ➜ POJO) con JAXB/Jackson
public static <T> getObjectFromXML(String xmlPath, Class<T> className)
MADRID · NOV 21-22 · 2014
Arquillian Persistence Extension
● Gestión de transacciones
● Inserción de datos en base de datos
● Valida datos tras la prueba
● Se basa en DBUnit
MADRID · NOV 21-22 · 2014
Arquillian Persistence Extension
useraccount: - id: 1 firstname: John lastname: Smith username: doovde password: password - id: 2 firstname: Clark lastname: Kent username: superman password: kryptonite
users.yml
useraccount: - firstname: John lastname: Smith username: doovde password: password - firstname: Clark lastname: Kent username: superman password: LexLuthor
expected-users.yml
MADRID · NOV 21-22 · 2014
Arquillian Persistence Extension
@Test@UsingDataSet("datasets/users.yml")@ShouldMatchDataSet("datasets/expected-users.yml")public void should_change_user_password() throws Exception {
// givenString expectedPassword = "LexLuthor";UserAccount user = em.find(UserAccount.class, 2L); // whenuser.setPassword(expectedPassword);user = em.merge(user); // thenassertEquals(expectedPassword, user.getPassword());
}
MADRID · NOV 21-22 · 2014
Estrategias de pruebas: End-to-End
Backing Bean
JPA
EJB
Arquillian Persistence Derby
Port MockJAX-WS
PruebaArquillian
MADRID · NOV 21-22 · 2014
Estrategias de pruebas: Aisladas
Backing Bean JPAEJB
Arquillian Persistence Derby
Port MockJAX-WS
PruebaArquillian
JPA Mock EJB Mock
PruebaArquillian
PruebaArquillian
MADRID · NOV 21-22 · 2014
Cobertura: JaCoCo
MADRID · NOV 21-22 · 2014
Cobertura: JaCoCo
MADRID · NOV 21-22 · 2014
Cobertura: Sonar
MADRID · NOV 21-22 · 2014
Principales problemas encontrados
● Falta documentación de configuraciones avanzadas
● Diferentes versiones de Arquillian y extensions
● Diferente comportamiento según contenedores
MADRID · NOV 21-22 · 2014
Algunas lecciones aprendidas
● Utilizar pruebas aisladas para TDD
● Uso de plugin failsafe para pruebas end-to-end
● Uso de @Inject en vez de @EJB
● Probar bien la arquitectura base de pruebas
● Elaborar una metodología de uso para desarrolladores
● Integración continua: ¡Rompe el build! }:-)
MADRID · NOV 21-22 · 2014
FIN@josemanlopez
https://www.linkedin.com/in/josemanlopez
http://josemlopez.blogspot.com.es/
http://goo.gl/MOi8zb