Introducción a JUnit

  • 8,651 views
Uploaded on

Introducción a pruebas unitarias con JUnit.

Introducción a pruebas unitarias con JUnit.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
8,651
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
214
Comments
1
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Pruebas unitarias JUnit
  • 2. Pruebas unitariasConceptos básicos  Es una forma de probar el correcto funcionamiento de un módulo de código.  Sirve para asegurar que cada uno de los módulos funcione correctamente por separado.  Con las Pruebas de Integración, se podrá asegurar el correcto funcionamiento del sistema o subsistema en cuestión.  Escribir casos de prueba para cada método en el módulo → cada caso sea independiente del resto.
  • 3. Pruebas unitariasRequisitos  Automatizable: no debería requerirse una intervención manual. Esto es especialmente útil para integración continua.  Completas: deben cubrir la mayor cantidad de código.  Repetibles o Reutilizables: no se deben crear pruebas que sólo puedan ser ejecutadas una sola vez. También es útil para integración continua.
  • 4. Pruebas unitariasRequisitos  Independientes: la ejecución de una prueba no debe afectar a la ejecución de otra.  Profesionales: las pruebas deben ser consideradas igual que el código, con la misma profesionalidad, documentación, etc.
  • 5. Pruebas unitariasObjetivos  Aislar cada parte del programa.  Mostrar que las partes individuales son correctas.  Proporcionan un contrato escrito, que el trozo de código debe satisfacer.  Controlar el impacto de los cambios. Las pruebas unitarias aseguran funcionamiento de código tras cambios del mismo.
  • 6. Pruebas unitariasVentajas  Fomentan el cambio: Facilitan al programador cambios de código para mejorar su estructura (refactorización) → Asegura que los nuevos cambios no han introducido errores.  Simplifica la integración: Llegar a fase de integración con seguridad de que el código está OK → Se facilitan las pruebas de integración.  Documenta el código: Las propias pruebas son documentación del código → ahí se puede ver cómo utilizarlo.
  • 7. Pruebas unitariasVentajas  Separación de la interfaz y la implementación: La lógica se prueba a través de los casos de prueba y no con interfaz → objetos mock (mock object) para simular el comportamiento de objetos complejos.  Los errores están más acotados y son más fáciles de localizar: Tenemos pruebas unitarias que pueden desenmascararlos.
  • 8. Pruebas unitariasLimitaciones  Las pruebas unitarias no descubrirán todos los errores del código.  Por definición, sólo prueban las unidades por sí solas → no descubrirán: • errores de integración • problemas de rendimiento • otros problemas que afectan a todo el sistema en su conjunto  Puede no ser trivial anticipar todos los casos especiales de entradas.
  • 9. JUnit
  • 10. JUnitConceptos básicos  Framework para pruebas unitarias.  Conjunto de librerías creadas por Erich Gamma y Kent Beck que son utilizadas en programación para hacer pruebas unitarias de aplicaciones Java  El framework incluye formas de ver los resultados (runners) que pueden ser en modo texto, gráfico (AWT o Swing) o como tarea en Ant.  Plug-ins para principales IDEs como Eclipse y NetBeans.
  • 11. JUnitConceptos básicos  Open Source, disponible en http://www.junit.org  Los casos de prueba son realmente programas Java. Quedan archivados y pueden (DEBEN) ser re- ejecutados tantas veces como sea necesario.
  • 12. JUnit Ejemplo sencillopackage dominio;import java.util.Vector; ← Representa una lista ordenable de formapublic class Lista extends Vector { creciente. public Lista() { ... } Se ordena llamando al public Lista(String[] elementos) {...} método público public Lista ordenar() {...} ordenar(), que llama a su vez a ordenar(0, protected void ordenar(int iz, int de) { ... size()-1) }}
  • 13. JUnitEjemplo sencillo •Un posible caso de prueba es el siguiente: String[] e3={"e", "d", "c", "b", "a"}; Lista reves=new Lista(e3); Lista derecha=reves.ordenar(); ...y el resultado esperado: "a", "b", "c", "d", "e"
  • 14. JUnitEjemplo sencillo String[] e3={"e", "d", "c", "b", "a"}; Lista reves=new Lista(e3); Lista derecha=reves.ordenar();  Si derecha es igual al resultado esperado, entonces el caso de prueba ha sido superado {"a", "b", "c", "d", "e"}
  • 15. JUnitEjemplo sencillo  Construcción manual de un objeto expected y comparación con el obtenido: String[] e3={"e", "d", "c", "b", "a"}; Lista reves=new Lista(e3); Lista derecha=reves.ordenar(); Lista expected={"a", "b", "c", "d", "e"}; if (derecha.equals(expected)) ResultadoCorrecto(); else ResultadoIncorrecto();
  • 16. JUnitEjemplo sencillo  El ejemplo anterior (obtained frente a expected) es una idea fundamental de JUnit ¿ Qué nos ofrece JUnit? • JUnit permite mantener de forma separada los casos de prueba • Permite ejecutarlos (y re-ejecutarlos) de forma automática • Nos permite construir "árboles de casos de prueba" (suites)
  • 17. JUnitEjemplo sencillo  El ejemplo anterior con JUnit: public void testOrdenarReves() { String[] ex={"a", "b", "c", "d", "e"}; Lista expected=new Lista(ex); String[] e3={"e", "d", "c", "b", "a"}; listaAlReves=new Lista(e3); this.assertEquals(expected, listaAlReves.ordenar()); }
  • 18. JUnitEjemplo sencillo  ¿Dónde está el código anterior? En la clase ListaTester, creada para realizar las pruebas de Lista.  ListaTester extiende de TestCase definida en Junit.  En TestCase está definido el método assertEquals antes mencionado, y muchos otros más.
  • 19. JUnitEjemplo sencillo public class ListaTester1 extends TestCase { public ListaTester1(String sTestName) { super(sTestName); } public void testOrdenarReves() { String[] ex={"a", "b", "c", "d", "e"}; Lista expected=new Lista(ex); String[] e3={"e", "d", "c", "b", "a"}; Lista listaAlReves=new Lista(e3); this.assertEquals(expected, listaAlReves.ordenar()); } }
  • 20. JUnitEl TestRunner public class ListaTester1 extends TestCase { public ListaTester1(String sTestName) { super(sTestName); } public void testOrdenarReves() { String[] ex={"a", "b", "c", "d", "e"}; Lista expected=new Lista(ex); String[] e3={"e", "d", "c", "b", "a"}; Lista listaAlReves=new Lista(e3); this.assertEquals(expected, listaAlReves.ordenar()); } }
  • 21. JUnit El TestRunnerpublic void testOrdenarReves() { public void testOrdenarNula1() { String[] ex={"a", "b", "c", "d", "e"}; Lista listaNula1=null; Lista expected=new Lista(ex); this.assertNull(listaNula1); } String[] e3={"e", "d", "c", "b", "a"}; Lista listaAlReves=new Lista(e3); public void testOrdenarNula2() { String[] e4=null; this.assertEquals(expected, Lista listaNula2=new Lista(e4); listaAlReves.ordenar()); String[] ex=null; } Lista expected=new Lista(ex); this.assertEquals(expected, public void testOrdenarTodosIguales() { listaNula2.ordenar()); String[] e2={"a", "a", "a", "a", "a"}; } Lista listaTodosIguales=new Lista(e2); public void testOrdenarListaVacia() { String[] ex={"a", "a", "a", "a", "a"}; String[] e5={}; Lista listaVacia=new Lista(e5); Lista expected=new Lista(ex); this.assertEquals(expected, String[] ex={}; listaTodosIguales.ordenar()); Lista expected=new Lista(ex); } this.assertEquals(expected, listaVacia.ordenar()); }
  • 22. JUnitEl TestRunner – Errors vs Failures
  • 23. JUnitEl TestRunner – Test OK
  • 24. JUnitTestRunner - Consideraciones  Es importante notar que todos los métodos test que implementados se están en ListaTester.  Si añadimos, borramos o modificamos el código de Lista, los casos de prueba habidos en ListaTester siguen disponibles y pueden volver a ser ejecutados.  Se aconseja/OBLIGA re-ejecutarlos cada vez que se modifique el código.
  • 25. JUnitPruebas de Excepciones (fail)  Es necesario comprobar el comportamiento en situaciones idóneas, pero se deben probar situaciones en las que se producen errores.  A veces el comportamiento correcto de nuestro programa consisten en se produzca un error → una excepción.
  • 26. JUnit Pruebas de Excepciones (fail)  Por ejemplo, puede ser deseable que ordenar() lance un error cuando la lista esté vacía:public Lista ordenar() throws Exception { if (size()==0) throw new Exception("No se puede ordenar una lista vacía"); ordenar(0, size()-1); return this; }
  • 27. JUnitPruebas de Excepciones (fail) public void testOrdenarNula2() throws Exception { String[] ex=null; Lista expected=new Lista(ex); this.assertEquals(expected, listaNula2.ordenar()); } public void testOrdenarListaVacia() throws Exception { String[] ex={}; Lista expected=new Lista(ex); this.assertEquals(expected, listaVacia.ordenar()); }
  • 28. JUnitPruebas de Excepciones (fail)  Se modificarán los métodos test de la siguiente manera: public void testOrdenarNula2() throws Exception { try { String[] ex=null; Lista expected=new Lista(ex); this.assertEquals(expected, listaNula2.ordenar()); fail("Debería haberse lanzado una excepción"); } catch (Exception e) { // Capturamos la excepción para que el caso no falle } }
  • 29. JUnitRedefinición de método equals  Todas las clases Java extienden de Object y por lo tanto heredan: Llamado por los assertEquals(...) definidos en Assert
  • 30. JUnitRedefinición de método equals  Por tanto, en muchos casos habrá que redefinir el método equals(Object):boolean en la clase que se quiera probar.
  • 31. JUnitEjemplo - equals ¿Cuándo son dos cuentas son iguales? a) Los saldos son los mismos b) Tienen el mismo nº de movimientos c) Opción b y todos son iguales d) ...
  • 32. JUnit Ejemplo - equalspublic void testIngresarYRetirarloTodo() throws Exception { Cuenta expected=new Cuenta("Pepe", "123"); Cuenta obtained=new Cuenta("Macario", "123456"); obtained.ingresar(1000.0); obtained.retirar(1000.0); assertEquals(expected, obtained);}
  • 33. JUnit Ejemplo - equals Si redefinimos equals(Object): booleanpublic void testIngresarYRetirarloTodo() throws Exception modo... en Cuenta de ese { Cuenta expected=new Cuenta("Pepe", "123"); Cuenta obtained=new Cuenta("Macario", "123456"); obtained.ingresar(1000.0); obtained.retirar(1000.0); assertEquals(expected, obtained); }public boolean equals(Object o){ if (!Cuenta.class.isInstance(o)) return false; Cuenta c=(Cuenta) o; return getSaldo()==c.getSaldo());}
  • 34. JUnitOtros métodos assert  assertTrue(boolean) public void testIngresar() { Cuenta obtained=new Cuenta("Pepe", "123"); obtained.ingresar(100.0); obtained.ingresar(200.0); obtained.ingresar(300.0); assertTrue(obtained.getSaldo()==600.0); }  assertNull(Object) public void testNull() { Cuenta c=null; assertNull(c); }
  • 35. JUnitOtros métodos assert  assertSame(Object, Object)/assertNotSame(Object, Object)public void testDiferentesReferencias() throws Exception { Cuenta cuenta1=new Cuenta("Macario", "123456"); cuenta1.ingresar(1000.0); cuenta1.retirar(1000.0); Cuenta cuenta2=new Cuenta("Macario", "123456"); cuenta2.ingresar(1000.0); cuenta2.retirar(1000.0); assertEquals(cuenta1, cuenta2); assertNotSame(cuenta1, cuenta2); }
  • 36. JUnitMock Objects  Basados en JUnit.  Sustituyen a clases complejas, dispositivos, etc.  Ejemplos: servlets, páginas jsp, bases de datos...
  • 37. JUnit Mock Objects - Ejemplopublic class temperature extends HttpServlet{ private static final String CONTENT_TYPE = "text/html"; public void init(ServletConfig config) throws ServletException { super.init(config); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); String str_f=request.getParameter("Fahrenheit"); try { int temp_f=Integer.parseInt(str_f); double temp_c=(temp_f-32)*5/9.0; out.println("Fahrenheit: " + temp_f + ", Celsius: " + temp_c); } catch (NumberFormatException e) { out.println("Invalid temperature: " + str_f); } }}
  • 38. JUnitMock Objects - Ejemploimport com.mockobjects.servlet.*;import junit.framework.Test;import junit.framework.TestCase;import junit.framework.TestSuite;public class TemperatureTester extends TestCase{ public TemperatureTester() { } public void test_bad_parameter() throws Exception { temperature s = new temperature(); MockHttpServletRequest request=new MockHttpServletRequest(); MockHttpServletResponse response=new MockHttpServletResponse(); request.setupAddParameter("Fahrenheit", "boo!"); response.setExpectedContentType("text/html"); s.doGet(request, response); response.verify(); assertTrue(response.getOutputStreamContents().startsWith("Invalid temperature")); }
  • 39. JUnitMock Objects  Difíciles de usar (poca documentación)  Descargas y más información en www.mockobjects.com
  • 40. JUnitConclusiones  Marco de automatización de pruebas.  Automatiza las pruebas de regresión.  Los casos de prueba documentan el propio código fuente.  Adecuado para Desarrollo dirigido por las pruebas.  Extensible (p.ej.: Mock), abierto, gratuito :)
  • 41. Pruebas Unitarias - JUnit FIN Iker Canarias iker.canarias@gmail.com