Pruebas Unitarias con Vuejs y Mocha

Hola con tod@s, continuamos en el aprendizaje de Vue.js como un framework de JavaScript para front-end, en este caso particular vamos a aprender como hacer pruebas unitarias utilizando el conjunto de herramientas de Vue y Mocha.

Mocha es un framework de pruebas para JavaScript que corre sobre Node.js realizando de esta manera pruebas asíncronas de manera simple.

Para mayor información, revisa https://mochajs.org/

Vamos a empezar un proyecto desde cero utilizando vue-cli, construiremos un componente que será un contador que incremente con un botón y haremos pruebas unitarias sobre ese componente, vamos a ello.

Creando un nuevo proyecto

Como primer paso, vamos a ejecutar vue-cli para crear un nuevo proyecto mediante el siguiente comando:

vue create counter-example

vue-cli nos mostrará una pantalla donde seleccionaremos las características de manera manual:

? Please Pick a Preset
  default (babel, eslint)
> Manually select features

Luego vamos a seleccionar Babel, Router, Vuex, Linter / Formatter y Unit Testing (este último es indispensable):

? Please pick a preset: Manually select features
? Check the features needed for your project:
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
❯◉ Unit Testing
 ◯ E2E Testing

En las siguientes pantallas seleccionamos la configuración que más deseemos tener, sin embargo la más importante para este post será seleccionar el framework de Mocha + Chai para las pruebas unitarias:

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, Linter, Unit
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a linter / formatter config: Basic
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Pick a unit testing solution: 
❯ Mocha + Chai 
  Jest 

De la misma manera, terminaremos de seleccionar la configuración que deseemos en los menús posteriores y finalizaremos la creación de un proyecto por defecto, donde podremos observar los siguientes detalles importantes:

Dentro de todo el árbol de archivos, nos centraremos en los siguientes elementos:

counter-example/
├── src
    ├── components
        └── HelloWorld.vue
    ├── router
        └── index.js
    ├── views
        ├── About.vue
        └── Home.vue
    ├── App.vue
    └── main.js
└── tests
    └── unit
        └── example.spec.js

Allí podremos observar los siguientes detalles:

  • Existe un componente llamado HelloWorld.vue dentro de la carpeta components.
  • Existe una vista llamada Home.vue, desde donde es llamado el componente HelloWorld.vue
  • Existe la prueba unitaria example.spec.js creada por defecto para probar el componente HelloWorld.vue.

    Las pruebas unitarias tienen la denominación: *.spec.js

Componente HelloWorld.vue

El componente HelloWorld.vue es un componente que contiene los elementos que nuestra App nos muestra bajo la ruta (/) gracias a que esta siendo invocado desde la vista Home.vue. Tiene la siguiente presentación:

include-header

Vista Home.vue con los elementos del componente HelloWorld.vue


De la vista anterior, nos centraremos en el título con la leyenda "Wellcome to Your Vue.js App" que es sobre el mismo que Vue.js ha construído una prueba unitaria por defecto. El siguiente código se encuentra en el componente "HelloWorld.vue":

<template>
    <div class="hello">
        <h1>{{ msg }}</h1>
        ...
    </div>
</template>

<script>
export default {
    name: 'HelloWorld',
        props: {
            msg: String
        }
    }
</script>
...

Los props son datos que sirven como parámetros para el componente, estos props son instanciados desde la llamada del componente o desde el mismo componente. En este caso, la vista Home.vue que contiene la llamada al componente anterior, se presenta de la siguiente manera:

<template>
    <div class="home">
        ...
        <HelloWorld msg="Welcome to Your Vue.js App"/>
    </div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
    name: 'Home',
    components: {
        HelloWorld
    }
}
</script>

Prueba unitaria example.spec.js para el componente HelloWorld.vue

Entendiendo esta llamada al componente y el envío de parámetros, vamos a analizar la prueba unitaria creada por defecto que se denomina example.spec.js:

import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
    it('renders props.msg when passed', () => {
        const msg = 'new message'
        const wrapper = shallowMount(HelloWorld, {
            propsData: { msg }
        })
        expect(wrapper.text()).to.include(msg)
    })
})

Vamos a observar los siguientes detalles de la prueba:

  • Se importa expect desde la librería chai que utiliza el framework de Mocha.
  • Se importa shallowMount desde la librería de test-utils para poder generar elementos desde el componente.
  • Se importa el componente a probar, en este caso HelloWorld.vue
  • Se utiliza el método describe que va a operar sobre un módulo del componente. (Para analizar varios módulos se puede incluir varias funciones describe dentro del mismo archivo).
  • Dentro de cada función describe se va a realizar cada prueba unitaria que se desee incluir bajo la función it. (Para realizar varias pruebas unitarias sobre el mismo módulo, se puede incluir varias llamadas a funciones it dentro del mismo describe del módulo).

Esta prueba unitaria crea un nuevo mensaje con la información "new message", monta el componente HelloWorld.vue y finaliza la prueba comparando el texto del componente con el mensaje. De esta manera se puede comprobar si un componente recibe props de manera adecuada.

Para correr la prueba unitaria, nos basta con ejecutar el siguiente comando:

npm run test:unit

El comando finaliza con el resultado de las pruebas realizadas:

 DONE  Compiled successfully in 1061ms
  [=========================] 100% (completed)
 WEBPACK  Compiled successfully in 1061ms

 MOCHA  Testing...

  HelloWorld.vue
    ✓ renders props.msg when passed

  1 passing (23ms)
 MOCHA  Tests completed successfully

Creando el componente Counter.vue

Ahora, vamos a crear nuestro propio componente, su vista y vamos a crear la prueba unitaria de sus módulos. Para ello, vamos a crear un archivo dentro de src/components con el nombre de Counter.vue e incluiremos la siguiente información:

<template>
    <div>
        Counter Value: <span class="counter-value">{{ value }}</span>
        <br/>
        <button class="increase" @click="onIncrease">Increase Counter</button>
    </div>
</template>

<script>
export default {
    props: {
        initialValue: {
            type: Number,
            required: false,
            default: 0
        }
    },
    data () {
        return {
            value: this.initialValue
        }
    },
    computed: {
        stringValue () {
            return this.value.toString()
        }
    },
    methods: {
        onIncrease () {
            this.value += 1
        }
    }
}
</script>

Este componente crea un contador dentro de un props (funcionando como parámetro) para que sea instanciado en la llamada al componente, si la llamada al componente no envía un valor de props, el componente instanciará el valor del contador en cero. De manera adicional, se creó un botón que permite aumentar en 1 el valor del contador:

include-header

Vista Mycounter.vue con los elementos del componente Counter.vue


Pruebas unitarias para el componente Counter.vue

Ahora vamos a crear 3 pruebas unitarias sobre el componente Counter.vue:

  • La primera de ellas instanciará el componente con un valor de props en 24 y probará el correcto funcionamiento del componente.
  • La segunda instanciará el componente sin valor en props y probará que el componente haya instanciado el contador en 0 por defecto.
  • La tercera va a instanciar el contador por defecto y comprobará que el valor del contador sea correcto posterior a un evento del boton.

En este sentido la prueba se detalla a continuación:

import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'

describe('Counter.vue', () => {
    it('the props value provided will be 24', () => {
        const wrapper = shallowMount(Counter, {
            propsData: { initialValue: 24 }
        })
        expect(wrapper.text()).to.include('Counter Value: 24')
    })
    it('the default value will be used in props', () => {
        const wrapper = shallowMount(Counter, {
            propsData: { }
        })
        expect(wrapper.text()).to.include('Counter Value: 0')
    })
    it('Increase counter click event', () => {
        const wrapper = shallowMount(Counter, {
            propsData: { }
        })
        const button = wrapper.find('.increase')
        button.trigger('click')
        expect(wrapper.vm.value).to.equal(1)
    })
})

Observamos que se utlizó describe para el módulo Counter.vue y dentro del mismo se crearon las pruebas unitarias descritas.

De la misma forma, vamos a ejecutar las pruebas unitarias con el comando npm run test:unit que nos mostrará el siguiente resultado:

 DONE  Compiled successfully in 1903ms
  [=========================] 100% (completed)
 WEBPACK  Compiled successfully in 1903ms

 MOCHA  Testing...

  Counter.vue
    ✓ the props value provided will be 24
    ✓ the default value will be used in props
    ✓ Increase counter click event

  HelloWorld.vue
    ✓ renders props.msg when passed

  4 passing (40ms)
 MOCHA  Tests completed successfully

De esta manera, hemos realizado pruebas unitarias usando Mocha test framework en Vue.js, no te olvides que puedes revisar el código fuente en el enlace a continuación.

Código fuente: https://github.com/nano-bytes/vuejs/tree/master/counter-example.

Hasta una próxima entrega.

You may also like...