Voltar para os posts
Como testar os seus componentes no Vue
30/05/2021
Introduçao
Esse tutorial tem como objetivo ajudar as pessoas que ainda não tem nenhum conhecimento sobre testes unitários e querem entender o básico para testar componentes isolados, vamos abordar alguns assuntos como testes de prop, de eventos e slots.
The more effort I put into testing the product conceptually at the start of the process, the less I effort I had to put into manually testing the product at the end because less bugs would emerge as a result.
-- Trish Khoo
Essa frase resumi o porquê de eu começar a fazer testes, já trabalhei em alguns projetos e comecei a ter o sentimento de que eu perdia mais tempo testando manualmente a aplicação do que realmente desenvolvendo alguma coisa nova, resolvendo um bug ou refatorando o código.
Dessa forma eu resolvi procurar algum tipo de solução de testes para o front-end, me esbarrei com a biblioteca Vue Test Utils que auxilia os testes com componentes do Vue, usando como base o Jest.
Pré-requisitos
Antes de você começar a fazer algo, você precisa:
- Do Node e Npm (ou Yarn) instalados na sua máquina
- Do Vue CLI instalada na sua máquina
- De algum conhecimento prévio com Vue
- De algum conhecimento prévio com Jest
1º Passo - Criação do projeto
Nesse post, utilizaremos como base o projeto default do Vue CLI, pra criar vá para o terminal e escolha o que contém apenas o Babel e o ESlint, com isso você já vai ter todos os arquivos necessários do Vue.
Para mais informações sobre a criação de projetos, clique aqui.
Para vê o resultado final clique aqui.
2º Passo - Instalação das depêndencias
Para começar, existem algumas formas de instalar o Vue Test Utils, tanto na hora de você criar o seu projeto
usando o vue create nome_do_projeto
, como também instalando manualmente, seguindo o passo a passo do próprio site,
aqui eu vou mostrar a segunda opção:
vue add unit-jest
npm install --save-dev @vue/test-utils
Com isso feito, você irá notar que houveram algumas modificações no seu projeto, no caso foram adicionados algumas depêndencias de desenvolvimento e um script para rodar os testes:
"scripts": {
...
"test:unit": "vue-cli-service test:unit",
...
},
"devDependencies": {
...
"@vue/cli-plugin-unit-jest": "~4.5.0",
"@vue/test-utils": "^1.2.0",
},
Também foi criado um arquivo jest.config.js
e um arquivo example.spec.js
no caminho test/unit/
.
3º Passo - Utilização
você agora pode rodar o seguinte comando no terminal para visualizar todos os testes da sua apliacação:
npm run test:unit
Resultado:
4º Passo - Explicando alguns conceitos
O mundo de testes é bem grande e contém vários conceitos, eu provavelmente não vou conseguir explicar todos esses conceitos, mas você sempre pode olhar a documentação oficial e tirar suas próprias conclusões.
Com isso em mente, vou descrever alguns conceitos importantes:
- ShallowMount
É um método que serve para renderização de componentes, porém ele não renderiza as depêndencias desse arquivo,
um exemplo disso, seria um componente com vários filhos. Esse método ajuda a Stubar
automaticamente os componentes,
deve ser usado principalmente em componentes soltos.
O primeiro argumento esperado é o componente e o segundo argumento que é opcional é um objeto de opções que você pode ver cliquando aqui.
- Mount
Também é um método que é basicamente o oposto do ShallowMount, é usado para renderizar o componente e não se preocupa se ele contém muitas depêndencias, deve ser usado em páginas com muitos elementos em uma apliacação real.
O primeiro argumento esperado é o componente e o segundo argumento que é opcional é um objeto de opções que você pode ver cliquando aqui.
- Wrapper
É o nome utilizado para a convenção de um componente, ou seja, você pode criar um componente X e no teste, você irá ter um wrapper desse componente, contendo várias propriedades e métodos para auxiliar a execução e validação do teste.
Para saber mais clique aqui.
5º Passo - Testando props com um componente simples
Para utilizar como exemplo, eu criei um componente Botao.vue
que ficou assim:
<template>
<button :disabled="desativado" @click="acaoClique">
<slot>
{{ texto }}
</slot>
</button>
</template>
<script>
export default {
props: {
texto: {
type: String
},
desativado: {
type: Boolean
}
},
methods: {
acaoClique() {
this.$emit('click');
}
}
}
</script>
Eu também criei um arquivo de teste chamado botao.spec.js
e adicionei o primeiro teste:
import {
shallowMount
} from '@vue/test-utils'
import Botao from '@/components/Botao.vue'
describe('Testando props', () => {
it('Deve renderizar o botão com o texto passado', () => {
const texto = 'Texto do botão';
const wrapper = shallowMount(Botao, {
propsData: {
texto
}
});
expect(wrapper.text()).toMatch(texto);
})
})
Resultado:
Como vimos, o teste foi um sucesso. No código podemos ver que a estrutura é idêntica com a do Jest.
Com a utilização do método shallowMount
citado no quarto passo, a gente usa o segundo parâmetro do método, passando então
a propriedade propsData
, no qual espera receber alguma prop do componente.
Criamos o wrapper contendo as informações do componente, e utilizando o método text()
recuperamos o valor
do primeiro elemento do componente, no final, comparamos o dado retornado com a variável que a gente utilizou para
o teste, validando assim o teste.
6º Passo - Testando eventos com um componente simples
Nesse passo, veremos como testar a emissão de eventos em um componente, utilizaremos o componente do passo anterior:
... omitindo código anterior
describe('Testando eventos', () => {
it('Deve emitir o evento de clique quando houver clique no botao', () => {
const wrapper = shallowMount(Botao);
wrapper.trigger("click");
expect(wrapper.emitted().click).toBeTruthy();
})
})
Resultado:
Vamos analisar o código: novamente usamos o shallowMount para a criação do nosso wrapper, logo em seguida, usamos
o método trigger
para forçar uma emissão de evento em algum elemento do DOM.
Nesse caso, ele força o botão que existe no componente, se você quiser forçar algum emissão customizada deverá usar
wrapper.vm.$emit('evento-customizado')
.
Logo em seguida, usamos a função emitted()
, que retorna um objeto onde as chaves são os eventos e cada campo, contém
uma array de array de valores que foram emitidos, podemos ver um exemplo retirado da documentação:
{
foo: [[ ], [123]]
}
Com isso, verificamos se a chave click
é truthy, validando
então o teste escrito.
7º Passo - Testando slots com um componente simples
Nessa última parte vamos testar o slot:
... omitindo código anterior
describe('Testando slots', () => {
it('Deve renderizar o texto que é passado no slot default', () => {
const textoSlot = "Texto do slot";
const wrapper = shallowMount(Botao, {
slots: {
default: textoSlot
}
})
expect(wrapper.text()).toBe(textoSlot);
})
})
Resultado:
Continuamos usando o shallowMount
e dessa vez usamos a propriedade slots que aceita um objeto onde cada chave é o nome
do slot, nesse caso usamos a chave default
para indicar que a gente quer usar o slot padrão do componente.
Depois disso nós utilizamos a mesma maneira de validar o texto que a gente enviou.
Passo Extra - Alguns pontos de atenção
Em alguns momentos na hora de escrever os testes, nos vemos em situações aonde não sabemos o porquê de o teste não funcionar, com isso em mente vou tentar indicar alguns aspectos que podem ser os culpados.
- Ação assíncrona
Em algums momentos você pode se deparar com uma ação que altera algum valor do DOM, sendo assim, você deverá usar o método
nextTick()
para que seja aguardada a alteração do valor, clique aqui
para ler mais sobre.
- Mount vs ShallowMount
Na maioria dos casos, o shallowMount()
será a melhor opção, mas por um acaso você estiver testando algum tela com muitos
componentes e ações diversas, o mount()
servirá melhor, clique aqui
para entender um pouco melhor.
- Mocks e Stubs
Mocks e Stubs são muito usados em componentes que contém algum tipo de ação externa, seja alguma lib do Vue, como o Vuex ou até mesmo o Axios. Para ler sobre Stubs clique aqui e para ler sobre mocks, clique aqui.
Conclusão
Com o artigo chegando ao fim conseguimos observar alguns aspectos interessantes sobre os testes, nesse texto eu me propus a escrever sobre os tipos de testes mais básicos e simples, no entanto existem alguns cenários que eu acabei não conseguindo escrever sobre, porém no futuro eu pretendo escrever mais sobre esses casos que vão de ações assíncronas até testar depêndencias externas.