Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Workshop iOS 3: Testing, protocolos y extensiones

488 views

Published on

http://www.visual-engin.com/blog/testing-protocolos-y-extensiones-ios-workshop/

Workshop Testing, protocolos y extensiones:
- Objetivos
- Requisitios
- Protocols
- Configurar proyecto en xcode
- Tests unitarios
- Integración continua
- Material de interés

Presentado por ingenieros Alberto Irurueta y Alejandro García

Published in: Technology
  • Login to see the comments

  • Be the first to like this

Workshop iOS 3: Testing, protocolos y extensiones

  1. 1. 5. Testing, protocols & extensions ÍNDICE 5. Testing, protocols & extensions...............................................................................1 Objetivos ..................................................................................................................2 1. Requisitos.............................................................................................................2 2. Protocols...............................................................................................................2 2.1. ¿Qué son?..............................................................................................................2 2.2. Propósito ...............................................................................................................2 3. Configurar Proyecto en Xcode..............................................................................3 3.1. Código ...................................................................................................................6 3.2. Documentación de código .......................................................................................8 4. Tests unitarios ....................................................................................................11 4.1. Código del test .....................................................................................................13 4.2. Ejecutar los tests desde Xcode ..............................................................................14 4.3. Cobertura de código desde Xcode..........................................................................14 4.4. Ejecutar los tests desde línea de comando .............................................................17 4.3. Cobertura de código desde línea de comando.........................................................18 5. Integración continua..........................................................................................20 5.1. Configuración de Travis-CI ....................................................................................21 5.2. Configuración de Coveralls con Travis-CI................................................................25 5.3. Publicación de informes en github-pages................................................................30 5.4. Configuración de Jenkins.......................................................................................47 Material de interés .................................................................................................48
  2. 2. Objetivos  Entender el funcionamiento de los protocolos  Aprender a crear tests unitarios  Generar informes de resultados de tests y de cobertura de código  Integración continua (Travis vs. Jenkins) 1. Requisitos En este workshop se usarán las siguientes herramientas:  Github: deberéis tener cuenta propia para poder crearos un repositorio público en el que configurar la integración continua  Travis CI: servicio de integración continua en el cloud  Coveralls: servicio para mostrar informes de cobertura de código en el cloud  Slather: librería para generar informes de cobertura  Jazzy: utilidad para generar documentación  xcpretty: utilidad para generar informes de tests 2. Protocols 2.1. ¿Qué son? Los protocolos son una manera de definir una serie de métodos, constructores, etc. que debe tener una clase o estructura, pero sin llegar a implementarlos. Están relacionados con el concepto de herencia múltiple en otros lenguajes como C++, y son similares al concepto de interface en otros lenguajes como C# o Java. Se suelen utilizar para abstraer determinadas partes del código para que pueda ser extendida en un futuro (como veremos en el ejemplo) y su uso es muy habitual para implementar delegates (que veremos en siguientes workshops, aunque los delegates siguen una filosofía similar a los listeners en Java). Sintaxis: <modifier> protocol ProtocolName : <Extended protocol> { func someMethod() func anotherMethodWithParameters(param1: Int, param2: Int) } 2.2. Propósito En este workshop implementaremos una función de medida de distancia de edición, o también conocida como distancia de Levenstein https://es.wikipedia.org/wiki/Distancia_de_Levenshtein La distancia de edición, es algo que se suele utilizar para comparar textos (palabras), cuando no son exactamente iguales.
  3. 3. La distancia de edición indica la cantidad de caracteres que es necesario añadir, eliminar, mover o reemplazar para que dos textos sean iguales. Su uso es habitual en buscadores de texto (como Google), ya que cuando se realiza una búsqueda es posible que el usuario cometa errores tipográficos o que el texto no coincida exactamente con lo que hay indexado en la base de datos, pero sea muy similar. A grandes rasgos, uno de las algoritmos que se usa en este tipo de herramientas es este (entre muchas otra más cosas que no detallaremos aquí). Aunque el uso habitual de la distancia de edición es para la comparación de Strings, en realidad el algoritmo permite comparar colecciones de cosas (en este caso un string es una colección de caracteres), por lo que en el workshop implementaremos el algoritmo mediante protocolos para que así pueda ser utilizado para comparar más cosas a parte de strings de texto. Finalmente extenderemos la clase String para que implemente el protocolo que hemos creado y de este modo poderla utilizar con EditDistance utilizando la siguiente sintaxis: extension <Class> : <Protocol> { func method() { } } Donde <Class> es la clase que queremos extender, y en este caso (aunque no es obligatorio) además implementamos un Protocolo. En la extensión de la clase añadimos el método method(). 3. Configurar Proyecto en Xcode A continuación se describen los pasos a seguir para configurar el proyecto en Xcode tal y como está en el repositorio. El resultado debería ser el mismo que lo que hay en la rama init del repositorio. 1. Abrir Xcode y seleccionar la opción para crear un proyecto nuevo. Escoger la opción de framework de cocoa touch.
  4. 4. 2. Asignar un nombre al proyecto, la cuenta de desarrollo y la ubicación donde se guardará el proyecto
  5. 5. 3. Guardar el proyecto 4. Al guardar el proyecto, Xcode nos genera una estructura inicial del proyecto con un test unitario de ejemplo (el cual sustituiremos). A continuación se muestra el aspecto general del proyecto tras su creación.
  6. 6. 3.1. Código A continuación se proporciona el código para implementar la distancia de edición:
  7. 7. 3.2. Documentación de código En el ejemplo de código puede verse que las clases, métodos y variables miembro pueden documentarse siguiendo una nomenclatura especial. Xcode detecta los bloques de código del tipo /** .. */ o que empiecen por tres barras /// y los trata de forma especial considerándolos como comentarios de documentación. La documentación se escribe en formato markdown, por lo que resulta sencillo escribir títulos con la sintaxis #título#, negrita como **negrita**, *cursiva*, etc. Además, como puede verse, la documentación admite ciertas palabras clave para documentar parámetros y valores retornados. Estos bloques de texto son tratados de forma especial por Xcode de modo que al hacer alt + click sobre una variable, tipo o método, nos mostrará la documentación sobre éste en un popup.
  8. 8. Del mismo modo, también puede verse esta misma documentación en el Quick Help inspector en el panel de la derecha. También es posible generar documentación en formato web para tenerla como referencia y colgarla en un servidor (igual que la documentación de Apple). Para ello puede utilizarse una herramienta como Jazzy. Para instalar Jazzy: Para ejecutar Jazzy: jazzy --clean --author Alberto Irurueta --github_url https://github.com/albertoirurueta/swift-protocols-and-generics-workshop -- xcodebuild-arguments - project,./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj,- scheme,swiftProtocolsAndGenerics --module swiftProtocolsAndGenerics --output docs
  9. 9. Nótese que se proporcionan argumentos de xcodebuild para especificar la ruta del archivo de proyecto y el esquema a documentar. En los argumentos proporcionados, los espacios que normalmente se proporcionarían en el comando de xcodebuild deben sustituirse por comas. xcodebuild es una herramienta de línea de comando que permite realizar tareas como compilación, ejecución de tests, archivado, generación de ipa's, etc desde línea de comando, por lo que será de gran utilidad para automatizar tareas en el servidor de integración. Una vez ejecutada esta línea de comando, tendremos en la carpeta docs una página web con toda la documentación del proyecto.
  10. 10. 4. Tests unitarios A continuación se describen los pasos a seguir para crear tests unitarios 1. Pulsar con el botón derecho sobre el grupo de tests (carpeta amarilla de tests en el project navigator). 2. Seleccionar nuevo archivo y escoger la opción de nuevo test unitario (no confundir con la opción de tests de UI) 3. Asignar un nombre al archivo y un lenguaje de programación
  11. 11. 4. Aseguraos de que el check del archivo de tests está asociado al target de tests y no al del framework, ya que de lo contrario estaríais incluyendo el archivo en la librería.
  12. 12. 4.1. Código del test A continuación se proporcionan tests unitarios de la distancia de edición. Nótese que al comparar con un array de strings, se escoje el string que más separece (el que tiene menor distancia de edición).
  13. 13. 4.2. Ejecutar los tests desde Xcode Para ejecutar los tests, en el panel izquierdo de Xcode seleccionamos el Test navigator. Desde el test navigator podremos seleccionar qué tests ejecutar. Tras la ejecución de los tests se mostrarán unas marcas que indican si se ejecutaron correctamente o no, tal y como se muestra a continuación. 4.3. Cobertura de código desde Xcode La cobertura de código nos permite saber realmente qué partes del código se han ejercitado con la ejecución de los tests y que partes aún no han sido testeadas.
  14. 14. A medida que un proyecto crece es importante ver de un vistazo qué áreas están testeadas y cuáles faltan por testear. Del mismo modo, a medida que un proyecto crece es interesante tener un servidor que ejecute todos los tests por nosotros y nos ofrezca informes de cobertura y de tests de forma automatizada para poder hacer un mejor seguimiento de la calidad del código de un proyecto, ya que normalmente en el desarrollo normal el desarrollador no tendrá que ejecutar todos los tests en su máquina, sólo aquellos que sean relevantes para la parte del código que esté desarrollando. El resto de tests los ejecutará el servidor de integración Por defecto Xcode deshabilita la cobertura de código, ya que al ejecutar los tests con la cobertura de código habilitada hay una pequeña penalización de rendimiento (la cual no tiene importancia a menos que realmente se esté midiendo el rendimiento con el profiler). Para poder obtener informes de cobertura, tanto en local como en el servidor, es necesario habilitar la cobertura de código en el esquema del proyecto. Para ello deben seguirse los siguientes pasos: 1. En el selector de esquemas, editar el esquema 2. En la opción de test activar la opción de recolección de datos de cobertura (Gather coverage data). Más adelante también veremos que activamos la opción "shared"
  15. 15. Una vez activada la recolección de datos de cobertura, si volvemos a ejecutar los tests, veremos en el Report Navigator del panel de la izquierda un resumen de los tests que han pasado y los que no, así como información de resumen de la cobertura de código. El informe de tests y de cobertura es interactivo y nos permite ir a las líneas de código específicas haciendo click sobre la flechita que aparece al pasar el cursor del mouse por un elemento del informe.
  16. 16. En el caso del informe de cobertura, si ahora regresamos al archivo de código (o hacemos click en la flechita desde el propio informe), veremos que aparecen resaltadas las líneas de código que se han ejecutado en el test y las que quedan por testear. 4.4. Ejecutar los tests desde línea de comando Tal y como hemos comentado al ejecutar Jazzy, Xcode ofrece una utilidad de línea de comando (xcodebuild) que permite realizar tareas como la ejecución de tests desde línea de comando. Esto como veremos resultará de utilidad para ejecutar los tests en un servidor de integración continua (Jenkins o Travis). Los tests pueden ejecutarse con la siguiente línea de comando: xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES En esta línea de comando se indica que primero se haga un clean de proyecto y a continuación se ejecuten los tests. Se proporciona la ubicación del proyecto, el esquema a ejecutar y el dispositivo en el que se ejecutarán. Se utilizará la configuración de debug con la cobertura de código activada. La ejecución de este comando inicia el simulador de iOS indicado, donde se ejecutarán todos los tests. Una vez finalizado, el simulador se cierra. Aunque xcodebuild nos muestra el resultado de la ejecución de los tests en la consola, puede ser de utilidad generar un informe más visual donde podamos ver qué tests fallan y donde. Para ello podemos utilizar xcpretty Para instalar xcpretty debemos ejecutar:
  17. 17. A continuación deberemos ejecutar xcodebuild pero haciendo un pipe de su salida mediante xcpretty: xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES | xcpretty Veremos que el resultado por consola ahora es más visual. Podemos guardar la salida original de consola de xcodebuild haciendo un pipe con la utilidad tee, de modo que el comando sería: xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES | tee xcodebuild.log | xcpretty Finalmente, podemos generar un informe en formato Junit (que es de utilidad en Jenkins) mediante el comando: xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES | tee xcodebuild.log | xcpretty -r junit El informe se almacena en build/reports/junit.xml Por otro lado, si lo preferís, podéis generar un informe en formato web, sustituyendo junit por html en el comando anterior xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES | tee xcodebuild.log | xcpretty -r html 4.3. Cobertura de código desde línea de comando Tras ejecutar los tests en un terminal, es posible generar un informe de cobertura desde línea de comandos mediante Slather. Slather es una utilidad que podemos instalar y permite transformar los datos de cobertura obtenidos a un formato que sea legible (formato xml para el plugin de Cobertura en Jenkins, formato para coveralls o bien formato html para generar el informe en formato web).
  18. 18. Para instalar Slather, debe ejecutarse la siguiente línea de comando: http://buegling.com/blog/2015/4/26/building-nokogiri-on-os-x. sudo gem install nokogiri -v 1.6.3.1 -- --with-iconv-dir=`xcode-select - p`/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr --with-xml2- include=`xcode-select - p`/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/libxml 2 Una vez tengamos slather instalado, podemos obtener el informe de cobertura siguiendo estos pasos: 1. Abrir una ventana de terminal 2. Ejecutar en la ventana de terminal los tests por línea de comando tal y como hemos visto 3. Ejecutar slather del siguiente modo: /usr/local/bin/slather coverage --html --scheme swiftProtocolsAndGenerics ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj Tras la ejecución, en la carpeta html tendremos el informe en formato html
  19. 19. En la web oficial de slather hay más información para generar el informe en otros formatos (Cobertura, el cual utilizaremos con Jenkins y Coveralls, el cual utilizaremos con Travis). 5. Integración continua Aunque la configuración de los tests y la cobertura sólo necesario realizarla una sola vez, puede ser tedioso tener que ejecutar manualmente los tests y generar manualmente el informe e cobertura cada vez que se hace un cambio en el código. Por otro lado, a medida que un proyecto crece, puede ser incómodo ejecutar todos los tests del proyecto cada vez que se hace un commit en el repositorio, ya que la ejecución de todos los tests puede tomar demasiado tiempo. En estos casos un servidor de integración continua puede ser de utilidad para automatizar la ejecución de todos los tests, generación de informes o artefactos compilados cada vez que se haga un push en el repositorio. De modo que el desarrollador sólo tiene que preocuparse de desarrollar y testear su parte del código y el servidor se encarga de comprobar que la contribución de un desarrollador en un equipo de trabajo (mediante un push o pull request) es correcta mediante la ejecución de todos los tests. Todo esto sin interrumpir el flujo de trabajo del desarrollador. En este workshop veremos dos servicios de integración continua:  Travis-CI: travis CI es un servicio de integración continua en el cloud que se integra con github de modo que cada vez que se hace un push en el repositorio realiza las tareas que se le indiquen. Travis-CI es gratuito para proyectos open source en github.  Jenkins: es un servidor open source de integración continua. En visual disponemos de http://jenkins.oficina.visual-engin.com
  20. 20. 5.1. Configuración de Travis-CI Para utilizar travis, es necesario configurar vuestra cuenta de github para proporcionarle acceso a travis. Para ello en la página de github, id a vuestra cuenta y entrad en la sección de integraciones: Os aparecerán un montón de servicios que pueden integrarse con github. Seleccionad travis (más adelante también configuraremos coveralls).
  21. 21. Seleccionar el botón verde (a mí me aparece configure porque ya lo tengo añadido en github). Otorgamos los permisos necesarios a Travis para acceder a nuestra cuenta de github Tras otorgar permisos a Travis para acceder a github, debemos añadir el repositorio que nos interesa a travis. Desde la pantalla principal de Travis, pulsamos en el botón + al lado de "My repositories" o sobre el nombre de nuestra cuenta.
  22. 22. Desde la pantalla de nuestra cuenta, pulsamos en el botón de sincronización para refrescar la lista de repositorios que hay en nuestra cuenta de github, y a continuación activamos el repositorio que nos interese. A partir de este momento, travis escuchará el repositorio indicado para iniciar la ejecución de los tests cada vez que se suban cambios al repositorio. Sólo falta indicarle a travis qué es lo que debe ejecutar.
  23. 23. Para configurar travis es necesario definir el archivo .travis.yml en la raíz del repositorio. .travis.yml language: objective-c osx_image: xcode8.1 script: - xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES En el archivo indicamos que vamos a utilizar como lenguaje de programación objective-c (aunque también sirve para Swift). Especificamos que deseamos una imagen de sistema operativo con xcode8.1, y a continuación indicamos la línea de comando que deseamos ejecutar para pasar los tests. Finalmente, para que travis tenga acceso al esquema del proyecto que le hemos indicado mediante línea de comando, debemos asegurarnos que el esquema esté marcado como "shared" en Xcode. Para ello debemos editar el esquema y asegurarnos que el check "shared" esté activado 5.5.1. Archivo Readme y badges Github por defecto nos crea un archivo README.md en el que podemos escribir documentación del proyecto en formato markdown. Esta información es la que aparece en la página web de github y puede utilizarse para poner documentación, intrucciones de uso, etc. En el caso de travis (y también sucede igual con Coveralls y otros servicios), podemos además añadir un badge que nos indique en todo momento el estado de los testa del proyecto (si pasan o fallan), para que así de un vistazo podamos saber en todo momento el estado del proyecto.
  24. 24. Para ello debemos hacer click en el badge del proyecto en la web de travis (que inicialmente tiene estado unknown) y copiar la URL del badge en formato markdown. Modificamos o creamos el archivo README.md en la raíz del repositorio y añadimos el código markdown que hemos copiado. # swift-protocols-and-generics-workshop Workshop for Swift protocols &amp; generics [![Build Status](https://travis-ci.org/albertoirurueta/swift-protocols-and- generics-workshop.svg?branch=master)](https://travis- ci.org/albertoirurueta/swift-protocols-and-generics-workshop) A partir de ahora en la web de github aparecerá el badge de estado de compilación. Lo podéis comprobar en: https://github.com/albertoirurueta/swift-protocols-and-generics-workshop En cuanto realicemos un push en la rama master del repositorio, Travis pondrá nuestro push en cola hasta que haya una máquina disponible para iniciar la ejecución de los tests. Podemos comprobar desde la web de travis el estado de la ejecución, la consola de terminal con los comandos que se han ejecutado, y desde la web de github veremos el estado de la compilación y ejecución de los tests. 5.2. Configuración de Coveralls con Travis-CI Del mismo modo que hemos hecho con travis, desde la web de Github, accedemos a integraciones en nuestra cuenta y añadimos la integración con Coveralls. Una vez concedido el acceso a nuestra cuenta de Github, en la web de coveralls, vamos a la sección de repositorios
  25. 25. Sincronizamos los repositorios, y activamos el acceso al repositorio de interés. Para generar el informe de cobertura en Coveralls, necesitaremos convertir los datos de cobertura generados por xcodebuild a un formato que entienda coveralls, para ello utilizaremos Slather. Para utilizar Slather, modificaremos el archivo .travis.yml para instalar slather en la máquina y ejecutarlo tras la ejecución de los tests
  26. 26. .travis.yml language: objective-c osx_image: xcode8.1 before_install: - gem install slather --no-ri --no-rdoc script: - xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES - slather A continuación, debemos crear un archivo .slather.yml para que slather sepa la configuración que debe utilizar para enviar los datos de cobertura a coveralls .slather.yml input_format: profdata coverage_service: coveralls xcodeproj: ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj scheme: swiftProtocolsAndGenerics Finalmente, modificaremos el archivo README.md para añadir un badge con información sobre la cobertura. La URL del badge de coveralls puede obtenerse en la propia web de coveralls, pulsando sobre el botón embed al lado del icono del badge y copiando la URL de markdown en nuestro archivo README.md
  27. 27. Por lo que el archivo README.md quedaría como se muestra a continuación: README.md # swift-protocols-and-generics-workshop Workshop for Swift protocols &amp; generics [![Build Status](https://travis-ci.org/albertoirurueta/swift-protocols-and- generics-workshop.svg?branch=master)](https://travis- ci.org/albertoirurueta/swift-protocols-and-generics-workshop) [![Coverage Status](https://coveralls.io/repos/github/albertoirurueta/swift- protocols-and-generics- workshop/badge.svg?branch=master)](https://coveralls.io/github/albertoirurueta /swift-protocols-and-generics-workshop?branch=master) Ahora sólo es necesario realizar un push, y automáticamente Travis ejecutará los tests y enviará la información de cobertura a Coveralls, y podremos acceder a ambos desde nuestra página de github.
  28. 28. 5.3. Publicación de informes en github-pages Tal y como hemos visto en local, podemos generar informes de documentación, cobertura, tests en formato HTML. Sin embargo sería conveniente tener disponibles dichos informes directamente en la página web de nuestro proyecto. Por suerte, github permite publicar páginas web estáticas en la rama gh-pages, de modo que todo lo que se suba a esa rama aparecerá en la web de github.
  29. 29. En la siguientes secciones veremos cómo podemos hacer que travis genere los informes y a continuación los suba a github pages para así tenerlos disponibles en la web de nuestro repositorio. 5.3.1. Configuración para publicar automáticamente en github-pages desde Travis Para poder utilizar github-pages deberemos poder hacer pushes en la rama gh-pages desde Travis, utilizando pasos similares a los indicados aquí: https://gist.github.com/domenic/ec8b0fc8ab45f39403dd. Para ello deberemos dar acceso a nuestro repositorio a Travis, lo cual implica proporcionar un usuario y contraseña o una clave SSH. Por seguridad, y más teniendo en cuenta que es un repositorio open source público, utilizaremos una funcionalidad de travis para almacenar la clave de forma segura en el repositorio. Primero necesitaremos crear una clave SSH. En la documentación de github se indica cómo hacerlo: https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ Los pasos a seguir son los siguientes: 1. Crear una clave SSH en local. Utilizaremos el mismo correo electrónico de nuestra cuenta de github al crear la clave. Indicamos la ubicación donde guardar la clave (puede usarse la ubicación por defecto) y es importante no asignarle contraseña, ya que de lo contrario el comando ssh-add que ejecutará Travis requeriría introducirla manualmente. Este comando creará un archivo de clave privada y uno de clave pública. No es necesario añadir la clave al agente SSH tal y como indica la documentación de Github ya que no la usaremos en local para conectarnos a Github, si no que será Travis el que lo hará, por lo que el comando ssh-add lo ejecutará Travis.
  30. 30. 2. Añadir en la web de Github la clave pública generada para tener acceso. Cuidado, la clave debe añadirse únicamente al repositorio que queremos dar acceso, no a nuestra cuenta, ya que entonces daríamos acceso a Travis todos los respositorios. Para ello vamos a los settings del repositorio. En la sección de opciones veremos que más abajo hay la opción para activar github-pages e incluso un editor online de las páginas. Nos aseguramos de que se usa la rama gh-pages o bien usamos la herramienta de generación de una página de inicio mediante el botón Launch automatic page generator.
  31. 31. 3. Vamos a la sección de claves y pulsamos en el botón para añadir una clave. 4. Asignamos un nombre que identifique a la clave, le proporcionamos acceso de escritura, copiamos el contenido de la clave pública y la añadimos
  32. 32. 5. Veremos una confirmación conforme la clave se ha añadido.
  33. 33. 6. Copiamos los archivos de claves pública y privada en el repositorio si no lo habíamos hecho ya (ojo, no hacer commit aún ya que primero hay que encriptar la clave privada). 7. Comprobamos que ruby está instalado (por defecto en macOS ya viene instalado) 8. Instalamos el cliente de Travis (https://github.com/travis-ci/travis.rb) ejecutando el siguiente comando. Podemos comprobar que travis se ha instalado ejecutando el comando: 9. Desde la carpeta donde está la clave privada dentro del repositorio (el archivo github_key) encriptamos la clave privada con el siguiente comando: Si es la primera vez que ejecutamos Travis en el repositorio, travis nos lo indicará y nos preguntará si es correcto. Travis nos devolverá el comando que es necesario para desencriptar el archivo .enc generado. Debemos anotarlo ya que lo necesitaremos más adelante.
  34. 34. openssl aes-256-cbc -K $encrypted_0d0cc787d66b_key -iv $encrypted_0d0cc787d66b_iv -in github_key.enc -out github_key -d 10. Veremos que se ha creado el archivo github_key.enc que contiene el archivo github_key pero encriptado, por lo que podemos borrar el archivo github_key original, ya que únicamente subiremos al repositorio en archivo github_key.enc. 11. Modificamos el archivo .travis.yml para añadir variables de entorno con los valores para desencriptar la clave privada, y añadimos el comando ./publish-gh-pages.sh para ejecutar un script que crearemos para publicar en github-pages .travis.yml language: objective-c osx_image: xcode8.1 env: global: - ENCRYPTION_LABEL: "0d0cc787d66b" - COMMIT_AUTHOR_EMAIL: "alberto@irurueta.com" before_install: - gem install slather --no-ri --no-rdoc script: - xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES - slather - ./publish-gh-pages.sh
  35. 35. https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables 12. Creamos el archivo de script publish-gh-pages.sh
  36. 36. 13. Otorgamos permisos de ejecución al archivo de script que hemos creado, de lo contrario Travis no podrá ejecutarlo 1. Creamos un token de acceso en la cuenta de github, para ello vamos a settings pulsando sobre la imagen de nuestra cuenta.
  37. 37. 2. Seleccionamos la opción de Personal access tokens y pulsamos el botón de generar un nuevo token. Asignamos un nombre al token y los permisos que le queremos dar (sólo de acceso a los repositorios) 3. Copiamos el token devuelto por github, ya que no lo podremos consultar más adelante.
  38. 38. Desde el directorio del repositorio ejecutamos por línea de comando lo siguiente: Este comando se encarga de generar un string encriptado mediante travis. Este string lo podemos luego poner como una variable de entorno en el archivo .travis.yml, para ello debemos copiar la respuesta de este comando en el archivo .travis.yml, tal y como se muestra a continuación: .travis.yml
  39. 39. language: objective-c osx_image: xcode8.1 env: global: - secure: "l7sVCVmEoGW+NMQkx6F7XFM7HXVhrmDGE5mwqHNy2qZ/zkOOFvhh2/fbxiCDsW 6D4cGUuoiwtp+aL5I7x/R2RfLU4KEDnuk+Nu8OwEXKpdXlNKCt/sbjokrJieuhyufHFpD6d2 fGKU0ekczoOns9Vvl0Sa8MILaffEsW8R8cEMYC6jReb0d9el/CfFb/4N9R2gEK5zXi9v2z48 AvOZrjogCBoJNmVup8gtSTjbnJWo431FSlF8dlFS7bhemn/cKBfLEvyK4bhlLogYgGAwH5OE p1LcwEWzGIKQ9nv8Ithr89DoG2YG48/n+vD2fpRaThuBjnHFmLvaTwGj0GWcGjrk+xkrkch0 tfqnO2sGpDM+B/ApZvom/CC71kSCvYWnFW5fRcXsXF6atvwbgP7iKlw/Ju66WewF7wANgyK3 hguhDy2RSUgUTYDvMuH8KpxmI6FcciN0GB0fHsxG9mf2laGNzLFzqO329RmXKHkxdV1wD/FO S3498z9XyDulu/AvWdU73tvOEgPeqCTwEXkV8tP5bEqxfvfauioWTxFuwo6kjHUjPqvqOAE4 zSFB/k9XdHfV8OSJyfNh0+MoHWFBspHhqIErX3JnlFhfPvJhyJyWBJU2ViX8/WOCEkrog+Hm Z/Sal5mUz8eRraqVVn4IFq1t8oP48ZOkAjM3am+8uuQpM=" - ENCRYPTION_LABEL: "0d0cc787d66b" - COMMIT_AUTHOR_EMAIL: alberto@irurueta.com before_install: - gem install slather --no-ri --no-rdoc - gem install jazzy --no-ri --no-rdoc - gem install xcpretty --no-ri --no-rdoc script: - set -o pipefail && xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug - enableCodeCoverage=YES | tee xcodebuild.log | xcpretty -r html - ./publish-gh-pages.sh after_success: - cd $TRAVIS_BUILD_DIR && slather Una vez hecho este cambio tendremos acceso a la variable de entorno GITHUB_OAUTH_TOKEN desencriptada sin necesidad de subir el token de forma pública a nuestro repositorio A continuación, cambiamos la última línea del script publish-gh-pages.sh para realizar el push mediante https utilizando un usuario con acceso al repositorio (no copiar el que hay aquí) y el token desencriptado en la variable de entorno GITHUB_OAUTH_TOKEN como contraseña.
  40. 40. Con estos pasos ya estaría todo configurado para que Travis subiera los informes que indiquemos en la función doStuff en gihub-pages 5.3.1. Publicación de informes de documentación de Jazzy en github-pages Ya hemos visto cómo generar informes web de documentación mediante Jazzy, ahora vamos a modificar la función doStuff en el archivo publish-gh-pages para que Travis los genere y los publique en github-pages.
  41. 41. Puesto que utilizamos jazzy, también tendremos que modificar el archivo .travis.yml para indicarle a travis que debe instalar jazzy
  42. 42. .travis.yml language: objective-c osx_image: xcode8.1 env: global: - secure: "l7sVCVmEoGW+NMQkx6F7XFM7HXVhrmDGE5mwqHNy2qZ/zkOOFvhh2/fbxiCDsW6D4cGUu oiwtp+aL5I7x/R2RfLU4KEDnuk+Nu8OwEXKpdXlNKCt/sbjokrJieuhyufHFpD6d2fGKU0ekczoOns 9Vvl0Sa8MILaffEsW8R8cEMYC6jReb0d9el/CfFb/4N9R2gEK5zXi9v2z48AvOZrjogCBoJNmVup8g tSTjbnJWo431FSlF8dlFS7bhemn/cKBfLEvyK4bhlLogYgGAwH5OEp1LcwEWzGIKQ9nv8Ithr89DoG 2YG48/n+vD2fpRaThuBjnHFmLvaTwGj0GWcGjrk+xkrkch0tfqnO2sGpDM+B/ApZvom/CC71kSCvYW nFW5fRcXsXF6atvwbgP7iKlw/Ju66WewF7wANgyK3hguhDy2RSUgUTYDvMuH8KpxmI6FcciN0GB0fH sxG9mf2laGNzLFzqO329RmXKHkxdV1wD/FOS3498z9XyDulu/AvWdU73tvOEgPeqCTwEXkV8tP5bEq xfvfauioWTxFuwo6kjHUjPqvqOAE4zSFB/k9XdHfV8OSJyfNh0+MoHWFBspHhqIErX3JnlFhfPvJhy JyWBJU2ViX8/WOCEkrog+HmZ/Sal5mUz8eRraqVVn4IFq1t8oP48ZOkAjM3am+8uuQpM=" - ENCRYPTION_LABEL: "0d0cc787d66b" - COMMIT_AUTHOR_EMAIL: "alberto@irurueta.com" before_install: - gem install slather --no-ri --no-rdoc - gem install jazzy --no-ri --no-rdoc script: - xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES - slather - ./publish-gh-pages.sh Hacemos push y ahora Travis podrá generar el informe de documentación y publicarlo en la carpeta docs de la rama gh-pages 5.3.2. Publicación de informes de tests de xcpretty en github-pages Del mismo modo, tal y como hemos visto, podemos modificar doStuff en el archivo publish-gh- pages para que Travis nos publique el informe de xcpretty en github-pages. Para ello debemos modificar el archivo .travis.yml para que en lugar de ejecutar xcodebuild directamente, haga un pipe con xcpretty tal y como hemos visto. Para poder utilizar xcpretty le tendremos que decir a Travis que primero lo instale. Además, para que el estado de build sea el correcto, tal y como se indica en la documentación de xcpretty añadiendo set -o pipefail && antes del comando xcodebuild en el archivo .travis.yml, tal. Puesto que se usa pipefail, ahora será necesario ejecutar slather por separado tras finalizar el script correctamente, haciendo primero cd al directorio de compilación de Travis
  43. 43. .travis.yml language: objective-c osx_image: xcode8.1 env: global: - secure: "l7sVCVmEoGW+NMQkx6F7XFM7HXVhrmDGE5mwqHNy2qZ/zkOOFvhh2/fbxiCDsW6D4cGUu oiwtp+aL5I7x/R2RfLU4KEDnuk+Nu8OwEXKpdXlNKCt/sbjokrJieuhyufHFpD6d2fGKU0ekczoOns 9Vvl0Sa8MILaffEsW8R8cEMYC6jReb0d9el/CfFb/4N9R2gEK5zXi9v2z48AvOZrjogCBoJNmVup8g tSTjbnJWo431FSlF8dlFS7bhemn/cKBfLEvyK4bhlLogYgGAwH5OEp1LcwEWzGIKQ9nv8Ithr89DoG 2YG48/n+vD2fpRaThuBjnHFmLvaTwGj0GWcGjrk+xkrkch0tfqnO2sGpDM+B/ApZvom/CC71kSCvYW nFW5fRcXsXF6atvwbgP7iKlw/Ju66WewF7wANgyK3hguhDy2RSUgUTYDvMuH8KpxmI6FcciN0GB0fH sxG9mf2laGNzLFzqO329RmXKHkxdV1wD/FOS3498z9XyDulu/AvWdU73tvOEgPeqCTwEXkV8tP5bEq xfvfauioWTxFuwo6kjHUjPqvqOAE4zSFB/k9XdHfV8OSJyfNh0+MoHWFBspHhqIErX3JnlFhfPvJhy JyWBJU2ViX8/WOCEkrog+HmZ/Sal5mUz8eRraqVVn4IFq1t8oP48ZOkAjM3am+8uuQpM=" - ENCRYPTION_LABEL: "0d0cc787d66b" - COMMIT_AUTHOR_EMAIL: "alberto@irurueta.com" before_install: - gem install slather --no-ri --no-rdoc - gem install jazzy --no-ri --no-rdoc - gem install xcpretty --no-ri --no-rdoc script: - set -o pipefail && xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES | tee xcodebuild.log | xcpretty -r html - ./publish-gh-pages.sh after_success: - cd $TRAVIS_BUILD_DIR && slather Puesto que xcpretty guarda el resultado del informe en la carpeta build/reports, y el arcivo de script publish-gh-pages.sh publica todo lo que hay en la carpeta out a github-pages, deberemos modificar el archivo de script para mover el contenido de build/reports dentro de la carpeta out, de este modo:
  44. 44. Ahora, tras realizar el push tendremos el informe de tests subido a github-pages. 5.3.3. Enlazar los informes de github-pages. Aunque hemos creado los informes y los hemos publicado en github-pages, no los podemos ver de forma cómoda porque no hay un enlace para verlos, para ello podemos modificar el archivo index.html de github-pages o bien el archivo README.md para colocar un enlace a los informes. README.md # swift-protocols-and-generics-workshop Workshop for Swift protocols &amp; generics [![Build Status](https://travis-ci.org/albertoirurueta/swift-protocols-and- generics-workshop.svg?branch=master)](https://travis- ci.org/albertoirurueta/swift-protocols-and-generics-workshop) [![Coverage Status](https://coveralls.io/repos/github/albertoirurueta/swift- protocols-and-generics- workshop/badge.svg?branch=master)](https://coveralls.io/github/albertoirurueta /swift-protocols-and-generics-workshop?branch=master) [Code Documentation](https://albertoirurueta.github.io/swift-protocols-and- generics-workshop/docs/index.html) [Test report](https://albertoirurueta.github.io/swift-protocols-and-generics- workshop/build/reports/tests.html) [Github pages](https://albertoirurueta.github.io/swift-protocols-and-generics- workshop/)
  45. 45. 5.4. Configuración de Jenkins Hasta ahora hemos visto cómo configurar un servicio de integración continua en el cloud mediante Travis, el cual se integra con Github y es gratuito para proyectos opensource. Para proyectos privados esto no es una solución viable, (a no ser que tengamos cuentas de pago en Github y Travis), pero es posible montar un servidor Jenkins para hacer exactamente lo mismo. En Visual tenemos nuestro servidor Jenkins (http://jenkins.oficina.visual-engin.com). Jenkins no es más que un servidor capaz de ejecutar scripts de forma programada (cada cierto intervalo de tiempo o cuando hay un cambio en el repositorio) y de forma distribuida (ya que puede ejecutar las tareas en nodos esclavos). Jenkins es muy modular y configurable, y para ellos es posible instalarle una infinidad de plugins. En nuestro caso necesitaremos los siguientes plugins (algunos ya vienen instalados por defecto):  SCM y GIT para obtener datos del repositorio  Junit: para analizar el archivo junit.xml generado por xcpretty con los resultados de los tests  Cobertura: para analizar el archivo xml de cobertura generado por slather  Publicación HTML: para publicar informes HTML Para configurar el proyecto, los pasos a seguir son los siguientes: 1. Añadimos una tarea nueva con un proyecto de estilo libre. 2. Asignamos un nombre al proyecto. 3. Para no hace un uso excesivo de disco duro activamos desechar ejecuciones antiguas y ponemos un número razonable de ejecuciones a mantener en disco (ej: 4) 4. Si el repositorio es github, podemos activar la casilla y poner la URL al repositorio. Esto nos permitirá ir a la web del repo en github 5. Activar la casilla restringir donde se puede ejecutar el proyecto e indicad una máquina de un nodo que esté previamente configurado en Jenkins. 6. En origen de fuente, seleccionamos git, introducimos la URL del repositorio e indicamos la rama de la cual queremos obtener el código. 7. En disparadores de ejecuciones, podemos activar las casillas para detectar un cambio en bitbucket o github, pero para que funcionen el servidor jenkins ha de ser accesible públicamente (no es el caso en Visual), por lo que podemos activar la casilla para comprobar el repositorio periódicamente (por ejemplo para comprobarlo cada 15 minutos debemos introducir H/15 * * * *) 8. Es conveniente activar la casilla para detener la ejecución si se atasca. Esto es útil para que Jenkins no deje el esclavo bloqueado indefinidamente en el caso de que algo falle (los tests peten, se cierre el simulador, etc). De este modo, si no hay actividad por consola en un determinado tiempo (ej: 5 minutos = 300 segundos), se detiene la ejecución. 9. En la sección de ejecutar, añadir un paso para ejecutar la linea de comandos (shell) y poner los siguientes comandos de shell:
  46. 46. #ejecutar tests con informe en ./build/reports/junit.xml xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES | tee xcodebuild.log | /usr/local/bin/xcpretty -r junit #generar documentación en ./docs/index.html /usr/local/bin/jazzy --clean --author Alberto Irurueta --github_url https://github.com/albertoirurueta/swift-protocols-and-generics-workshop -- xcodebuild-arguments - project,./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj,- scheme,swiftProtocolsAndGenerics --module swiftProtocolsAndGenerics --output docs #generar informe de cobertura /usr/local/bin/slather coverage --cobertura-xml --output-directory ./coverage -- scheme swiftProtocolsAndGenerics ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj /usr/local/bin/slather coverage --html --scheme swiftProtocolsAndGenerics ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj 10. En la sección de acciones para después, añadir: a) Publicar informes de "cobertura". El archivo estará ubicado en: coverage/cobertura.xml b) Publicar los resultados de test de Junit. El archivo estará ubicado en: build/reports/junit.xml c) Publish HTML reports. i. Informe de documentación de código. Directorio: docs Index page(s): index.html Report title: Code Documentation ii. Informe HTML de cobertura Directorio: html Index page(s): index.html Report title: Coverage Material de interés Página oficial de Swift: https://swift.org (aquí encontraréis toda la documentación oficial de Swift y el libro oficial en formato ebook en la sección de documentación donde encontraréis información sobre Protocols). Documentar código Swift: http://www.appcoda.com/swift-markdown/ Publicar documentación en github: http://www.jessesquires.com/swift-documentation/ Testing y cobertura de código en Xcode: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/ testing_with_xcode/chapters/07-code_coverage.html Configurar Travis: https://www.raywenderlich.com/109418/travis-ci-tutorial Instalar slather: https://github.com/SlatherOrg/slather
  47. 47. Generar informes web de los tests: https://github.com/fastlane/fastlane/tree/master/scan Github pages: https://pages.github.com Publicar de forma automática en Github-pages con Travis: https://gist.github.com/domenic/ec8b0fc8ab45f39403dd Integración continua y cobertura con Jenkins: https://pspdfkit.com/blog/2016/continuous-ios- code-coverage-with-jenkins-and-slather/ Generar ipa's en Travis y distribuirlos con Testflight o HockeyApp: https://www.objc.io/issues/6- build-tools/travis-ci/ NOTA: Aunque en este workshop no lo hemos visto, también es posible utilizar cocoapods con Travis, para ello habría que descomentar las líneas comentadas mediante # en el siguiente archivo de travis, y modificar la llamada de xcodebuild para que se utilice un workspace en lugar de un proyecto language: objective-c osx_image: xcode8.1 #cache: cocoapods before_install: #- gem install cocoapods --no-ri --no-rdoc - gem install slather --no-ri --no-rdoc script: - xcodebuild clean test -project ./swiftProtocolsAndGenerics/swiftProtocolsAndGenerics.xcodeproj -scheme swiftProtocolsAndGenerics -destination 'platform=iOS Simulator,name=iPhone 7' TEST_AFTER_BUILD=YES -configuration Debug -enableCodeCoverage=YES - slather

×