Sobre testes
Antes de mais nada, por que React ?
Bom, eu gosto de usar React e tive essa idéia ao tentar aprender a combinação React Testing Library e Jest. Qualquer linguagem ou framework irá servir para o meu propósito que é justamente como sair do zero com testes em um projeto simples. Quero justamente criar o que me falta na minha limitação, que é o elo entre o abstrato e a escrita inicial. Caso dê certo, aquela paralisia inicial e o famoso tutorial-hell serão reduzidos em futuros projetos e acho que é isso que falta em muitas pessoas que começam a programar…
E outra coisa: O Javascript precisa de um runtime para ser testado facilmente.
É até possível testá-lo sem de forma pura, mas só é recomendado em casos específicos. O básico é realmente o uso do runtime mais famoso do universo js, o Node.
Vamos manter as coisas simples certo ?
Por que testar ?
Testar não serve só pra ver se funciona, ou para impressionar a chefia ! Os testes possuem alguns objetivos diretos e te ajuda em alguns conceitos que você utilizará agora ou no futuro. Alguns desses conceitos são:
- Testar o comportamento do programa: se ele está funcionando como o esperado
- Atomizar o programa: quanto menor for o trecho independente de um código, mais fácil ele fica de ser analisado. Os testes ajudam nesse tipo de organização.
- Trazer “confidência” para o código: se você sabe como o seu trecho de código deve funcionar e os testes garantem o funcionamento, logo você pode alterar o código diversas vezes com a confiança que se tiver algum erro ele será detectado
- Testar situações limites: “O que acontece se eu colocar 10 espaços vazios no meu username ? E se eu colocar um script nesse campo ? E se eu colocar um valor negativo no campo qtd ?” Esses são alguns exemplos de situações limites que podem existir no seu código.
- Automatização e reusabilidade: Se os testes são um roteiro de como o meu programa deve funcionar, logo eu posso repassar essa tarefa para uma ferramenta automática fazer esta tarefa pra mim. Isso ajuda a reduzir o famoso teste “Xouveraqui” e é quase uma benção quando se trata de formulários a serem preenchidos.
- Prototipagem: Vamos pegar o bom e velho to-do: vamos supor que você tenha um conjunto de testes para um to-do em Jest. Este framework é compatível com praticamente todo o ecossistema Javascript, logo você pode fazer o to-do funcionar em React, Vue, Agular, Svelte, etc. E digo mais ! Você pode adaptar essa “solução” para o PHP-unit ou o Capybara e criar o programa em PHP ou Ruby on Rails. E DIGO MAIS !!! Os testes ainda podem ser expandidos para testes visuais e/ou de preenchimento automático e fazer com que a sua solução tenha a mesma aparência rotina de execução em qualquer plataforma !!! Antes de morrer talvez eu faça isso…
Tudo isso pode ser feito com o auxílio de testes. Porém nem todo mundo gosta de testar códigos, principalmente quando a janela de execução é curta ou o trabalho específico não é bom. mas no geral um código testado, mesmo que não nasça melhor, pode se tornar melhor. Já um código sem testes pode se tornar “imexível” com o tempo.
O que testar ?
Atenção ! Não existe uma regra que impõe o que deva ser testado em uma aplicação e, apesar do senso comum definir que tudo deva ser testado, a “lei geral da criação” (feito é melhor que perfeito) que se aplica ao mundo real nos leva a um caminho próximo ao do listado abaixo:
- Recursos de alto valor: Se o seu programa é um app de vendas, A coisa mais importante para ele é efetuar uma venda ! Isso deve ser construído e testado antes de qualquer outra característica. Um app de notícias precisa atualizar em tempo real. Um de música precisa garantir a reprodução de áudio. E assim por diante. Geralmente são utilizados testes unitários E de integração, mas podem haver outros tipos também.
- Situações limites de recursos de alto valor: O que acontece se a compra for cancelada ? o que acontece se a notícia for atualizada no momento do acesso ? O que acontece se uma pessoa quiser a transcrição da letra da música que está tocando ? Enfim, considerando o mais importante no seu programa, você pode se desdobrar em maiores detalhes para garantir que tudo está conforme o necessário.
- Recursos problemáticos: A carne de pescoço do programa. Uma situação clássica é o acesso à uma API externa, que pode ou não estar funcionando. Eventos de toque ou de movimento que os ajustes são bem complexos também. Alguns detestam formulários que de fato, são tretosos. Esses cenários estão fora do eixo essencial para o sistema (não dá prejuízo imediato) mas podem trazer contratempos ao seu produto. Alguns especialistas recomendam um tipo de teste chamado teste de fumaça para detectar erros de difícil detecção. Fica a dica caso precise se aprofundar no tema de testes.
- Funcionamento básico: o resto. Aliás, muitas pessoas criticam os testes de algo que é garantido pela lógica, e de fato estão certos. Porém as vezes o seu programa tem um comportamento que se desvia da norma: ex: um app de vendas não tem numero negativo no campo de quantidade, logo o que você vai fazer quando “bater no zero” ? desativar o botão “de menos”, disparar uma mensagem ou fazer o zero aparecer constantemente ? Por isso uma forma de definir os testes unitários é definir um teste chamado teste de comportamento (behavior test driven ou BDD)
- testes comportamentais: podem ser definidos no chamado teste A/B, é um teste onde dois tipos de ambientes são mostrados ao seus usuários e o que obter melhor resultado acaba sendo absorvido pelo sistema. Geralmente envolve a parte de apresentação (aparência) do sistema para definir o que é mais agradável para (a cobaia) o usuário. Geralmente são necessários quando seu produto já possui um tráfego de visitantes, senão não faz muito sentido. Por isso é uma última análise de teste. Mas está longe de ser ignorada e faz a diferença quando aplicada em produtos que já possuem mercado.
Como testar ?
O padrão mais utilizado para escrita em testes é conhecido como AAA (Arrange, Act and Assert – arranjar, atuar e afirmar em tradução livre) que definem as três partes que um teste deve ter para ser compreensível e eficaz. Na verdade é bem simples, veja:
- Arrange (arranjar/organizar): Basicamente é a preparação do que o teste precisa. Entenda que não é preparação de todo o ambiente de teste mas de um teste em sí. O exemplo prático é carregar o componente a ser testado, mesmo que nem tenha nada escrito nele. Ou criar um mock, que é uma simulação de algo que o seu componente precisa (ex: resposta de api). Dessa forma o seu teste vai ter o que precisa para funcionar corretamente naquele trecho.
- Act(Atuar/agir): A ação do teste,ou seja, o que o teste faz. Exemplos: com o componente “arranjado”, você vai testar se aparece a palavra “Descontão” quando ele carrega, logo você só precisa carregar o componente. Agora você precisa testar se ao clicar na palavra “Descontão” um novo preço deve aparecer ao lado do antigo e em verde, também deve aparecer um botão escrito “Eu quero!”. Agora você tem que carregar o componente e simular um clique. E assim por diante.
- Assert (afirmar/aferir): é justamente avaliar a igualdade ou diferença da sua ação. Exemplos: A palavra “Descontão” apareceu ? Não apareceu a mensagem “teste de componente” ? Enfim, O seu resultado esperado para definir se trecho de código está correto
Basicamente você cria o cenário e avalia a entrada e a saída, mas mesmo parecendo óbvio, essa é a maneira mais produtiva de se fazer testes.
Dito isto, vamos ao que contém a criação básica de um projeto.
Sobre projetos
Antes de começar eu vou tentar usar conceitos que são úteis tanto para o desenvolvimento tradicional, quanto para o auto proclamado ágil:
Atores e histórias !
Em desenvolvimento de softwares existe o conceito do ator, que é, basicamente, um objeto que representa quem acessa uma interface do seu programa. Não chega a ser necessariamente uma pessoa, mas quase sempre é uma, quando não, geralmente é um serviço ou equipamento que dependa da ação de uma pessoa. Existe uma gigantesca teoria por traz desse conceito, mas você não precisa saber tudo isso antes de começar, até porque tanto esse conceito como o próximo, têm que ser administrado por uma equipe em qualquer cenário profissional, a não ser que você esteja trabalhando sozinho, como nesse caso.
Requisitos funcionais (e não-funcionais)
Requisitos funcionais e não-funcionais, são conceitos que tangem os recursos e características necessários para a subsistência do seu projeto, ou seja, o que precisa pra existir e ser o “SEU” projeto.
Requisitos funcionais geralmente são características técnicas do seu sistema(linguagem, banco de dados, comportamento do sistema), e não-funcionais remetem a características que são auxiliares ao seu sistema (Custo, precificação, confiabilidade, estruturas de armazenamento, etc)
Definição de Requisitos é um dos pináculos do desenvolvimento de software, e não vou me meter a ensinar ninguém sobre isso, vamos ficar no básico e ir para a parte prática que é a construção do roteiro por meio do “caminho feliz” (YAY !!!)
Roteiro – conceito
Eis aí o que eu espero ser o divisor de águas em nossas vidas (amém !!!)
A construção de um roteiro é essencial, pois o seu lado “humano” vai permanecer com as bases que terão de ser executadas pelo seu lado “programador” e isso irá ajudar a reduzir a névoa de pensamentos que geralmente nos ataca ao começar um projeto. Lembrando que isso não irá definir se o seu projeto será bom ou ruim, mas irá garantir que você comece “DO ZERO” até a conclusão de um produto minimamente viável (Minimal Viable Product – MVP).
O ideal na construção de um roteiro é ser o mais objetivo possível porém mantendo todos os itens necessários para que o que será feito seja claro, específico e realista. Evite ser Linkediano nesse momento, seu projeto não faz o cliente ter uma experiência única e irrepetível a cada acesso, ele baixa a porra de um PDF ! Ou uma piada em inglês no nosso caso. Defina o seu objetivo, ações e pronto.
Quantos e Quais atores possui: Usuário (sem especificar) é quase um termo genérico, evite. Se não precisa de autenticação, então é um visitante, se precisa são usuários autorizados e não autorizados. Se tem dashboards, então tem usuários administrativos. Assinatura: assinantes e por aí vai…
Eis aí os seus atores, e deles vão surgir o que é preciso para que existam dados, interfaces, rotas de navegação, funcionalidades, etc.
Requisitos funcionais: Vai usar React? PHP? Postgres? Lê QR? Têm IA? Python?
Você que sabe ! Diz ai….
Requisitos não funcionais: O código estará hospedado em plataforma open source? Necessidade de precificação? Disponibilidade? Servidor próprio ou de terceiros?
etc…
E com todos esses conceitos contidos em um texto que serve mais como guia do que como documento você, provavelmente, conseguirá desenvolver melhor a sua criação ou discutir sobre ela com maior clareza.
Conclusão
Se você leu até este ponto deve ter percebido que algumas características tanto do desenvolvimento quanto dos testes são bem semelhantes. Ao saber isso você acaba solucionando uma etapa em cada processo sem muito custo mental (cansaço).
Tú já é 2x e nem começamos !!!
Ah uma questão também que sempre os iniciantes vão sofrer é sobre como codar, e pra isso geralmente eu uso um “Toolbelt” de códigos, que basicamente é uma coleção de snippets para problemas comuns. Eles já podem vir com testes e prontos para uso futuro (porque choras Github Copilot ?)
Mas isso é pra outra hora….
A próxima parte irá continuar focando nessa preparação, que neste caso é mais importante que o código em sí, porque serve de guia para futuros projetos maiores (espero)
Até a próxima !