<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ricardo Silva</title>
    <description>The latest articles on Forem by Ricardo Silva (@ricardobsilva).</description>
    <link>https://forem.com/ricardobsilva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F985686%2F2e91b629-6c49-48e5-b606-33f2277d3fa6.jpeg</url>
      <title>Forem: Ricardo Silva</title>
      <link>https://forem.com/ricardobsilva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ricardobsilva"/>
    <language>en</language>
    <item>
      <title>Desafios Comuns na Escrita de Testes Automatizados: Rumo à Clareza e Padronização - Parte 3</title>
      <dc:creator>Ricardo Silva</dc:creator>
      <pubDate>Tue, 27 Feb 2024 14:59:49 +0000</pubDate>
      <link>https://forem.com/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-3-30p9</link>
      <guid>https://forem.com/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-3-30p9</guid>
      <description>&lt;p&gt;Na &lt;a href="https://dev.to/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-2-1850"&gt;parte dois&lt;/a&gt;, nós vimos as três etapas que compõem um teste automatizado: Preparação, execução e resultado.&lt;/p&gt;

&lt;p&gt;Com isso em mente, vamos dedicar nossa terceira parte a responder às seguintes perguntas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que devo testar?&lt;/li&gt;
&lt;li&gt;O que não devo testar?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;O que devo testar?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apesar de ser uma atividade técnica, o ato de testar é influenciado por alguns fatores subjetivos que podem dificultar a vida de uma pessoa na hora de definir o escopo que precisa ser testado. Cada membro pode ter sua própria interpretação do que é importante testar, e isso é um fator subjetivo. Determinadas partes do sistema têm mais criticidade que outras, e isso é outro fator subjetivo.&lt;/p&gt;

&lt;p&gt;Antes de mais nada, o time precisa ter discussões claras que irão colocar todos na mesma página a respeito do que é importante testar, pois estabelecendo esse tipo de acordo, ficará mais fácil identificar quando determinada entrega (um PR, por exemplo) contém testes que fogem muito da estrutura dos demais testes existentes no projeto.&lt;/p&gt;

&lt;p&gt;Eu costumo propor que os testes precisam usar como referência principal os requisitos da tarefa, levando em conta os cenários "felizes" e "não felizes", onde o caminho feliz é o percurso ideal de execução, seguindo todas as condições esperadas sem ocorrência de erros, contrastando com o caminho não feliz, que abrange situações indesejadas ou desvios do comportamento previsto. &lt;/p&gt;

&lt;p&gt;Se essas informações não estão claras na descrição da tarefa, é importante mapeá-los (ao menos os iniciais, uma vez que dúvidas e requisitos não identificados antes poderão aparecer durante o processo de desenvolvimento).&lt;/p&gt;

&lt;p&gt;Vamos considerar que a seguinte task foi criada no board do projeto:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Cadastro de Chamado no Sistema&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;História:&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;Como usuário do sistema, desejo poder cadastrar um chamado para reportar problemas ou solicitar suporte.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Critérios de Aceitação:&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Número Único de Identificação:&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Após o cadastro bem-sucedido, com usuário informando título e descrião do chamado, o sistema deve gerar automaticamente um número único de identificação para o chamado.&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Número único de identificação precisa conter letras maísculas e números&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Cenários de Teste:&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Caminho Feliz:&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;O sistema gera um número único de identificação para o chamado.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Caminho Não Feliz:&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;O usuário tenta cadastrar um chamado sem preencher todos os campos obrigatórios, resultando em uma mensagem de erro.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos supor que estamos na etapa de construir um Service Object que aplicará essas regras descritas na tarefa. Um bom ponto de partida seria “transferir os requisitos” da tarefa para uma estrutura mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ticket_creator_spec.rb&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#call'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'When title and description are filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'generates a unique identification number with uppercase letters and numbers'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;# etapas do caminho feliz ficarão aqui&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'When title is not filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'raises an error'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;#etapas do caminho não feliz ficarão aqui&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O próximo passo é focar em escrever as etapas dos testes. Vamos começar pelo caminho feliz?&lt;/p&gt;

&lt;p&gt;Podemos dar início através do setup do teste, sempre tentando montar essa etapa somente com o que é estritamente necessário. Nesse caso, seriam os dados de título e descrição.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ticket_creator_spec.rb&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#call'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'When title and description are filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'generates a unique identification number with uppercase letters and numbers'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
         &lt;span class="n"&gt;valid_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                   &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Issue Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s1"&gt;'Detailed description of the issue'&lt;/span&gt; 
                 &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'When title is not filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'raises an error'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;#etapas do caminho não feliz ficarão aqui&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como eu considero que isso é muito pouco para executar o teste, vou seguir com o segundo passo, que seria a execução, colocando em nosso teste a unidade de código testada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ticket_creator_spec.rb&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#call'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'When title and description are filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'generates a unique identification number with uppercase letters and numbers'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
         &lt;span class="n"&gt;valid_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                   &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Issue Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s1"&gt;'Detailed description of the issue'&lt;/span&gt; 
                 &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valid_attributes&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'When title is not filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'raises an error'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;#etapas do caminho não feliz ficarão aqui&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui já conseguimos ter duas escolhas: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Rodar o teste e receber o feedback de que a classe TicketCreator ainda não existe, mais ou menos assim:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NameError:
  uninitialized constant TicketCreator
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partir para a terceira etapa, que seria determinar que após a execução da unidade de código (TicketCreator), um &lt;code&gt;identification_number&lt;/code&gt; precisa ter sido gerado&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se a ideia for seguir pelo segundo caminho, nosso teste poderia ficar mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ticket_creator_spec.rb&lt;/span&gt;

RSpec.describe TicketCreator &lt;span class="k"&gt;do
  &lt;/span&gt;describe &lt;span class="s1"&gt;'#call'&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;context &lt;span class="s1"&gt;'When title and description are filled in'&lt;/span&gt; &lt;span class="k"&gt;do
      &lt;/span&gt;it &lt;span class="s1"&gt;'generates a unique identification number with uppercase letters and numbers'&lt;/span&gt; &lt;span class="k"&gt;do
         &lt;/span&gt;valid_attributes &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
                   title: &lt;span class="s1"&gt;'Issue Title'&lt;/span&gt;, 
                     description: &lt;span class="s1"&gt;'Detailed description of the issue'&lt;/span&gt; 
                 &lt;span class="o"&gt;}&lt;/span&gt;

                ticket &lt;span class="o"&gt;=&lt;/span&gt; TicketCreator.new&lt;span class="o"&gt;(&lt;/span&gt;valid_attributes&lt;span class="o"&gt;)&lt;/span&gt;.call

                expect&lt;span class="o"&gt;(&lt;/span&gt;ticket.identification_number&lt;span class="o"&gt;)&lt;/span&gt;.not_to be_nil
                expect&lt;span class="o"&gt;(&lt;/span&gt;ticket.identification_number&lt;span class="o"&gt;)&lt;/span&gt;.to match&lt;span class="o"&gt;(&lt;/span&gt;/&lt;span class="se"&gt;\A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;A-Z0-9]+&lt;span class="se"&gt;\z&lt;/span&gt;/&lt;span class="o"&gt;)&lt;/span&gt;
      end
    end

    context &lt;span class="s1"&gt;'When title is not filled in'&lt;/span&gt; &lt;span class="k"&gt;do
      &lt;/span&gt;it &lt;span class="s1"&gt;'raises an error'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c"&gt;#etapas do caminho não feliz ficarão aqui&lt;/span&gt;
      end
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na medida em que formos rodando os testes, coletando os feedbacks e implementando o código até que os testes passem &lt;br&gt;
(&lt;a href="https://www.codecademy.com/article/tdd-red-green-refactor"&gt;ciclo Red-Green-Refactor&lt;/a&gt;), no final teremos uma classe mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/services/ticket_creator.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TicketCreator&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="vi"&gt;@title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="vi"&gt;@description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ticket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;identification_number: &lt;/span&gt;&lt;span class="n"&gt;generate_identification_number&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ticket&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_identification_number&lt;/span&gt;
    &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma vez que o caminho feliz foi implementado, podemos partir para a implementação do cenário não feliz com a confiança de que, caso façamos besteira e o caminho feliz pare de funcionar, seremos devidamente advertidos pelos testes.&lt;/p&gt;

&lt;p&gt;Primeiro os testes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ticket_creator_spec.rb&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#call'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when title and description are filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'generates a unique identification number with uppercase letters and numbers'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
         &lt;span class="n"&gt;valid_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                   &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Issue Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s1"&gt;'Detailed description of the issue'&lt;/span&gt; 
                 &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valid_attributes&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

                &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;identification_number&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_nil&lt;/span&gt;
                &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;identification_number&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\A[A-Z0-9]+\z/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when title is not filled in'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'raises an error'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;invalid_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s1"&gt;'Detailed description of the issue'&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;TicketCreator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invalid_attributes&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;raise_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Title can\'t be blank'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora a implementação&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/services/ticket_creator.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TicketCreator&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="vi"&gt;@title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="vi"&gt;@description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="n"&gt;validate_attributes&lt;/span&gt;

    &lt;span class="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ticket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;identification_number: &lt;/span&gt;&lt;span class="n"&gt;generate_identification_number&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ticket&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_attributes&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Title can\'t be blank'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_identification_number&lt;/span&gt;
    &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviamente, o código final da classe irá variar de acordo com o gosto da pessoa/time que estiver desenvolvendo, mas o importante aqui é que, desde o início, o foco sempre foi atender aos requisitos determinados na tarefa e avançar em direção a um código legível e organizado, uma prova de que os testes têm influência direta no design do código implementado, ao mesmo tempo em que diminui os riscos de se gerar novos bugs durante o processo.&lt;/p&gt;

&lt;p&gt;Outro ponto que vale destacar é a relevância dos dados de entrada das classes em relação aos dados de saída. Através dos dados de entrada, nós conseguimos ter total controle a respeito dos resultados esperados, baseado nos contextos definidos. É por isso que passar um título preenchido ou não foi o suficiente para simular o caminho feliz e o caminho não feliz.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que não devo testar?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Existe um motivo para que o método &lt;strong&gt;&lt;code&gt;call&lt;/code&gt;&lt;/strong&gt; seja o único método levado em consideração nos testes: métodos privados são &lt;strong&gt;detalhes de implementação e não devem ser testados diretamente,&lt;/strong&gt; ao mesmo passo em que, se uma classe tem somente um método público, isso será uma forma de garantir que ela assumirá somente uma responsabilidade (aqui não é sobre testes necessariamente, mas sobre o &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;princípio de responsabilidade única&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;O foco do teste precisa ser garantir que o comportamento externo da unidade de código (a classe TicketCreator) atenda aos requisitos especificados. E isso acontece através dos métodos públicos, que são de quem os usuários e outros componentes dependerão.&lt;/p&gt;

&lt;p&gt;Testar métodos privados pode (e provavelmente vai) resultar em testes frágeis e poluídos, uma vez que estarão sujeitos a mudanças internas na implementação que não afetarão o comportamento externo da unidade de código testada, ou seja: a saída do método público. Isso quer dizer que mudanças nos métodos privados &lt;strong&gt;poderão ou não&lt;/strong&gt; causar quebra ou mudança no comportamento da classe, mas caso cause, os testes do método público já estarão cobrindo isso.&lt;/p&gt;

&lt;p&gt;Se um método privado executa rotinas muito complexas, vale a pena extrair esse código para uma classe contendo seus próprios testes.&lt;/p&gt;

&lt;p&gt;Testes simples, implementação simples… De complicado já basta a vida, não é verdade?&lt;/p&gt;

&lt;p&gt;E assim finalizamos a parte três da nossa série.&lt;/p&gt;

&lt;p&gt;Nos vemos na parte quatro!&lt;/p&gt;

</description>
      <category>singleresponsibility</category>
      <category>bdd</category>
      <category>tdd</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Desafios Comuns na Escrita de Testes Automatizados: Rumo à Clareza e Padronização - Parte 2</title>
      <dc:creator>Ricardo Silva</dc:creator>
      <pubDate>Fri, 23 Feb 2024 01:17:48 +0000</pubDate>
      <link>https://forem.com/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-2-1850</link>
      <guid>https://forem.com/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-2-1850</guid>
      <description>&lt;p&gt;Na &lt;a href="https://dev.to/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-1-1f8d"&gt;primeira parte&lt;/a&gt; nós vimos como testes são uma excelente forma de documentação, principalmente se os blocos &lt;em&gt;describe, context e it&lt;/em&gt; estiverem organizados e com descrições claras, ajudando a dar clareza a respeito do objetivo daquela unidade de código em questão (e qual o papel dela em relação a outras unidades de código).&lt;/p&gt;

&lt;p&gt;A ideia dessa segunda parte é continuar trabalhando padrões, agora focando nos seguintes pontos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Etapas de um teste automatizado&lt;/li&gt;
&lt;li&gt;Testes e implementação são interdependentes (e isso não deveria ser negociável)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; Etapas de um teste automatizado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Um teste automatizado é composto por três etapas: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Preparação(Setup)&lt;/em&gt; - Aqui a gente carrega tudo aquilo que consideramos necessário para testar nossa unidade de código, seja a criação de um registro no banco, chamada para uma API externa, carregamento de arquivos e tudo mais que for imprescíndivel &lt;em&gt;antes&lt;/em&gt; e para execução dos testes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Execução(Execution)&lt;/em&gt; - Aqui é onde as coisas acontecem de fato. Nessa etapa o teste vai servir como gatilho para executar a unidade de código alvo, seja uma classe, um endpoint ou qualquer outro componente do sistema. Eu não vou dizer que absolutamente tudo pode ser testado, mas até hoje não vi algo que não possa. Porém, vale destacar que o verdadeiro objetivo é testar tudo aquilo que é referente a regras de negócio do sistema. Então não faz muito sentido testar métodos de uma biblioteca, por exemplo.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resultado(Assertion/Verification)&lt;/em&gt; - Aqui é a etapa onde a gente verifica se o &lt;em&gt;comportamento&lt;/em&gt; esperado da unidade de código aconteceu como esperado, de acordo com o cenário proposto, como por exemplo se algum registro foi criado/alterado no banco.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'must change the band name'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Preparação: Cria uma banda com o nome 'The Rolling Stones'&lt;/span&gt;
  &lt;span class="n"&gt;band&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:band&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'The Rolling Stones'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Execução: Executa a unidade de código desejada&lt;/span&gt;
  &lt;span class="n"&gt;updated_band&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;BandNameUpdater&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;band&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Oasis'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

  &lt;span class="c1"&gt;# Resultado: Valida se o resultado saiu conforme esperado&lt;/span&gt;
  &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updated_band&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Oasis'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Independente do tamanho e complexidade do que está sendo testado, o objetivo é sempre se ater a essas três etapas na hora de construir ou modificar seus  testes, tentando sempre mantê-los &lt;strong&gt;o mais simples possível&lt;/strong&gt;. E é aqui onde os testes começam a influênciar diretamente na qualidade do código do software, pois se estiver sendo difícil contemplar os possíveis comportamentos de uma unidade de código através dessas três etapas, isso pode ser o primeiro sinal de que essa unidade de código está assumindo multiplas responsabilidades e possivelmente uma quebra em unidades de códigos menores deverá ser  seu próximo passo, com o intuito de torna-la mais coesa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; Testes e implementação são interdependentes (e isso não deveria ser negociável)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Essas três etapas também estão presentes em testes manuais. Se você usa ferramentas como o postman, por exemplo, você vai precisar criar objetos no banco, setar URL's, configurar headers (Preparação). Depois você vai clicar no botãozinho para fazer a requisição (Execução). E, por fim, você vai analisar tudo aquilo que veio na resposta (status 200? Json contendo determinado dado? Novo registro criado?).  &lt;/p&gt;

&lt;p&gt;E dito isso, fica o questionamento:&lt;/p&gt;

&lt;p&gt;Se você faz tudo isso manualmente para só depois escrever os testes automatizados, isso não seria um retrabalho?&lt;/p&gt;

&lt;p&gt;Talvez tudo o que você precise é se forçar a colocar os testes automatizados desde o inicio do seu processo de desenvolvimento, por mais que sejamos constantemente tentados a abrir mão da qualidade (não só em testes) em detrimento de uma falsa sensação de velocidade de desenvolvimento, o que na prática não se concretiza, por conta do retrabalho que mais cedo ou mais tarde acontece.  Um exemplo muito comum? Lá vai:&lt;/p&gt;

&lt;p&gt;1 - Dev estima tarefa com e sem testes&lt;/p&gt;

&lt;p&gt;2 - Dev apresenta essas estimativas ao Product Owner (ou seja lá quem for a pessoa pra quem você estima tarefas)&lt;/p&gt;

&lt;p&gt;3 -  Há um consenso de que escrever sem testes será mais rápido e que os testes serão escritos posteriormente&lt;/p&gt;

&lt;p&gt;4 - A entrega é feita e lançada em produção com uma falsa sensação de rapidez&lt;/p&gt;

&lt;p&gt;5 - A entrega resultou em um bug&lt;/p&gt;

&lt;p&gt;6 - Para tudo para resolver o bug, dessa vez com muito mais pressão para entregar&lt;/p&gt;

&lt;p&gt;7 - Surge o questionamento de quanto tempo levará para corrigir o bug&lt;/p&gt;

&lt;p&gt;8 - De volta ao item 1 🤡&lt;/p&gt;

&lt;p&gt;Ver os testes como separados da implementação é separar o código da qualidade do código, uma aposta difícil de ganhar, e eu achei importante trazer esse ponto antes de seguirmos com exemplos mais práticos pois, na minha percepção, fazer essa separação é o primeiro passo para ter testes frágeis, dificeis de manter e com pouca ou nenhuma padronização. &lt;/p&gt;

&lt;p&gt;Considere que testes e implementação &lt;strong&gt;são&lt;/strong&gt; &lt;strong&gt;a mesma coisa&lt;/strong&gt; e você estará colocando isso em prática mais cedo do que imagina.&lt;/p&gt;

&lt;p&gt;Na parte três vamos ver na prática que tão importante quanto &lt;em&gt;saber&lt;/em&gt; o que testar é saber o que &lt;em&gt;não&lt;/em&gt; testar.&lt;/p&gt;

&lt;p&gt;Até lá.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>bdd</category>
      <category>fullstack</category>
      <category>programming</category>
    </item>
    <item>
      <title>Desafios Comuns na Escrita de Testes Automatizados: Rumo à Clareza e Padronização - Parte 1</title>
      <dc:creator>Ricardo Silva</dc:creator>
      <pubDate>Mon, 19 Feb 2024 15:16:26 +0000</pubDate>
      <link>https://forem.com/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-1-1f8d</link>
      <guid>https://forem.com/ricardobsilva/desafios-comuns-na-escrita-de-testes-automatizados-rumo-a-clareza-e-padronizacao-parte-1-1f8d</guid>
      <description>&lt;p&gt;&lt;strong&gt;Do que é composto um software?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Gosto da premissa de que um software pode ser considerado um conjunto de &lt;strong&gt;unidades de código&lt;/strong&gt;, como objetos, classes, métodos e variáveis, que interagem e se comunicam entre si para realizar determinadas operações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que faz um código ser considerado um código de qualidade?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Em poucas palavras, é quando essas unidades de código conseguem existir de forma coesa (onde tudo faz sentido) e desacoplada (quando a alteração de uma unidade não causa a quebra de uma outra unidade).&lt;/p&gt;

&lt;p&gt;Nos próximos artigos nós tentaremos entender um pouco mais sobre como os testes automatizados, desde que bem escritos, podem nos ajudar a conseguir colocar em prática os pontos acima.&lt;/p&gt;

&lt;p&gt;ps: A ideia aqui não é ensinar os conceitos básicos de testes automatizados, muito menos mergulhar nas sopas de letrinhas do SOLID, BDD, DRY, Design Patterns, pirâmide de testes, etc. Vou evitar até mesmo usar termos como testes de integração e unitários, utilizando sempre o termo “testes automatizados".  Embora tudo isso seja levando em conta no conteúdo proposto (até porque nada do que vou passar aqui foi inventado por mim), a ideia principal é estabelecer um ponto de partida para criar testes automatizados que sejam consistentes e que validem de fato o que um software deve fazer.&lt;/p&gt;

&lt;p&gt;ps2: Os conceitos e exemplos aqui são agnósticos a tecnologias. Irei utilizar Ruby (com Rails) e RSpec como stack para os exemplos, mas recomendo que tente replica-los na stack que você preferir.&lt;/p&gt;

&lt;p&gt;ps3: Como o óbvio também precisa ser dito, objetivo aqui não é determinar a melhor forma de escrever testes e sim tentar estabelecer algumas formas padronizadas de fazer isso.&lt;/p&gt;

&lt;p&gt;Nessa primeira parte nós começaremos abordando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consequências ao ignorar os testes automatizados&lt;/li&gt;
&lt;li&gt;Testes automatizados como documentação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; Consequências ao ignorar os testes automatizados&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Algo que vi com certa frequência em boa parte dos projetos em que trabalhei foi a falta de clareza e objetividade na escrita dos testes automatizados. Não raramente, desenvolvedores dos mais diversos níveis de experiência apresentando insegurança a respeito de como escrever testes automatizados para um código que ele mesmo escreveu me faz refletir sobre como algum tipo de padronização de pensamento poderia ajudar na hora de montar esses testes.&lt;/p&gt;

&lt;p&gt;Em resumo:&lt;/p&gt;

&lt;p&gt;1 - Nenhum desenvolvedor (com o juízo no lugar) questiona a importância de &lt;strong&gt;escrever&lt;/strong&gt; testes.&lt;/p&gt;

&lt;p&gt;2 - Muitos desenvolvedores não tem clareza sobre &lt;strong&gt;como escrever&lt;/strong&gt; tais testes.&lt;/p&gt;

&lt;p&gt;A falta de clareza sobre como escrever testes leva muitos desenvolvedores a gastar horas tentando reproduzir cenários para validar implementações ou corrigir bugs usando ferramentas como Postman ou o console do framework.&lt;/p&gt;

&lt;p&gt;Agora vamos ao nosso primeiro exemplo, já que ninguém é obrigado a acreditar no que eu falo:&lt;/p&gt;

&lt;p&gt;Em nosso exemplo, nós temos uma API responsável por publicar artigos, sendo composto pelos seguintes requisitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Article pertence à Author e Category, que precisam estar previamente cadastrados&lt;/li&gt;
&lt;li&gt;Article possui title e body como atributos&lt;/li&gt;
&lt;li&gt;Ao cadastrar um novo artigo, o autor precisará ser notificado que seu artigo já foi publicado&lt;/li&gt;
&lt;li&gt;Teremos um Service Object responsável por executar todo esse fluxo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dito isso, em um cenário onde testes automatizados estão sendo ignorados naquele momento pelo desenvolvedor, ele precisará abrir o console e preparar tudo o que precisa para reproduzir o fluxo de publicação de um artigo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# primeiro criando um autor&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="s1"&gt;'john.doe@example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# depois criando uma categoria&lt;/span&gt;
&lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Technology'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# em seguida montando o hash com os dados de um novo artigo&lt;/span&gt;
&lt;span class="n"&gt;article_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Introduction to Rails'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s1"&gt;'This is the content of the article.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;author_id: &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;category_id: &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# e executando o Service Object que irá performar todo o fluxo de criação &lt;/span&gt;
&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando eu disse que os testes foram ignorados pelo desenvolvedor, eu me referi a duas possibilidades bem comuns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Os testes não existem e o desenvolvedor optou por escreve-los somente após concluir a implementação em que está trabalhando (lembrando que pode ser um bugfix, refatoração ou algo totalmente novo).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Os testes existem, mas o desenvolvedor não quis abri-los, entende-los e executá-los.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qualquer uma das opções impactam negativamente em vários aspectos, dos quais nesse momento podemos destacar duas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Entender o código de um Service Object pode ser demorado, pois o desenvolvedor precisa analisar o código-fonte e as classes relacionadas para compreender completamente o propósito da implementação. Até que ocorram "epifanias" que esclareçam o fluxo da execução, o desenvolvimento pode ser prolongado, especialmente ao lidar com código legado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A montagem e reprodução do cenário necessário para testes também podem ser morosas. No exemplo fornecido, já foi necessário criar manualmente registros no banco e preparar um hash de dados para um novo artigo. Em um software real com mais complexidade, essa preparação pode envolver várias etapas, com &lt;strong&gt;vários possíveis contextos e resultados diferentes&lt;/strong&gt;, tornando frequentemente necessário o auxílio de um membro experiente da equipe para configurar o ambiente de teste, ao contrário da facilidade proporcionada por comandos que automatizam esse processo.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; Testes automatizados como documentação&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testes automatizados, antes de mais nada, são uma documentação viva do software, servindo de referencia para o entendimento de contextos de cada funcionalidade, contemplando as entradas esperadas, saídas esperadas, mudanças implementadas e a relação entre cada uma das unidades de que compõem de código de um software.&lt;/p&gt;

&lt;p&gt;Agora um exemplo de testes que poderiam auxiliar o desenvolvedor nesse primeiro desafio de entender e reproduzir o cenário desejado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/services/article_creation_service_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :service&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#call'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when passing valid data'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'creates a new article'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;article_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Test Article'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s1"&gt;'This is a test article.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author_id: &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;category_id: &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'enqueues email notification job'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;article_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Test Article'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s1"&gt;'This is a test article.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author_id: &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;category_id: &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ArticleMailer'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when passing invalid data'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'does not create a new article'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                &lt;span class="n"&gt;invalid_article_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Test Article'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s1"&gt;'This is a test article.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;category_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invalid_article_params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'does not enqueue email notification job'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                &lt;span class="n"&gt;invalid_article_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Test Article'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s1"&gt;'This is a test article.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;category_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invalid_article_params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa estrutura é focada em três blocos: &lt;em&gt;describes&lt;/em&gt;, &lt;em&gt;contexts&lt;/em&gt; e &lt;em&gt;its&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O bloco &lt;em&gt;describe&lt;/em&gt; determina qual a unidade de código está sendo testada, no nosso caso aqui estamos falando do método &lt;em&gt;call.&lt;/em&gt; O &lt;em&gt;describe&lt;/em&gt; engloba todos os &lt;em&gt;contexts&lt;/em&gt; (possível contextos), que por sua vez guardam os &lt;em&gt;its&lt;/em&gt; que são as saídas esperadas para essas unidades de código. &lt;/p&gt;

&lt;p&gt;O termo “documentação viva” se dá justamente por conta da mensagem que os testes passam, descrevendo o que está sendo testado e qual o comportamento esperado de acordo com cada possível cenário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Dada&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;unidade&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;digo&lt;/span&gt; &lt;span class="no"&gt;ArticleCreationService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Que&lt;/span&gt; &lt;span class="n"&gt;cont&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;unidade&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;digo&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;
    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Quando&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;forem&lt;/span&gt; &lt;span class="n"&gt;passados&lt;/span&gt; &lt;span class="n"&gt;dados&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;lidos&lt;/span&gt;
      &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Espera&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;um&lt;/span&gt; &lt;span class="n"&gt;novo&lt;/span&gt; &lt;span class="n"&gt;artigo&lt;/span&gt; &lt;span class="n"&gt;seja&lt;/span&gt; &lt;span class="n"&gt;criado&lt;/span&gt;
      &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Espera&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;um&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;notifica&lt;/span&gt;&lt;span class="err"&gt;çã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;seja&lt;/span&gt; &lt;span class="n"&gt;enfileirado&lt;/span&gt;
    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Quando&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;forem&lt;/span&gt; &lt;span class="n"&gt;passados&lt;/span&gt; &lt;span class="n"&gt;dados&lt;/span&gt; &lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;lidos&lt;/span&gt;
      &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Espera&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;um&lt;/span&gt; &lt;span class="n"&gt;novo&lt;/span&gt; &lt;span class="n"&gt;artigo&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="err"&gt;ã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;seja&lt;/span&gt; &lt;span class="n"&gt;criado&lt;/span&gt;
      &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="no"&gt;Espera&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;um&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;notifica&lt;/span&gt;&lt;span class="err"&gt;çã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="err"&gt;ã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;seja&lt;/span&gt; &lt;span class="n"&gt;enfileirado&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outro ponto que faz com que testes sejam uma documentação viva é que alterações no código poderão acarretar em quebra dos testes, o que forçará o desenvolvedor a ajustar os testes de acordo com a nova necessidade e por consequência os descritivos de cada bloco. &lt;/p&gt;

&lt;p&gt;Por enquanto é isso. Nas próximas continuações (se a procrastinação não me vencer) iremos ver outras abordagens que te ajudarão na hora de escrever testes para suas aplicações.&lt;/p&gt;

&lt;p&gt;Até lá.&lt;/p&gt;

</description>
      <category>bdd</category>
      <category>tests</category>
      <category>backend</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
