“gray laptop computer turned on” by Rich Tervet on Unsplash

Fazendo uma aplicação em Vue.js com TDD — Um guia extensivo para quem quer aprender — parte 1

Daniel Kuroski
magnetis backstage
Published in
8 min readOct 10, 2018

--

Afinal, ensinar a montar uma aplicação sem testes é muito fácil

Este é o primeiro de uma série de artigos:

Caso tenha curiosidade, entre diretamente no repositório com o código final:

Caso você decidiu fazer todo o tutorial, vamos lá 🚀

Durante os workshops do VueJS Summit 2018, acabei conversando pessoalmente com o Edd Yerburgh, e mostrei a forma como eu estava testando as minhas aplicações, e depois de um incentivo, cá estou eu escrevendo esse artigo 😅

Espero com ele, mostrar como é fácil testar no front, principalmente, como é fácil testar uma aplicação com Vue.js!

Este tutorial possui muitas imagens e uma certa densidade de conceitos, por isso eu recomendo uma leitura calma caso você não tenha a base das ferramentas.

O que vamos fazer

Nossa aplicação

O projeto será muito simples, vamos fazer uma aplicação que se comunica com a API do Github, buscando um usuário a partir de um username digitado.

Pode parecer um projeto pequeno, mas nele iremos ver vários tipos de testes que encontramos no desenvolvimento de uma aplicação Vue.js, aqui iremos testar:

  • Componentes
  • Vuex
  • Serviços

Vamos aplicar neste projeto a tecnica do TDD!

TDD

Vamos escrever um teste que falhe, então fazer o mínimo de esforço para fazê-lo passar, e finalmente o iremos refatorar caso necessário, repetindo isso até finalizarmos a nossa aplicação.

Uma das vantagens de utilizar esta técnica, é que acabamos tendo feedbacks muito mais rápidos, podendo trabalhar com ciclos muito menores entre as alterações durante o desenvolvimento do nosso projeto.

TDD & Abordagem Tradicional

Aplicar o TDD pode ser difícil no início, pois ele exige uma mudança de mindset, afinal, estamos escrevendo testes antes mesmo de escrever um código de produção.

Quero lembrar aqui que não somos obrigados a seguir a risca tudo do que é proposto, mas para este projeto, eu espero mostrar que isso na realidade pode ser algo simples de ser feito.

Modelando a aplicação

Antes de mais nada, vamos planejar como iremos fazer a nossa aplicação.

Componentes da aplicação

Iremos quebrar ela em apenas 3 componentes:

  • UserView — Componente “inteligente”, responsável por fazer a comunicação com a store e carregar os nossos componentes de apresentação
  • VUserSearchForm — Componente “burro”, responsável por renderizar o formulário, e também resposável por transmitir uma mensagem para o componente pai com o termo de pesquisa
  • VUserProfile — Componente “burro”, responsável por renderizar as informações do nosso usuário pesquisado

Também iremos contar com um serviço para fazer requisições para a API do Github.

API do github para usuários — https://developer.github.com/v3/users/
Pegue o seu café e vamos começar

Baixe o vue-cli e vamos criar o nosso projeto:

npm i -g @vue/cli
vue create tdd-app

Abaixo, estão as features que eu escolhi, selecione o que for mais conveniente para você, ressaltando que irei cobrir testes E2E em um próximo artigo quem sabe.

Opções selecionadas para este projeto
Espere tudo acabar de instalar e estaremos com o nosso projeto pronto para começar

Vamos propor um desafio aqui, só iremos rodar o npm run serve apenas quando finalizarmos a nossa aplicação.

Vamos limpar o projeto

Um projeto pelo Vue CLI acaba trazendo alguns arquivos iniciais, vamos remover tudo o que não precisamos neste primeiro momento.

Remova:

  • src/store.js
  • src/assets/logo.png
  • src/components/HelloWorld.vue
  • src/views/About.vue
  • src/views/Home.vue
  • tests/unit/HelloWorld.spec.js

Limpe o App.vue

<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>

Limpe o router.js

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: []
})

Crie uma pasta para colocar a nossa store:

// src/store/index.jsimport Vue from 'vue'
import Vuex from 'vuex'
import state from '@/store/state'
import mutations from '@/store/mutations'
import actions from '@/store/actions'
Vue.use(Vuex)export default new Vuex.Store({
state,
mutations,
actions,
})

Criamos os arquivos: src/store/state.js src/store/actions.js src/store/mutations.js e todos eles possuem o mesmo trecho de código abaixo:

export default {}

Adicionamos um npm script para observar os nossos testes no package.json

..."test:unit": "vue-cli-service test:unit",
"test:unit:watch": "vue-cli-service test:unit --watchAll"

E finalmente, vamos instalar algumas dependências que iremos usar no projeto.

npm i -d axios
npm i -D flush-promises nock

Criando nosso primeiro teste

Agora podemos começar a criar os nossos testes, vamos começar pelo nosso primeiro componente, o UserView lembrando que estamos utilizando jest como nosso framework de testes.

Este será um componente inteligente, responsável por carregar todos os componentes da tela, e ele fará a comunicação com a store para fazer a busca do usuário do Github.

Vamos criar então o arquivo: tests/unit/UserView.spec.js

describe('UserView', () => {
it('works', () => {})
})

E podemos rodar os testes: npm run test:unit

Nosso primeiro teste

Mas o que exatamente a gente acaba testando nos nossos componentes?

Podemos testar várias coisas nos nossos componentes, mas podemos nos basear nos seguintes tópicos:

Se o componente renderiza

Precisamos garantir que pelo menos o componente está renderizando corretamente.

Se ele renderiza a coisa certa

Se garantimos que o componente renderiza, podemos testar então se ele está renderizando a coisa certa, o nosso componente contem um botão e um input, ou ele contém um botão e um comentário dizendo “Input será implementado na v2”.

Os seus binds

Testamos todos os binds possíveis, o nosso componente está passando as props corretas para os componentes filhos?

Os eventos

Ao clicar em um botão ou receber um determinado evento, o nosso componente está se comportando da forma esperada?

Casos extremos

No caso de uma lista, precisamos garantir como ela irá se comportar com uma lista vazia, com 5 itens, ou 1000 itens.

Agora sim

Sabendo isso, podemos finalmente fazer o nosso teste, vamos ver o primeiro caso, se o nosso componente UserView está renderizando:

UserView.spec.js — WRITE

Estamos usando jest como nosso framework de teste e o vue-test-utils para auxiliar operações com os nossos componentes.

Na linha 7, estamos fazendo um shallowMount do nosso componente, isso quer dizer:

Vamos renderizar apenas o primeiro nível de dependências dele.

Shallow mount renderiza apenas o primeiro nível do nosso componente

O vue-test-utils também disponibiliza um outro método chamado mount, no qual renderizamos a arvore completa de dependências.

Aqui realmente fazemos uma renderização completa de toda a arvore de componentes a partir do componente renderizado

Mas o shallowMount já é o suficiente para o nosso caso.

Na linha 10, estamos pegando o wrapper, que é uma representação do nosso componente, criado pelo vue-test-utils, e então estamos “tirando uma foto” do html do nosso componente, esse método htmlexiste graças ao vue-test-utils.

Ao rodar os testes npm run test:unit temos a nossa primeira falha.

RED

O componente ainda não existe, então chegamos na fase do TDD no qual podemos finalmente criar o nosso arquivo.

Criar — src/views/UserView.vue

Escrevemos aqui uma representação mínima do nosso componente, e graças a isso, temos o nosso primeiro teste passando, rodamos então: npm run test:unit:watch

GREEN

Mas o que raios então é esta snapshot?

Basicamente, o jest tirou uma “foto” do htm do nosso componente, se vermos nos diretórios, foi criada uma pasta __snapshots__ dentro de tests

Nossa primeira snapshot

Agora temos uma referência do nosso componente, e caso tenha qualquer tipo de alteração no html dele, o nosso teste irá falhar.

Faça um experimento, e altere o UserView.vue e veja o teste falhar.

src/views/UserView.vue
Nosso teste falhando pela alteraçao no html

Podemos agora ver que, caso tenha alguma alteração no nosso html, precisaremos corrigir o erro, ou voltar ao estado original.

Caso a alteração seja intencional, podemos atualizar a snapshot, dizendo que esta versão será a nossa nova referência.

Snapshot testing

Para fazer isto, basta apertar u no terminal, e automaticamente a snapshot será atualizada 😄. Para ver mais opções, basta apertar w no terminal, que irá ser trazida uma listagem de opções do jest.

Snapshot atualizada, GREEN
O arquivo de snapshot é atualizado automaticamente

NUNCA mexa no arquivo de snapshot, este arquivo é gerado para você!

Resumo da obra

Resumindo

Neste primeiro artigo, fizemos:

  • A introdução do que iremos fazer
  • O planejamento da nossa aplicação
  • Setup inicial do nosso projeto deixando apenas os arquivos mínimos a serem trabalhados
  • Explicação do que testamos no front
  • Criamos o nosso primeiro teste

Fiquem atentos que próxima semana estaremos nos aprofundando nos testes do nosso componente.

Muito obrigado pela atenção, se gostou, por favor, clique no 💚, e qualquer dúvida, sugestões ou correções sinta-se a vontade para me mandar uma mensagem, eu agradeço muuito 😄.

Meu Twitter: @DKuroski

Vejo você próxima semana 😄

--

--