$30 off During Our Annual Pro Sale. View Details »

Introducción a las pruebas unitarias :: Introduction to Unit Testing

Introducción a las pruebas unitarias :: Introduction to Unit Testing

Fernando Perales

February 27, 2016
Tweet

More Decks by Fernando Perales

Other Decks in Technology

Transcript

  1. Pruebas unitarias

    View Slide

  2. Fernando Perales

    View Slide


  3. View Slide

  4. Ingeniero de Software
    MagmaLabs

    View Slide

  5. Ingeniero de Software
    MagmaLabs
    ¡Hey! Estamos contratando
    careers.magmalabs.io

    View Slide

  6.  Promotor del FLOSS 
    Apasionado del desarrollo web
    Conferencista en formación
    Estudiante de Bajo Eléctrico
    Fan: Heavy metal, cerveza, Twitter, Gregory
    Sallust, Ruby

    View Slide


  7. View Slide

  8. Agenda

    View Slide


  9. Pruebas de software: la manera manual

    ¿Por qué automatizar las pruebas?

    Herramientas para pruebas unitarias
    - junit (Java)
    - minitest (Ruby)
    - phpunit (PHP)

    Codigo heredado (legacy code) y refactorización

    Pruebas y programación orientada a objetos

    Pruebas automatizadas en el flujo de desarrollo profesional

    Desarrollo basado en pruebas (TDD)

    Integración continua

    Otras herramientas

    View Slide

  10. Pruebas de software: la manera manual
    http://www.mycloud.sg/wp-content/uploads/manifying.jpg

    View Slide

  11. Pruebas
    Probar el software es el proceso de revisar que
    la funcionalidad de la aplicación se comporta
    conforme a los requerimientos

    View Slide

  12. Pruebas unitarias
    Las pruebas unitarias son el tipo de prueba que se encargar se
    asegurar el correcto funcionamiento de una entidad (método o clase)
    Las pruebas unitarias son esenciales para toda compañia de
    desarrollo de software ya que ayudan a entregar un software de
    buena calidad a sus clientes

    View Slide

  13. Pruebas unitarias
    Las pruebas unitarias se pueden realizar de
    dos formas: la manera manual o la manera
    automatizada

    View Slide

  14. Pruebas manuales
    Es el proceso de probar el software de manera manual.
    Require de un tester/QA que ejecute el rol de un usuario
    final y que use la mayoría de las funcionalidades de la
    aplicación para asegurar su correcto compotarmiento
    Para asegurar que las pruebas sean completas, el
    tester/QA suele seguir un plan por escrito que lo guía
    mediante una serie de casos de uso importantes

    View Slide

  15. Pruebas automatizadas
    Consisten en el uso de software especial (separado del
    software que se está probando) para controlar la ejecución de
    pruebas y la comparación de las salidas actuales de la
    aplicación con las salidas previstas.
    La automatización de pruebas nos permite ejecutar de manera
    recurrente pruebas repetitivas pero necesarias, o añadir una
    capa de prueba adicional que sería difícil de hacer de manera
    manual

    View Slide

  16. ¿Por qué automatizar las pruebas?
    http://robohub.org/wp-content/uploads/2015/09/A-Robot-Arm-in-Every-Home.jpg

    View Slide

  17. Desventajas de las pruebas
    manuales
    Consumen tiempo y suelen ser tediosas:
    Como los casos de prueba son ejecutados por
    humanos, suelen ser lentas y tediosas de
    realizar

    View Slide

  18. Desventajas de las pruebas
    manuales
    Gran inversión de recursos humanos:
    Como los casos de usos son ejecutados de
    forma manual, se requiere de más testers para
    acelerar la velocidad de las pruebas

    View Slide

  19. Desventajas de las pruebas
    manuales
    Menos confiables:
    Las pruebas manuales suelen ser menos confiables ya
    que las pruebas pueden no ser realizadas con la
    misma precisión en cada ocasión debido a errores
    humanos

    View Slide

  20. Desventajas de las pruebas
    manuales
    No programables:
    No hay programación realizable para realizar
    pruebas sofisticadas que requieren de
    información oculta

    View Slide

  21. Ventajas de las pruebas
    automatizadas
    Los casos de uso automatizados corren
    significativamente más rapido que los
    ejecutados por humanos

    View Slide

  22. Ventajas de las pruebas
    automatizadas
    Inversión menor en recursos humanos:
    Los casos de uso son ejecutados por herramientas
    automatizadas, así que menos testers son
    requeridos para las pruebas automatizadas

    View Slide

  23. Ventajas de las pruebas
    automatizadas
    Más confiables:
    Las pruebas automatizadas se ejecutan de la
    misma manera cada vez que corren

    View Slide

  24. Ventajas de las pruebas
    automatizadas
    Programables:
    Los testers pueden programar casos de uso
    sofisticados

    View Slide

  25. Herramientas para pruebas automatizadas
    https://i.ytimg.com/vi/-6JSmjpwnK8/maxresdefault.jpg

    View Slide

  26. xUnit
    Es una serie de herramientas basadas basadas
    en el framework de pruebas SUnit creado para
    Smalltalk por Kent Beck en 1998

    View Slide

  27. xUnit
    Sunit fue escrito en una estilo fuertemente
    orientado a objetos. SUnit fue despues
    adaptado a Java por Kent Beck y Erich Gamma
    en lo que se le conoce como JUnit

    View Slide

  28. xUnit
    Todas los frameworks de la familia xUnit
    comparten la misma arquitectura básica de
    componentes, con algunas variaciones en los
    detalles de la implementación.

    View Slide

  29. Test runner
    Es el programa ejecutable que corre las
    pruebas implementadas usando un framework
    xUnit y reporta los resultados de las pruebas.

    View Slide

  30. Test case
    Es la clase más elemental. Todos los casos de
    uso heredan de esta prueba

    View Slide

  31. Test fixtures (context)
    Es el conjunto de precondiciones o estados necesarios
    para correr una prueba. El desarrollador debe establecer
    el estado necesario antes de correr las pruebas y regresar
    al estado origin después de haber corrido las pruebas.

    View Slide

  32. Test suites
    Es el conjunto de pruebas que comparten una
    misma precondición. El orden de ejecución de
    estas pruebas no importa

    View Slide

  33. Ejecución de las pruebas
    Es el conjunto de pruebas que comparten una
    misma precondición. El orden de ejecución de
    estas pruebas no importa

    View Slide

  34. Test result formatter
    El runner de pruebas produce los resultados de la
    prueba en uno o más formatos. Adicional a un formato
    legible para los humanos, también se suele generar
    los resultados en XML o JSON

    View Slide

  35. Assertions
    Son las funciones o macros que verifican el resultado o estado de la
    unidad que está siendo probada. Las aserciones suelen expresar una
    condición lógica que es verdadera para los resultados esperados. El
    fallo de dicha aserción suele lanzar una excepción, abortando el resto
    de las pruebas actuales.

    View Slide

  36. http://junit.org/

    View Slide

  37. http://docs.seattlerb.org/minitest/

    View Slide

  38. https://phpunit.de/

    View Slide

  39. Código heredado (legacy code) y refactorización
    https://upload.wikimedia.org/wikipedia/commons/3/38/Papyrus_Bodmer_VIII.jpg

    View Slide

  40. Legacy code
    Es el código fuente relacionado a un sistema que ya
    no tiene soporte. El término fue primeramente
    utilizado por el científico computacional George
    Olivetti para referirse a código mantenido por un
    administrador que no desarrolló el sistema.

    View Slide

  41. Interpretación moderna
    “To me, legacy code is simply code without tests.”
    - Michael Feathers

    View Slide

  42. Refactorizar
    Es el proceso de reestructurar código existente sin
    cambiar su comportamiento externo. Refactorizar es
    mejorar los atributos no funcionales del software.

    View Slide

  43. Refactorizar
    Las ventajas de refactorizar incluyen mejorar la legibilidad del
    código y reducir su complejidad; esto puede mejorar la
    mantenibilidad del código fuente y crear una estructura interna
    más expresiva o el modelado de los objetos para mejorar la
    extensibilidad. Típicamente, al refactorizar se aplican una seria
    de micro-refactorizaciones básicas estandarizadas, cada una de
    ellas es usualmente un pequeño cambio en el código que o
    preserva el comportamiento del software, o al menos no
    modifica su apego a los requerimientos funcionales.

    View Slide

  44. ¿Cómo garantizar que, al trabajar con código
    heredado no rompamos el funcionamiento actual?

    View Slide

  45. ¿Cómo garantizar que, al trabajar con código
    heredado no rompamos el funcionamiento actual?
    R: con pruebas automatizadas

    View Slide

  46. Más información
    Refactoring: Improving the Design of Existing
    Code
    Kent Beck
    Working Effectively with Legacy Code
    Michael Feathers

    View Slide

  47. Pruebas y programación orientada a objetos
    http://blog.teamtreehouse.com/wp-content/uploads/2013/10/photo1.jpg

    View Slide

  48. S.O.L.I.D.

    View Slide

  49. Es un acrónimo mnemónico creado por Michael
    Feathers para referirse a los “cinco principios”
    mencionados por Robert C. Martin. Estas siglas
    significan cada uno de los cinco principios
    básicos para programación y diseño orientado a
    objetos.
    S.O.L.I.D.

    View Slide

  50. Estos principios, cuando se aplican en conjunto,
    hacen más facil que un programador desarrolle
    un sistema que es fácil de mantener y extender a
    lo largo de su vida útil.
    S.O.L.I.D.

    View Slide

  51. S = Single responsibility,
    O = Open-closed
    L = Liskov substitution
    I = Interface segregation
    D = and Dependency inversion
    S.O.L.I.D.

    View Slide

  52. Una clase sólo debe tener una única razón de
    cambio, esto quiere decir que una clase sólo
    debe tener una única responsabilidad.
    Single Responsibility Principle

    View Slide

  53. Los objetos o entidades deben estar abiertos a
    extensión, pero cerrados a modificación.
    Open-closed Principle

    View Slide

  54. Los objetos en un programa deben ser
    reemplazables con instancias de sus subtipos sin
    alterar la exactitud del programa.
    Liskov Substitution Principle

    View Slide

  55. Un cliente no debe ser forzado a implementar una
    interfaz que no usa ni deberian ser forzado a
    depender de métodos que no utilliza.
    A client should never be forced to implement an
    interface that it doesn’t use or clients shouldn’t be
    forced to depend on methods they do not use.
    Interface Segregation Principle

    View Slide

  56. Las entidades deben depender de abstracciones
    y no de implementaciones concretas. Se
    establece que los módulos de alto nivel no deben
    depender de módulos de bajo nivel, pero pueden
    depender de abstracciones.
    Dependency Inversion Principle

    View Slide

  57. Más información
    Growing Object-Oriented Software, Guided By
    Tests
    Steve Freeman
    Head First Object-Oriented Analysis and
    Design
    Brett D. McLaughlin, Gary Pollice y Dave West

    View Slide

  58. Más información
    Practical Object-Oriented Design in Ruby: An
    Agile Primer
    Sandi Metz

    View Slide

  59. View Slide

  60. Pruebas automatizadas en el flujo de

    desarrollo profesional
    https://www.austinfraser.com/wp-content/uploads/2015/09/FSPLFPQBCZ.jpg

    View Slide

  61. Es una metodología de desarrollo que aboga
    por la mejora en la calidad del software y la
    flexibilidad a los cambios de requerimiento por
    parte del cliente. Al ser un tipo de metodología
    Agile, prioritiza lanzamientos frecuentes en
    pequeños periodos de desarrollo con el afán de
    mejorar la productividad e introducir puntos de
    referencia donde es posible agregar o cambiar
    requerimientos
    Programación Extrema (XP)

    View Slide

  62. XP fue concebida por
    Kent Beck entre 1996
    y 1999, año en el que
    lanza el libro Extreme
    Programming
    Explained
    Programación Extrema (XP)

    View Slide

  63. Programación Extrema (XP)
    By DonWells - https://en.wikipedia.org/wiki/File:XP-feedback.gif, CC BY-SA 3.0,
    https://commons.wikimedia.org/w/index.php?curid=27448045

    View Slide

  64. Más información
    Extreme Programming Explained: Embrace
    Change
    Kent Beck

    View Slide

  65. Desarrollo basado en pruebas (TDD)
    http://www.paulkerrison.co.uk/wp-content/uploads/2014/02/06_Red_Green_Refactor.jpg

    View Slide

  66. Test-driven development (TDD) es un proceso
    de desarrollo de software donde el
    desarrollador primero escribe una prueba
    (inicialmente fallida) que define el
    comportamiento de la nueva función, después
    produce el mínimo código necesario para hacer
    que la prueba pase, y finalmente refactoriza el
    nuevo código para que logre los estándares
    acordados

    View Slide

  67. Kent Beck, a quién se le atribuye el desarrollo o
    'redescubrimiento de la técnica', mencionó en
    2003 que TDD propicia el diseño simple e
    inspira confianza en el desarrollo.

    View Slide

  68. El ciclo del TDD

    View Slide

  69. En TDD, cada nueva funcionalidad comienza
    escribiendo una prueba. Para escribir una prueba,
    el programador debe entender las
    especificaciones y requerimientos de la
    funcionalidad. El programador puede lograr esto
    medienta casos de uso e historias de usuario.
    También se puede iniciar modificando una prueba
    ya existente.
    Agregar una prueba

    View Slide

  70. Esto valida que nuestro harnés de pruebas
    funciona correctamente, que la nueva prueba no
    pasa sin requerir código nuevo, y que la
    funcionalidad no exista ya en el sistema. Este
    paso también prueba la prueba por si misma. La
    nueva prueba debe fallar por la razón esperada.
    Correr las pruebas y verificar que la
    nueva falle

    View Slide

  71. El siguiente paso es escribir el código que hace
    que la prueba pase. El nuevo código escrito en
    este paso no es perfecto y puede, por ejemplo,
    pasar la prueba en una manera poco elegante.
    Esto es aceptable ya que se mejorará en el punto
    5.
    Escribir código

    View Slide

  72. Si todas las pruebas pasan, el programador
    puede estar confiado de que el nuevo código
    cumple los requerimientos de la prueba y no
    rompe funcionalidad existente. En caso de que
    algo falle, se sigue ajustando el código.
    Correr las pruebas

    View Slide

  73. El código se debe limpiar de manera regular.
    Hay guías generales y específicas sobre cómo
    refactorizar y cómo crear código limpio.
    Al correr continuamente las pruebas, el
    programador tiene la certeza de que el proceso
    no altera funcionalidad existente.
    Refactorizar el código

    View Slide

  74. Más información
    Test Driven Development: By Example
    Kent Beck

    View Slide

  75. Integración continua
    http://www.globaltacs.com/assets/img/mang.png

    View Slide

  76. Es una práctica de
    desarrollo de software
    propuesta por Grady
    Booch en 1991 y que
    ayuda a prevenir
    problemas de
    integración de código
    en un proyecto con
    varios desarrolladores

    View Slide

  77. http://www.programmingresearch.com/wp-content/uploads/2012/11/jenkins-plugin-diagram-saci.png

    View Slide

  78. Herramientas de C.I.

    View Slide


  79. Los desarrolladores pueden detectar y solucionar
    problemas de integración de forma continua,
    evitando el caos de última hora cuando se
    acercan las fechas de entrega.

    Disponibilidad constante de una versión para
    pruebas, demos o lanzamientos anticipados.

    Ejecución inmediata de las pruebas unitarias.

    Monitorización continua de las métricas de calidad
    del proyecto.
    Ventajas
    https://es.wikipedia.org/wiki/Integraci%C3%B3n_continua

    View Slide

  80. Más información
    Continuous Integration: Improving Software
    Quality and Reducing Risk
    Paul M. Duvall

    View Slide

  81. Otras herramientas
    http://www.globaltacs.com/assets/img/mang.png

    View Slide

  82. ¿Preguntas?

    View Slide

  83. ¡Gracias!
    [email protected]
    Feedback
    http://goo.gl/forms/WjhtvLSHj9

    View Slide