La importancia de UI Testing y Unit Testing

¿Quién necesita hacer testing? “Yo no, mi código es perfecto!”. ¡ERROR!

El testing no solo nos ayuda a eliminar la mayoría de bugs antes si quiera de que el producto sea lanzado al público sino que, lo más importante: nos ayuda a escribir un buen código, modular y correctamente estructurado. Aquel código del cual no resulte fácil hacer testing tampoco va a ser fácil de mantener y/o debuggear. Por tanto no es buen código.

Unit Testing consiste en comprobar el correcto funcionamiento de una pieza de código, generalmente una función. Esto sirve para asegurar que cada unidad funcione correctamente a medida que se desarrolla el producto y se añaden funciones al mismo.

Es de vital importancia diferenciar correctamente entre Unit Test, que tiene como finalidad comprobar el correcto funcionamiento de una pieza de código, y el UI Test que tiene como finalidad comprobar el correcto funcionamiento de todo el código en conjunto para garantizar que el producto se comporta como debiera en la vida real. Es muy importante hacer los dos tipos de Testing, o situaciones como ésta ocurrirían:

Como podemos apreciar, ambas ventanas funcionan perfectamente por separado, pero juntas no. Es por ello que aunque el Unit Test sea satisfactorio, debemos comprobar la integración del código en conjunto.

FIRST

El acrónimo FIRST hace referencia a las buenas prácticas que hay que aplicar a la hora de hacer testing:

  • Fast: los tests deben ejecutarse rápidamente, de forma que no se perderá tiempo en correrlos.
  • Independent: los tests jamás deben tener ningún tipo de interacción entre ellos.
  • Repeatable: se deben obtener los mismos resultados cada vez que se ejecuta el test, es por ello que es casi imperativo no utilizar datos provenientes de terceros al hacer Testing.
  • Self-validating: los tests tienen que ser completamente automatizados, es por ello que el resultado del test ha de ser únicamente “pass” o “fail”, y jamás la interpretación del desarrollador a un log file.
  • Timely: idealmente, los tests han de ser escritos antes de escribir el fragmento de código que van a comprobar.

Siguiendo el principio FIRST conseguirás unos tests limpios, y concisos, en lugar de hacer del testing un obstáculo más en el camino.

Unit Testing en Xcode

En este ejemplo vamos a utilizar Swift para realizar tests unitarios. Es importante que cojas la idea de lo que es un test unitario y no te centres en entender el lenguaje. Para ellos, lo primero que vamos a hacer es crear un proyecto en XCode. Importante por supuesto, marcar las opciones Include Unit Tests y Include UI Tests.

A partir de este momento, cada vez que desarrollemos una aplicación, vamos a adoptar una práctica llamada TDD (Test Driven Development, o Desarrollo Guiado por Tests). Esto implica escribir los tests antes de escribir el código asociado a ese test. Es por ello que para cada archivo .swift que creemos y que sea testado, deberemos crear un archivo de tests de mismo nombre:

Como estamos en TDD, vamos a empezar por crear los tests para el código que irá en el archivo Mates.Swift. Estos test irán en el archivo MatesTests.swift.

import XCTest
@testable import Example

class MatesTests: XCTestCase {

let mates = Mates()

override func setUp() {
  super.setUp()
}

override func tearDown() {
  super.tearDown()
}

func testarSumaYMultiplicacion() {
  let num1 = 2
  let num2 = 4
  let num3 = 6
  let esperado = 36
  let resultado = mates.SumarYMultiplicacion(num1, int2: num2, int3: num3)

  XCTAssert(resultado == esperado)
}
}


Lo primero es importar el XCTest Framework y el project en sí con @testable import NombreProjecto. Esto permite a los Tests buscar las clases que hayan sido declaradas. Luego definimos la clase MatesTests que hereda de XCTestCase. Además declaramos una constante en la cual creamos una instancia de la clase Mates() y declaramos dos funciones incluidas en el XCTest Framework, setUp() y tearDown().

Nuestro Mates.Swift va a tener una función que recibe tres números enteros, suma los dos primeros y el resultado lo multiplica por el tercero. Como estamos haciendo TDD vamos a escribir el test primero:

func testarSumaYMultiplicacion() {
 let num1 = 2
 let num2 = 4
 let num3 = 6
 let esperado = 36
 let resultado = mates.SumarYMultiplicacion(num1, int2: num2, int3: num3)

 XCTAssert(resultado == esperado)
}

Para que la función que acabamos de escribir se ejecute al correr el test, es totalmente imprescindible que el nombre de la función comience por “test”.

Declaramos tres números enteros, el resultado esperado al sumar los dos primeros y el resultado multiplicarlo por el tercero, y llamamos a la función SumarYMultiplicacion de nuestra clase Mates. Posteriormente con XCTassert vamos a comprobar si el valor que retorna el método coincide con lo que nosotros esperamos conseguir. Xcode nos va a lanzar un error informándonos de que no existe tal función en la clase Mates, esto es debido a que estamos en TDD. Vamos a proceder a declararla en Mates.swift.

import Foundation

class Mates {

 func SumarYMultiplicacion(_ int1: Int, int2: Int, int3: Int) -> Int {
   let suma = int1 + int2
   let producto = suma * int3

   return producto
 }
}

Si os habéis dado cuenta, en producto he puesto una división y no una multiplicación. Esto está hecho a propósito para que el test falle.

Vamos a correr el test presionando Comando + U en el Test:

Evidentemente, el test ha fallado. En este momento de desarrollo, nos habríamos dado cuenta de que hay un fallo en la lógica de esta pieza de código que estamos testándolo. Así que podríamos proceder a arreglarlo, y correr el test otra vez:

¡Felicidades! El test ha sido satisfactorio. Ahora podemos continuar implementado funciones en nuestra app (y testándolas, por supuesto), sabiendo que estamos reduciendo enormemente la cantidad de bugs.

Hasta aquí el artículo de hoy, no os perdáis futuras entregas de esta serie, en la que cubriremos Unit Testing en detalle y la introducción a UI Testing.

¡Dejadnos saber en los comentarios que os ha parecido el artículo, así cómo qué opináis de el Testing, y si lo usáis!