Testing automatizado en React-Native

Luego de 6 meses trabajando a diario con React-Native he logrado hacerme una idea bastante clara sobre esta temática que me parece no está suficientemente bien documentada.

En primer lugar tengamos presente que con React-Native vamos a generar aplicaciones móviles para Android y/o iPhone con lo cual un tipo de prueba automatizada que podremos realizar es directamente sobre el binario nativo que se instala en el dispositivo, serían las denominadas pruebas end-to-end que muchas veces se hacen en forma manual. Su ejecución requiere por un lado del uso de un emulador (o incluso se puede usar un dispositivo físico) y por otro, el uso de algún driver/conector que nos permita interactuar con la aplicación desde la perspectiva del usuario. Como estas pruebas van directamente contra el binario/ejecutable, tenemos independencia para codearlas en un lenguaje distinto al que utilizamos para codear la aplicación. La pieza central en este tipo de pruebas es el driver/componente que nos va a permitir manipular la aplicación emulando la interacción del usuario. En este sentido una de las herramientas más populares es Appium y otra es Detox.

Sacando las pruebas end2end, tenemos distintos tipos de pruebas de índole más técnico, de componentes/unitarios. Estas pruebas sí las estaremos codeando con la misma tecnología que codeamos la aplicación. En el caso de estar trabajando con React Native estas pruebas las vamos a codear con JavaScript. Aquí también entran en juego distintas herramientas. La primera de ellas es el framework de testing que utilizaremos para escribir los casos de prueba y agruparlos en suites. Aquí tenemos varias alternativas (como suele ocurrir habitualmente en JavaScript) pero al trabajar con React se suele utilizar Jest que es la herramienta recomendada en la documentación oficial de React. Jest nos va a permitir escribir casos de prueba sobre objetos/funciones JavaScript, sean estos componentes React o simples objetos planos «vanilla JavaScript». Una «bondad» que tiene Jest es que trae nativamente funcionalidades de mocking/stubbing con lo cual nos ahorramos de tener que incluir en nuestro proyecto otro framework/herramienta para mocking.

Si en nuestras pruebas queremos testear componentes React-Native, en particular el rendering, en primera instancia podemos utilizar el Test Renderer que es parte del core de React. También como parte del core de React tenemos las Test Utils que ofrecen un conjunto muy útil de funciones utilitarias.

También tenemos la posibilidad de utilizar React-Native Testing Library que debemos instalar por separado (yarn add –dev @testing-library/react-native). Esta librería construída sobre la base del Test Renderer y agrega un conjunto de funciones utilitarias de gran utilidad.

Comenzando con React Native

Estamos semana comenzamos a trabajar en la nueva aplicación móvil de Radiocut. A diferencia de la aplicación anterior que estaba construida con Cordova/Ionic, esta vez decidimos utilizar React Native.

Son varias las razones para trabajar con una tecnología de este tipo en lugar de trabajar directamente con tecnología nativa:

  • Somos un equipo chico, generalista y «multi tecnología», trabajar con tecnologías nativas sería demasiado esfuerzo ya que tendríamos que codear y mantener dos aplicaciones completamente distintas (una android y otra ios) en lenguajes distintos, Java/Kotlin y ObjectiveC/Swift ninguno de los cuales forma parte de nuestro stack actual.
  • Las características de la nuestra aplicación no requieren trabajar con tecnología nativa, creemos que casi todas las funcionalidades las podemos implementar sin mayores complicaciones sin tener que tocar código nativo.

Una vez decidido el uso de React Native hay dos cuestiones que debemos definir en forma temprana: el CLI y el lenguaje. El proyecto React Native se crea con una herramienta de línea de comandos (CLI) que genera código y simplifica el bootstrap del proyecto. En este sentido una opción es usar el CLI de React Native pero hay también otra opción: Expo CLI. Importante: ambos CLIs son herramientas JavaScript con lo cual para instalarlos solo necesitamos de Node/NPM.

Expo CLI nos ofrece un bootstrap simplificado, o sea, nos provee un proyecto base que ya cuenta con varias cuestiones «pre-configuradas». Al mismo tiempo no requiere que nos instalemos el tooling para desarrollo nativo (Android SDK/xCode) ya que el build final de nuestra aplicación se hace en el servicio cloud ofrecido por Expo.

Por su parte el CLI de React Native nos provee «menos asistencia», hay más cuestiones que tendremos que manejar nosotros mismos y al mismo tiempo tendremos que instalarnos el tooling para desarrollo nativo.

Comparativamente los puntos que tenemos que considerar para eligir el CLI son:

  • El binario generado por Expo termina típicamente siendo más pesado que el binario que genera el CLI de React Native.
  • Expo CLI nos simplifica muchas cuestiones y nos provee un mayor nivel de abstracción y por su parte el CLI de React Native nos «hace trabajar más» pero nos da un mayor control de la aplicación/código.
  • Al trabajar con Expo CLI dependemos del servicio cloud de Expo para la generación del binario final.

La forma en que estas 3 cuestiones impactan en cada proyecto son particulares de cada proyecto. En nuestro caso decidimos ir por el CLI de React Native.

Una vez elegido el CLI, podemos avanzar con la creación del proyecto y eso lleva a una nueva elección: el lenguaje. Podemos trabajar con TypeScript o JavaScript. En nuestro caso elegimos JavaScript ya estamos acostumbrados a trabajar con lenguajes de tipado dinámico y todo nuestro código client-side ya está escrito en JavaScript puro.

Hasta aquí, nuestros primeros pasos. En siguientes entregas iré compartiendo:

  • Setup de la infra cd CI/CD
  • Manejo de configuración de APP
  • Publicación en los stores

Continuará…