<?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>DEV Community: Gabrielly de Andrade</title>
    <description>The latest articles on DEV Community by Gabrielly de Andrade (@gabriellydeandrade).</description>
    <link>https://dev.to/gabriellydeandrade</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%2F253529%2Fb6c4a2a1-df19-4405-83e6-7645a4916fb3.jpeg</url>
      <title>DEV Community: Gabrielly de Andrade</title>
      <link>https://dev.to/gabriellydeandrade</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gabriellydeandrade"/>
    <language>en</language>
    <item>
      <title>Testes em Python - Parte 2: Testes orientados ao comportamento</title>
      <dc:creator>Gabrielly de Andrade</dc:creator>
      <pubDate>Sun, 07 Jun 2020 20:58:47 +0000</pubDate>
      <link>https://dev.to/womakerscode/testes-em-python-parte-2-testes-orientados-ao-comportamento-l19</link>
      <guid>https://dev.to/womakerscode/testes-em-python-parte-2-testes-orientados-ao-comportamento-l19</guid>
      <description>&lt;p&gt;Essa é a continuação da &lt;a href="https://dev.to/womakerscode/testes-em-python-parte-1-introducao-43ei"&gt;parte 1&lt;/a&gt; da série "Testes em Python". &lt;/p&gt;

&lt;p&gt;Na série de hoje iremos ver como realizar testes de comportamento resgatando alguns conceitos visto na primeira parte.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pré-requisito
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Conhecimento básico de Python&lt;/li&gt;
&lt;li&gt;Conceito básico sobre testes e o porque eles são importantes (&lt;a href="https://dev.to/womakerscode/testes-em-python-parte-1-introducao-43ei"&gt;Veja a parte 1 da série&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Roteiro
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;O que são testes de comportamento&lt;/li&gt;
&lt;li&gt;O que é BDD&lt;/li&gt;
&lt;li&gt;Behave&lt;/li&gt;
&lt;li&gt;Exemplo&lt;/li&gt;
&lt;li&gt;Considerações adicionais&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. O que são testes de comportamento
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Motivação
&lt;/h3&gt;

&lt;p&gt;Ao receber uma demanda de uma implementação de funcionalidade, normalmente são os próprios desenvolvedores que implementam e realizam os casos de testes para validar se tudo funciona como o esperado. &lt;/p&gt;

&lt;p&gt;No entanto, essas implementações são escritas de uma maneira muito técnica, de modo que somente quem possui conhecimento de certas tecnologias possa entender, não permitindo uma clareza de comunicação com profissionais não-técnicos, que geralmente são os que demandam a funcionalidade.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Testes de comportamento
&lt;/h3&gt;

&lt;p&gt;Testes de comportamento surgiu a partir da necessidade de validar cenários por meio de uma comunicação mais transparente. Deste modo, conseguimos validar qual deve ser o comportamento do nosso código e realizar assertivas em cima desses cenários.&lt;/p&gt;

&lt;p&gt;Esses testes permitem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entendimento comum por meio do escopo do negócio (regras de negócio)&lt;/li&gt;
&lt;li&gt;Comunicação clara por meio de linguagem comum entre todos os participantes envolvidos&lt;/li&gt;
&lt;li&gt;Melhora na documentação sobre os cenários da aplicação&lt;/li&gt;
&lt;li&gt;Ajuda em um melhor acordo comum da "definição de pronto" do sistema&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. O que é o BDD
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cucumber.io/docs/bdd/" rel="noopener noreferrer"&gt;BDD&lt;/a&gt; é uma sigla que significa &lt;strong&gt;B&lt;/strong&gt;ehavior-&lt;strong&gt;D&lt;/strong&gt;riven &lt;strong&gt;D&lt;/strong&gt;evelopment, do português desenvolvimento orientado ao comportamento. Ele foi introduzido por &lt;a href="https://dannorth.net/introducing-bdd/" rel="noopener noreferrer"&gt;Dan North&lt;/a&gt; em resposta ao tradicional TDD¹&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TDD¹ é uma sigla que significa &lt;strong&gt;T&lt;/strong&gt;est-&lt;strong&gt;D&lt;/strong&gt;riven &lt;strong&gt;D&lt;/strong&gt;evelopment, do português desenvolvimento orientado a testes. Resgatando o que foi visto na parte 1 da série, seria escrever os cenários de testes antes de implementar o nosso código propriamente dito. Assim, estaríamos garantindo que toda a nossa aplicação estaria coberta por testes. Veja mais em &lt;a href="https://www.eusoudev.com.br/tdd/" rel="noopener noreferrer"&gt;https://www.eusoudev.com.br/tdd/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Isso significa que vamos primeiro escrever cenários com comportamentos em linguagem natural e depois escrever nosso código orientado a isso. Veremos que esses comportamentos serão fluxos do usuário.&lt;/p&gt;

&lt;p&gt;O BDD segue algumas &lt;a href="https://behave.readthedocs.io/en/latest/philosophy.html" rel="noopener noreferrer"&gt;filosofias&lt;/a&gt;, dentre elas pode se destacar a entrega de valor ao negócio. Assim, diferentes personas envolvidas na elaboração de um projeto como desenvolvedores, QA,  participantes do negócio e outras pessoas não técnicas podem garantir que o valor está sendo entregue a partir de uma &lt;a href="https://lizkeogh.com/2007/06/13/bdd-tdd-done-well/" rel="noopener noreferrer"&gt;documentação clara e simplificada&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Quando todos possuem uma visão clara dos requerimentos para um programa funcionar, todos ficam mais alinhados com o valor que será entregue, pois a aplicação estará coberta por esses cenários orientados ao comportamento. Isso inclusive pode levar com que todos descubram cenários não pensados anteriormente.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Behave
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://behave.readthedocs.io/en/latest/index.html" rel="noopener noreferrer"&gt;Behave&lt;/a&gt; é uma biblioteca em Python que iremos utilizar para fazer nossos testes orientados ao comportamento. Ela utiliza componentes do &lt;a href="https://cucumber.io/docs/installation/" rel="noopener noreferrer"&gt;cucumber&lt;/a&gt;, que é uma ferramenta para rodar testes escritos em linguagem natural.&lt;/p&gt;

&lt;p&gt;Veremos como utilizar na prática por meio de um exemplo.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Exemplo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 O escopo do exemplo
&lt;/h3&gt;

&lt;p&gt;Vamos realizar um pequeno sistema de criação de conta de um banco simplificado. Nele, podemos além de criar uma conta, depositar e sacar dinheiro.&lt;/p&gt;

&lt;p&gt;Vamos considerar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Nome do cliente&lt;/li&gt;
&lt;li&gt;Número da conta&lt;/li&gt;
&lt;li&gt;Senha&lt;/li&gt;
&lt;li&gt;Saldo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As ações de depositar e sacar dinheiro só poderão ser feitas se o cliente estiver autenticado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Repare que esse fluxo é bem simplificado e vários outros fatores estão sendo desconsiderados dessa abstração para que possamos nos concentrar no BDD.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Preparando o ambiente
&lt;/h3&gt;

&lt;p&gt;Vamos criar um diretório para conter o nosso código, vamos chamar a pasta de &lt;strong&gt;simple_bank_account&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Antes de começar a implementação, vamos escrever o comportamento esperado. Para isso vamos instalar o &lt;a href="https://behave.readthedocs.io/en/latest/install.html" rel="noopener noreferrer"&gt;behave&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OBS.: Sugiro utilizar um ambiente virtual para instalar as dependências, pois irá possibilitar isolar o nosso código de outros recursos e projetos que temos no nosso computador. &lt;a href="https://tutorial.djangogirls.org/pt/django_installation/#ambiente-virtual" rel="noopener noreferrer"&gt;Recomendo o tutorial do Django Girls para isso&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Quando estiver no ambiente virtual, rode o comando para instalar o behave&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;behave&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos implementar nossa estrutura base de arquivos. Teremos nossa estrutura raiz que terá o projeto e o behave sempre procura os arquivos dentro de um diretório chamado &lt;strong&gt;features&lt;/strong&gt; (irá conter as funcionalidades do sistema) e as &lt;strong&gt;steps&lt;/strong&gt; (local onde iremos realizar as assertivas para garantir que as funcionalidades estão funcionando).&lt;/p&gt;

&lt;p&gt;No final vamos ter algo parecido com essa estrutura:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fovmop537lf086zl25cih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fovmop537lf086zl25cih.png" alt="Estrutura de pastas de testes com behave"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feita a criação dos diretório, chegamos a essa estrutura&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffo59ykpgoil46f5zjskn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffo59ykpgoil46f5zjskn.png" alt="Estrutura do código de exemplo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos agora implementar nossa primeira funcionalidade&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Escrevendo a estória do usuário (features)
&lt;/h3&gt;

&lt;p&gt;Vamos escrever o nosso primeiro fluxo do usuário.&lt;/p&gt;

&lt;p&gt;Esses fluxos são arquivos terminados em &lt;strong&gt;.feature&lt;/strong&gt; e são interpretados pelo behave a partir de uma linguagem chamada &lt;a href="https://cucumber.io/docs/gherkin/reference/#spoken-languages" rel="noopener noreferrer"&gt;Gherkin&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Essa linguagem permite interpretar a linguagem escrita de maneira natural. Diversos idiomas são suportados e para o nosso exemplo vamos ver o uso desse documento escrito em português.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fluxo de criação da conta&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dentro da pasta &lt;strong&gt;features&lt;/strong&gt; vamos criar um arquivo chamado &lt;strong&gt;create_account.feature&lt;/strong&gt; e nele iremos escrever a funcionalidade de criação de conta.&lt;/p&gt;

&lt;p&gt;Seguindo a nomenclatura da &lt;a href="https://behave.readthedocs.io/en/latest/tutorial.html" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;, mas escrevendo em português, temos o seguinte fluxo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# language: pt
&lt;/span&gt;
&lt;span class="n"&gt;Funcionalidade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;criar&lt;/span&gt; &lt;span class="n"&gt;conta&lt;/span&gt;

  &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Como cliente, eu quero que seja possível criar uma nova conta no banco para possibilitar depositar e sacar dinheiro
  &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

  &lt;span class="n"&gt;Cenário&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt; &lt;span class="n"&gt;solicita&lt;/span&gt; &lt;span class="n"&gt;criação&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;conta&lt;/span&gt;
    &lt;span class="n"&gt;Quando&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;conta&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;criada&lt;/span&gt;
    &lt;span class="n"&gt;Então&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;saldo&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;sua&lt;/span&gt; &lt;span class="n"&gt;conta&lt;/span&gt; &lt;span class="n"&gt;deve&lt;/span&gt; &lt;span class="n"&gt;estar&lt;/span&gt; &lt;span class="n"&gt;zerado&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.3.1  create_account.feature&lt;/p&gt;

&lt;p&gt;Repare que aqui temos algumas palavras chaves como &lt;strong&gt;Funcionalidade&lt;/strong&gt;, &lt;strong&gt;Cenário&lt;/strong&gt;, &lt;strong&gt;Quando&lt;/strong&gt; e &lt;strong&gt;Então&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Funcionalidade&lt;/strong&gt;: descreve o comportamento esperado de uma funcionalidade da aplicação. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cenário&lt;/strong&gt;: descreve uma parte do comportamento esperado da funcionalidade. Faz referência com cada cenário de teste que vimos com unittest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quando&lt;/strong&gt;: descreve uma ação que acontece na nossa aplicação&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Então&lt;/strong&gt;: o que deve ser retornado quando a ação for realizada&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repare que esse documento poderá ser escrito por analistas de negócios, analista de qualidade e profissionais não técnicos justamente por estar em linguagem natural.&lt;/p&gt;

&lt;p&gt;Outras palavras chaves podem ser utilizadas e o mapeamento completo pode ser visto na documentação do &lt;a href="https://cucumber.io/docs/gherkin/reference/" rel="noopener noreferrer"&gt;cucumber&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos rodar no terminal o comando behave dentro da raiz do nosso projeto e ver o que acontece&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;behave
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4nja61r3zqavmbwisqtf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4nja61r3zqavmbwisqtf.png" alt="Avisos ao rodar o behave pela primeira vez"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que temos alguns avisos nos alertando que não temos nenhuma definição de &lt;strong&gt;step&lt;/strong&gt; implementada.  Vamos implementar essas steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.4 Escrevendo as steps (implementando as assertivas)
&lt;/h3&gt;

&lt;p&gt;Aqui é onde tudo será validado. Steps são arquivos em python (.py) que irá implementar as palavras chaves utilizadas no arquivo de &lt;strong&gt;feature&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Dentro da pasta &lt;strong&gt;features/steps&lt;/strong&gt; vamos criar uma step que valide a feature de criação de conta. Para isso, vamos criar o arquivo &lt;strong&gt;create_account.py&lt;/strong&gt; criando uma estrutura desse jeito&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn68h8dab0p82det83t0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn68h8dab0p82det83t0n.png" alt="Nota estrutura de arquivos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que no arquivo &lt;strong&gt;4.3.1 create_account.feature&lt;/strong&gt; utilizamos algumas palavras chave. Essas palavras chaves serão utilizadas com base em um &lt;a href="https://realpython.com/primer-on-python-decorators/" rel="noopener noreferrer"&gt;decorator&lt;/a&gt; implementado pela própria biblioteca do behave. Vamos importar as palavras mapeadas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;behave&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;

&lt;span class="nd"&gt;@when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a conta do cliente for criada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_account&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="k"&gt;pass&lt;/span&gt;

&lt;span class="nd"&gt;@then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;o saldo de sua conta deve estar zerado&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_create_account&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="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.4.1 create_account.py &lt;/p&gt;

&lt;p&gt;Repare que nesse arquivo python utilizamos as palavras chaves &lt;strong&gt;when&lt;/strong&gt; e &lt;strong&gt;then&lt;/strong&gt; que respectivamente significam o &lt;strong&gt;quando&lt;/strong&gt; e &lt;strong&gt;então&lt;/strong&gt; que utilizamos no nosso arquivo &lt;strong&gt;4.3.1 create_account.feature&lt;/strong&gt;. E o parâmetro que é passado pra esse decorator (@when e &lt;a class="mentioned-user" href="https://dev.to/then"&gt;@then&lt;/a&gt;) é justamente o texto que escrevemos na nossa feature.&lt;/p&gt;

&lt;p&gt;Vamos rodar o behave novamente&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7lwdstpo0bn6d0envtwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7lwdstpo0bn6d0envtwy.png" alt="Testes passaram sem implementação"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Veremos que tudo passou, mas na verdade não estamos validando nada ainda. Vamos começar a rascunhar nosso código e importar no arquivo de step.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.5 Interagindo com o código e o teste
&lt;/h3&gt;

&lt;p&gt;Iremos criar uma estrutura de classe simples para conseguir importar no nosso arquivo de teste. Vamos criar fora da pasta de features&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4bya3767gbg63nqpqniu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4bya3767gbg63nqpqniu.png" alt="Arquivo novo que irá conter nosso código simplificado de criação de conta"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleBankAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.5.1 simple_bank_account.py &lt;/p&gt;

&lt;p&gt;Considerando os requisitos levantados no escopo do exemplo, vamos passar para criação da conta o nome do cliente, a numeração da conta (sim, nesse exemplo fictício o cliente especifica isso) e a senha. Logo depois, validar se o saldo da conta é zero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;behave&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;simple_bank_account&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleBankAccount&lt;/span&gt;

&lt;span class="nd"&gt;@when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a conta do cliente for criada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_account&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="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleBankAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shizuku Tsukishima&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&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;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123456&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="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;

&lt;span class="nd"&gt;@then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;o saldo de sua conta deve estar zerado&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_create_account&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="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.5.2 create_account.py &lt;/p&gt;

&lt;p&gt;Na primeira step &lt;strong&gt;@when("a conta do cliente for criada")&lt;/strong&gt; instanciamos nossa classe &lt;strong&gt;SimpleBankAccount&lt;/strong&gt; passando os dados necessários que gostaríamos.&lt;/p&gt;

&lt;p&gt;Logo em seguida, salvamos dentro do contexto da nossa step, o resultado que queremos validar através de um &lt;a href="https://www.geeksforgeeks.org/monkey-patching-in-python-dynamic-behavior/" rel="noopener noreferrer"&gt;comportamento dinâmico que o behave implementa&lt;/a&gt;. Isso é importante para compartilhar valores com outras steps.&lt;/p&gt;

&lt;p&gt;Já na step &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/then"&gt;@then&lt;/a&gt;("o saldo de sua conta deve estar zerado")&lt;/strong&gt; pegamos o valor salvo dentro do contexto e validamos se é igual a zero com o &lt;code&gt;assert&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Vamos rodar o behave novamente&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzmwvnscnks46ckf4gy0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzmwvnscnks46ckf4gy0u.png" alt="Falha nos testes com behave, TypeError"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Veremos que começou a aparecer alguns erros, o primeiro ele é um &lt;strong&gt;TypeError&lt;/strong&gt; pois o nosso código não tem ainda nada implementado, somente a base. Vamos voltar no arquivo  4.5.1 simple_bank_account.py e inicializar a classe com esses argumentos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_name&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleBankAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;4.5.3 simple_bank_account.py &lt;/p&gt;

&lt;p&gt;Rodando novamente o behave vamos perceber que não existe também o atributo &lt;strong&gt;balance&lt;/strong&gt; que irá conter o saldo da conta. Isso acontece pois no &lt;strong&gt;4.5.2 create_account.py&lt;/strong&gt; estamos acessando &lt;strong&gt;account.balance&lt;/strong&gt; e esse atributo realmente não existe em nossa classe. Vamos adicioná-lo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_name&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleBankAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rodando novamente o behave veremos que a funcionalidade &lt;strong&gt;criar conta&lt;/strong&gt; deve funcionar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj636rgnesoso3xbd71yx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj636rgnesoso3xbd71yx.png" alt="Testes passando e implementado com behave"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E repare que dessa vez ele passou pois realmente estava testando nosso cenário. Se trocássemos o assert da nossa step para&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;por exemplo, veremos que os testes não irão mais passar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fawcarsi4whl0sfgku3kg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fawcarsi4whl0sfgku3kg.png" alt="Testes irão falhar se a assertiva for modificada"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É bom fazer essas validações com outros tipos de valores para garantir que o teste realmente está  sendo implementado.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.6 Funcionalidade de depositar e sacar
&lt;/h3&gt;

&lt;p&gt;Para esse artigo não ficar muito grande, não iremos ver nesse artigo como ficaram as outras funcionalidades. No entanto, o código poderá ser visto &lt;a href="https://github.com/gabriellydeandrade/python-material/tree/master/tests/bdd/simple_bank_account" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;No final, teremos um retorno que descreve exatamente o fluxo de interação do usuário com o nosso sistema. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F127iaaictfsetcznlms6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F127iaaictfsetcznlms6.png" alt="Testes passando para a funcionalidade de depositar e sacar da nossa conta simplificada"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Considerações adicionais
&lt;/h2&gt;

&lt;p&gt;Aqui, listo alguns tópicos que são interessantes levar em consideração:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para conseguir fazer um bom levantamento nos arquivos de funcionalidade, é uma boa prática implementar uma cultura de &lt;a href="https://cucumber.io/docs/bdd/discovery-workshop/" rel="noopener noreferrer"&gt;Discovery&lt;/a&gt; para envolver diferentes profissionais para discutir a cerca do negócio e da implementação.&lt;/li&gt;
&lt;li&gt;É importante seguir o fluxo: escrever a funcionalidade &amp;gt; implementar os steps &amp;gt; implementar o código para programar orientado ao comportamento. E, ao longo desse processo, rodar o behave para ver os testes pendentes, falhando e passando. Mas nunca se esqueça de refatorar o código. Nesse código de exemplo mesmo poderíamos ter desacoplado algumas coisas como a parte de autenticação (pode ser visto no código completo do &lt;a href="https://github.com/gabriellydeandrade/python-material/tree/master/tests/bdd/simple_bank_account" rel="noopener noreferrer"&gt;github&lt;/a&gt;) e se ao rodar os testes eles passarem, ainda estaríamos garantindo que os comportamentos permanecem os mesmos.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://behave.readthedocs.io/en/latest/context_attributes.html?highlight=hooks#context-attributes" rel="noopener noreferrer"&gt;Utilize hooks para evitar steps repetidas nos testes de comportamento&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Aprender sobre as regras de negócio é tão importante quanto aprender sobre tecnologia. Lembre-se que nosso papel como profissional da área de tecnologia é resolver problemas de um certo domínio de negócio. Entender como essas regras funcionam são importantes para ajudar a pensar em cenários e corner cases nas validações.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Conclusão
&lt;/h2&gt;

&lt;p&gt;O BDD reforça o pensamento "Outside-in" (de fora para dentro) e é guiado a entrega de valor ao negócio. Os colaboradores então trabalham em conjunto no levantamento dos cenários que serão entregues e que automaticamente estão relacionados com a cobertura de testes do código em questão. &lt;/p&gt;

&lt;p&gt;Usar ou não BDD? Depende. Se for necessária interações entre diferentes personas (analista de negócios, desenvolvedores, testadores, stackholder) pode ser interessante principalmente pela escrita de um documento em linguagem natural. &lt;/p&gt;

&lt;p&gt;De toda forma é interessante saber que existe essa outra maneira de implementar testes e que tendo um documento comum que será utilizado tanto para validar os cenários do sistema tanto como definições dos critérios de aceitação entre os analistas de negócio é algo bem legal :)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A parte mais difícil de construir um sistema é decidir precisamente o que construir&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;– Fred Brooks, O Mítico Homem-Mês: Ensaios Sobre Engenharia de Software&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen4ls4vpepbcofv2dd3e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen4ls4vpepbcofv2dd3e.gif" alt="https://media.giphy.com/media/lD76yTC5zxZPG/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>testes</category>
      <category>bdd</category>
      <category>behave</category>
    </item>
    <item>
      <title>Testes em Python - Parte 1: Introdução</title>
      <dc:creator>Gabrielly de Andrade</dc:creator>
      <pubDate>Tue, 19 May 2020 01:22:52 +0000</pubDate>
      <link>https://dev.to/womakerscode/testes-em-python-parte-1-introducao-43ei</link>
      <guid>https://dev.to/womakerscode/testes-em-python-parte-1-introducao-43ei</guid>
      <description>&lt;p&gt;Essa é a primeira parte da série de testes em Python. &lt;/p&gt;

&lt;p&gt;A primeira parte tem por objetivo fazer uma introdução a testes automatizados utilizando o framework nativo do Python unnitest. Aqui, veremos alguns conceitos primordiais para escrever os primeiros casos de teste.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pré-requisito
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Conhecimento básico de Python&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Roteiro
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;O que são testes&lt;/li&gt;
&lt;li&gt;Teste unitário (de unidade)&lt;/li&gt;
&lt;li&gt;Conceitos&lt;/li&gt;
&lt;li&gt;Exemplos&lt;/li&gt;
&lt;li&gt;Considerações adicionais&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. O que são testes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Motivação
&lt;/h3&gt;

&lt;p&gt;Ao escrever nossos programas, precisamos validar se o resultado que ele produz é o &lt;strong&gt;correto&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Se tratando dos primeiros programas que escrevemos, normalmente rodamos o nosso código e passamos diversos valores para verificar se o que ele retorna é o esperado. Quando isso não acontece, temos que fazer uma varredura pelo nosso código e tentar entender o que ocorreu. Pode ter sido exibido &lt;a href="https://docs.python.org/3/tutorial/errors.html" rel="noopener noreferrer"&gt;algum erro ou exceção ao usuário&lt;/a&gt; ou o programa retornar o valor errado e não exibir erro nenhum (ocasionado por erro de lógica na maioria das vezes). Nos dois casos, podemos usar o &lt;a href="https://docs.python.org/3/library/pdb.html" rel="noopener noreferrer"&gt;modo debug&lt;/a&gt; (que são facilitados por uma IDE¹) ou adicionar alguns &lt;em&gt;outputs&lt;/em&gt; no terminal usando a função &lt;em&gt;print.&lt;/em&gt; Com isso, podemos identificar o problema e corrigir nosso código para retornar o que é esperado. &lt;strong&gt;Isso é um teste manual.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IDE¹ (Integrated Development Environment) do português ambiente integrado de desenvolvimento. É um ambiente que nos ajuda a desenvolver nossos códigos sendo possível não só utilizar como editor de texto, mas também facilitar execução, debbug e integração com outras ferramentas. Em Python, o &lt;a href="https://www.jetbrains.com/pt-br/pycharm/" rel="noopener noreferrer"&gt;Pycharm&lt;/a&gt; é uma IDE muito utilizada e difundida.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Repare que isso se torna extremamente cansativo e está sujeito a falhas fazer validações dessa forma. Assim, não garantimos a qualidade do nosso programa de forma facilitada se mais funcionalidades forem adicionadas pois todas as vezes teríamos que executar nosso programa e verificar os cenários na mão.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Testes automatizados
&lt;/h3&gt;

&lt;p&gt;Testes automatizados são cenários que escrevemos através de linha de código simulando os testes manuais que antes eram feitos. Poupando assim tempo e esforço nessas verificações.&lt;/p&gt;

&lt;p&gt;Escrever testes automatizados vai muito além do que somente escrever cenários para validar que o código faça o que deveria fazer. O teste também nos ajuda a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deixar o código mais limpo (ajuda na remoção de &lt;a href="https://www.quora.com/What-are-some-common-Python-code-smells-and-how-should-one-refactor-them" rel="noopener noreferrer"&gt;code smell&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Garantir maior manutenção do código&lt;/li&gt;
&lt;li&gt;Servir como documentação: de forma visual conseguimos saber quais são os cenários esperados e os tratamentos em caso de erro olhando o arquivo de teste&lt;/li&gt;
&lt;li&gt;Evitar trabalho manual (um teste automatizado é muito melhor do que um teste manual com &lt;em&gt;print&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Evitar bug's&lt;/li&gt;
&lt;li&gt;Prover feedback para quem está desenvolvendo a aplicação: conseguimos saber se o programa está retornando o que é esperado mesmo alterando a lógica do programa principal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Teste unitário
&lt;/h2&gt;

&lt;p&gt;Um teste unitário é a maneira de você testar as pequenas unidades existentes em seu código. Também é chamado de teste de unidade.&lt;/p&gt;

&lt;p&gt;Para nos ajudar com os testes, iremos utilizar o framework built-in (nativo) do Python chamado &lt;a href="https://docs.python.org/3/library/unittest.html" rel="noopener noreferrer"&gt;unittest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 1:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;No exemplo acima, estamos testando uma pequena unidade do nosso código, estamos validando um cenário da função chamada &lt;strong&gt;square&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Repare que todo o contexto de teste está sendo utilizado dentro de uma &lt;a href="https://docs.python.org/pt-br/3/tutorial/classes.html" rel="noopener noreferrer"&gt;classe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mas, para entender melhor como funciona o exemplo acima, vamos primeiro entender alguns conceitos.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Conceitos
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Preparação do teste
&lt;/h3&gt;

&lt;p&gt;Nessa etapa é feita a preparação do ambiente para fazer o teste rodar. Essa preparação é chamada de &lt;strong&gt;fixture&lt;/strong&gt; e consiste nos itens necessários para um ou mais testes serem executados. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exemplo: para conseguir testar uma função que lê um determinado arquivo precisamos de um arquivo no nosso ambiente de teste para ser possível fazer a validação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pode conter o uso dos métodos &lt;a href="https://riptutorial.com/python/example/13280/test-setup-and-teardown-within-a-unittest-testcase" rel="noopener noreferrer"&gt;setUp() e tearDown()&lt;/a&gt;. Isso são ações que são executadas antes e depois, respectivamente, da execução de cada um dos cenários de teste.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Caso de teste
&lt;/h3&gt;

&lt;p&gt;É o conjunto de cenários que queremos testar. &lt;br&gt;
Em um caso de teste agrupamos todos os pequenos cenários que queremos validar de forma unitária que fazem parte do mesmo contexto.&lt;/p&gt;

&lt;p&gt;Com o framework unittest, usamos uma classe base chamada &lt;strong&gt;TestCase&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Asserções
&lt;/h3&gt;

&lt;p&gt;Asserções servem para validar que o cenário do seu código ocorreu como o esperado.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;assert&lt;/strong&gt; é um comando built-in (nativo) do Python. E podemos usar da seguinte forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmm6gdfastl51j2t95xcm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmm6gdfastl51j2t95xcm.png" alt="Assert built-in Python"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que na primeira asserção é comparada se a soma de 1+1 é igual a 2. Como o resultado é verdadeiro, nada é exibido no console.&lt;/p&gt;

&lt;p&gt;Já na asserção seguinte, há uma falha e um erro é levantado do tipo &lt;strong&gt;AssertionError&lt;/strong&gt; (erro de asserção).&lt;/p&gt;

&lt;p&gt;O framework &lt;strong&gt;unittest&lt;/strong&gt; facilita nessas asserções que vamos precisar fazer. As asserções completas podem ser vistas em sua própria &lt;a href="https://docs.python.org/3/library/unittest.html#assert-methods" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 Test Runner
&lt;/h3&gt;

&lt;p&gt;Permite rodar a execução dos testes. O test runner orquestra a execução dos testes e exibe para o usuário os resultados.&lt;/p&gt;

&lt;p&gt;Além de utilizar o &lt;a href="https://docs.python.org/3/library/unittest.html#command-line-interface" rel="noopener noreferrer"&gt;test runner do unittest&lt;/a&gt; outros podem ser utilizados como o &lt;a href="https://docs.pytest.org/en/latest/usage.html" rel="noopener noreferrer"&gt;pytest&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.5 Coverage
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://coverage.readthedocs.io/en/coverage-5.1/" rel="noopener noreferrer"&gt;Coverage&lt;/a&gt; remete a cobertura de testes, ou seja, o quanto o seu código está sendo testado.&lt;/p&gt;

&lt;p&gt;Executando o coverage, conseguimos saber quais trechos de código foram testados e quais não foram. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ATENÇÃO:&lt;/strong&gt; 100% de cobertura é diferente de ter todos os cenários testados! Além de testar o fluxo principal do programa também precisamos testar casos inesperados (veremos mais adiante na série "Testes em Python").&lt;/p&gt;

&lt;h3&gt;
  
  
  3.6 Mock
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.python.org/3/library/unittest.mock.html" rel="noopener noreferrer"&gt;Mock&lt;/a&gt; é uma biblioteca utilizada em testes quando queremos simular um determinado comportamento. Mock em inglês é literalmente "imitar". Ele é bastante utilizado quando nosso código se comunica com elementos externos como por exemplo: conexão com o banco de dados e chamadas HTTP. &lt;/p&gt;

&lt;p&gt;Se não for utilizado o mock, no momento que executarmos nosso código chamadas reais irão acontecer para a rede ou banco de dados, por exemplo (veremos mais adiante na série "Testes em Python").&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Exemplos
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/o0vwzuFwCGAFO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/o0vwzuFwCGAFO/giphy.gif" alt="GIF cat typing in computer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cat writing: show me the code!&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Vamos entender o funcionamento do Exemplo 1
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;Na primeira linha importamos os itens necessários do framework unittest. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;main()&lt;/code&gt; ⇒  chamamos o &lt;strong&gt;Test Runner&lt;/strong&gt; da biblioteca para ao rodar nosso código Python (python meu_arquivo.py).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TestCase&lt;/code&gt; ⇒ fornece a estrutura necessária para montar o caso de teste.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;O próximo bloco se refere ao nosso código com o trecho que queremos validar&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Criamos uma classe de teste herdando o &lt;code&gt;TestCase&lt;/code&gt; do unittest e seus métodos são os &lt;strong&gt;casos de teste&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Repare que dentro da classe escrevemos de modo descritivo o cenário que está sendo testado (estamos testando se o nosso código retorna o quadrado de dois). Depois fazemos uma &lt;strong&gt;asserção&lt;/strong&gt; usando &lt;code&gt;assertEqual&lt;/code&gt; comparando se a chamada da função &lt;strong&gt;square&lt;/strong&gt; retorna o esperado, que é 4. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Repare que o nome da classe e o cenário começam com a palavra "test". O nome "test" é obrigatório ser iniciado para as funções de teste, mas opcionais para a classe (no entanto é recomendado por questões de clareza).&lt;/p&gt;

&lt;p&gt;Por fim, o último trecho chama o &lt;strong&gt;main()&lt;/strong&gt; do unittest quando o arquivo python for executado.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Para rodar o exemplo basta rodar como um arquivo python normalmente (no meu caso eu salvei em um arquivo my_first_test.py)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

python my_first_test.py


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

&lt;/div&gt;

&lt;p&gt;No console será exibido que 1 teste foi executado e ele está com o status OK, ou seja, o teste passou.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwmnndym3cif6v5laub3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwmnndym3cif6v5laub3b.png" alt="First test passed with success"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos adicionar outro cenário de teste para simular um erro&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Executando novamente o código acima temos o seguinte retorno:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fasekm37dde9oli4yz1hi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fasekm37dde9oli4yz1hi.png" alt="Simulating error: test did not pass"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que adicionando o cenário &lt;strong&gt;test_if_returns_square_of_4&lt;/strong&gt; executamos no total 2 testes e justamente esse cenário falhou. Isso por que chamando a função &lt;strong&gt;square&lt;/strong&gt; ela retorna 16 e estamos tentando validar que o esperado a ser retornado é 4. &lt;/p&gt;

&lt;p&gt;Corrigindo o nosso código, ele deveria ficar da seguinte forma:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_returns_square_of_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Observação:&lt;/strong&gt; Os testes nos ajudam a identificar problemas no nosso código principal, mas o próprio cenário de teste também está suscetível a erros. Devemos sempre validar se o teste está bem escrito e se realmente testando o cenário esperado. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observação 2:&lt;/strong&gt; Note que existe outra forma de calcular o quadrado de um número. No exemplo acima calculamos como &lt;code&gt;x*x&lt;/code&gt; mas perceba que se mudarmos a forma que é calculada para &lt;code&gt;x ** 2&lt;/code&gt; o resultado retornado é o mesmo e isso não afeta os nossos testes. Se executarmos novamente veremos que os cenários continuarão passando.&lt;/p&gt;

&lt;p&gt;Um teste não deve enviesar a forma como é implementado o código. Por isso se efetuarmos refatorações² no código, rodando os testes conseguimos garantir se o comportamento é o mesmo retornado pelo código anterior.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Refatoração² é o efeito de você mudar a implementação do código sem afetar o seu retorno (comportamento externo). A implementação é mudada de forma que o código fique mais organizado, mais limpo e melhor estruturado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; É uma boa prática separar o código principal do código dos testes, veremos isso no próximo exemplo.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Detecção de divisão
&lt;/h3&gt;

&lt;p&gt;O exemplo abaixo mostra uma função que detecta uma divisão. Se a divisão for possível deverá retornar &lt;strong&gt;verdadeiro&lt;/strong&gt;, se não deverá retornar &lt;strong&gt;falso&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Essa função está armazenada dentro de um arquivo chamado &lt;strong&gt;division_detect.py&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;numerator&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.1&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Vamos escrever um cenário de testes para essa função. Para isso, vamos criar um arquivo chamado &lt;strong&gt;test_division_detect.py&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Apesar dos testes rodarem independente do nome do arquivo, é uma boa prática escrever o arquivo de teste começando com a palavra &lt;strong&gt;"test"&lt;/strong&gt; assim como nossa classe.&lt;/p&gt;

&lt;p&gt;O arquivo de teste possui o seguinte esqueleto:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDivisionDetect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_true_if_division_by_number_is_successful&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para escrever esse cenário de teste, queremos validar se a nossa função &lt;code&gt;division_detect&lt;/code&gt; retorna &lt;code&gt;true&lt;/code&gt; se a divisão for bem sucedida. &lt;/p&gt;

&lt;p&gt;A questão é: qual número vamos usar para fazer esse teste? Poderíamos escolher dois números aleatórios como 10 para o numerador e 2 para o denominador. Importando a função e comparando se o resultado retornado é verdadeiro com a asserção &lt;code&gt;assertTrue&lt;/code&gt; temos o seguinte cenário de teste:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDivisionDetect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_true_if_division_by_number_is_successful&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.3&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No teste acima, vamos validar se a divisão de  &lt;code&gt;10/2&lt;/code&gt; é considerada válida. &lt;/p&gt;

&lt;p&gt;Vamos rodar o arquivo de teste com o comando abaixo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

python &lt;span class="nt"&gt;-m&lt;/span&gt; unittest test_division_detect.py


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

&lt;/div&gt;

&lt;p&gt;Como sabemos, o resultado da operação é 5 e &lt;code&gt;bool(5)&lt;/code&gt; é verdadeiro&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcqo7xfnrsvcdo0rczfcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcqo7xfnrsvcdo0rczfcl.png" alt="Result of bool(5) is true"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Veremos que um teste rodou e o resultado foi &lt;strong&gt;OK&lt;/strong&gt; (o cenário de teste passou)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4flju09uc6w112key7zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4flju09uc6w112key7zv.png" alt="Test passed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mas, o que aconteceria se a gente mudasse o código principal no arquivo &lt;strong&gt;division_detect.py&lt;/strong&gt; para esse código:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;numerator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Claro que aqui estamos forçando um pouco a barra e alterando completamente a lógica do código principal, mas se os testes forem executados novamente o teste vai passar. &lt;/p&gt;

&lt;p&gt;Nesse caso o teste passou mas isso não é garantia que o cenário está sendo validado de fato. Para garantir que a divisão está sendo feita  vamos gerar números aleatórios tanto para o numerador quanto para o denominador. Para isso vamos usar a função do python &lt;code&gt;randint&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;randint&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDivisionDetect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_true_if_division_by_number_is_successful&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.5&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Repare que tanto para o numerador como para o denominador está sendo gerado números aleatórios entre 0 e 100000 e se executarmos novamente o arquivo &lt;strong&gt;division_detect.py&lt;/strong&gt; que foi escrito no &lt;strong&gt;Código 4.2.4&lt;/strong&gt; vamos ver que o código não vai passar. Vamos voltar o código para que fique o mesmo do &lt;strong&gt;Código 4.2.1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Olhando novamente para o cenário de teste, o que aconteceria se o denominador sorteado fosse 0?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3oFzmdjqH15YebLQ52/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oFzmdjqH15YebLQ52/giphy.gif" alt="GIF infinity loop made by snake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É, aqui temos um problema. A divisão de qualquer número por zero é &lt;strong&gt;indefinida&lt;/strong&gt;!* &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;*&lt;a href="https://pt.khanacademy.org/math/algebra/introduction-to-algebra/division-by-zero/v/why-dividing-by-zero-is-undefined" rel="noopener noreferrer"&gt;Divisão por zero é uma operação que tende ao infinito e portanto é dada como indefinida.&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos adicionar um novo cenário de teste para validar isso, dessa vez vamos forçar que o denominador seja zero.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;randint&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDivisionDetect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_true_if_division_by_number_is_successful&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_false_if_division_by_number_is_not_possible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.6&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Rodando novamente esse arquivo de testes, vamos receber o seguinte retorno&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnfn9yzlxgnig0nohesfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnfn9yzlxgnig0nohesfm.png" alt="Zero division error: test failed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que dois testes foram executados, o que é correto pois escrevemos dois cenários de teste. Mas um dos testes, o &lt;code&gt;test_it_returns_false_if_division_by_number_is_not_possible&lt;/code&gt;, falhou. Isso pois aconteceu um erro chamado &lt;code&gt;ZeroDivisionError&lt;/code&gt; (&lt;a href="https://docs.python.org/3/library/exceptions.html#ZeroDivisionError" rel="noopener noreferrer"&gt;https://docs.python.org/3/library/exceptions.html#ZeroDivisionError&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Olhando nosso código principal, vemos que não está sendo feito nenhum tipo de tratamento para esse erro. Vamos refatorar então o nosso código para lidar com esse erro, para isso vamos usar o &lt;a href="https://docs.python.org/3/tutorial/errors.html#handling-exceptions" rel="noopener noreferrer"&gt;statement try/except do Python&lt;/a&gt;. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;numerator&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Código 4.2.7&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No código acima primeiro tentamos fazer a divisão entre os dois parâmetros recebidos, se a operação for bem sucedida irá retornar &lt;code&gt;True&lt;/code&gt;, mas se acontecer uma exceção do tipo &lt;code&gt;ZeroDivisionError&lt;/code&gt; irá retornar &lt;code&gt;Falso&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Rodando novamente os testes com &lt;code&gt;python -m unittest test_division_detect.py&lt;/code&gt; vamos ver que os dois cenários passaram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcjvcifhn4fjbnr9bjq2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcjvcifhn4fjbnr9bjq2b.png" alt="Two tests passed with success"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Repare que nosso código original não estava preparado para uma divisão por zero. Isso é chamado de corner case, ou seja, são cenários que podem acontecer fora do padrão esperado. Para tratar esse cenário tivemos que adicionar um tratamento com as exceções do Python.&lt;/p&gt;

&lt;p&gt;No arquivo de teste, para os dois cenários que estamos testando, estamos repetindo &lt;code&gt;randint(0, 100000)&lt;/code&gt; . Como queremos pegar sempre um numerador aleatório para todos os testes, podemos utilizar o &lt;code&gt;setUp()&lt;/code&gt;(&lt;a href="https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp" rel="noopener noreferrer"&gt;https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp&lt;/a&gt;) que é uma inicialização que é executada sempre no início de cada cenário de teste. &lt;/p&gt;

&lt;p&gt;Por fim, chegaremos ao código abaixo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;randint&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;division_detect&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDivisionDetect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random_numerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_true_if_division_by_number_is_successful&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random_numerator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;randint&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="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_it_returns_false_if_division_by_number_is_not_possible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;division_detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random_numerator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Repare que o denominador no primeiro cenário sorteia um número entre 1 e 100000, pois estamos querendo validar um cenário onde a divisão é bem sucedida.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Considerações adicionais
&lt;/h2&gt;

&lt;p&gt;Aqui, listo alguns pontos que devem ser levados em consideração no momento de programar e testar seus códigos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Divida para conquistar: Mantenha a estrutura de arquivos organizadas. Se um projeto é grande, é sempre uma boa prática dividir em arquivos menores (isso facilita a manutenção e legibilidade)&lt;/li&gt;
&lt;li&gt;Um teste também deve ser limpo igual ao código principal (Clean Code - Robert C. Martin)&lt;/li&gt;
&lt;li&gt;Use nomes descritivos para as funções de teste, mesmo que seja um nome muito longo&lt;/li&gt;
&lt;li&gt;Pense em corner cases (cenários fora do padrão esperado), igual fizemos na divisão por zero no exemplo 2&lt;/li&gt;
&lt;li&gt;Um teste não deve engessar a implementação do seu código, igual vimos no exemplo 1 (o quadrado de um número pode ser feito de duas formas)&lt;/li&gt;
&lt;li&gt;Escrever em pequenas unidades ajudam a testar o código e a melhorar sua clareza&lt;/li&gt;
&lt;li&gt;Refatore: Sempre que puder melhorar seu código melhore! (Lema de escoteiro)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;De acordo com a &lt;a href="https://www.python.org/dev/peps/pep-0020/#id3" rel="noopener noreferrer"&gt;PEP20&lt;/a&gt;³:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Errors should never pass silently&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PEP³ (do inglês (Python Enhancement Proposals) se refere a propostas de como utilizar o Python da melhor forma: &lt;a href="https://www.python.org/dev/peps/" rel="noopener noreferrer"&gt;https://www.python.org/dev/peps/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusão
&lt;/h2&gt;

&lt;p&gt;Testes são uma maneira de garantir que o seu programa &lt;strong&gt;retorna o&lt;/strong&gt; &lt;strong&gt;resultado esperado.&lt;/strong&gt; Além disso, garante maior qualidade no produto que está sendo entregue. Os testes também ajudam que a equipe de desenvolvedores entendam os cenários que acontecem na aplicação e ajudam a identificar cenários fora do padrão. Testando nosso código, conseguimos encontrar também maneiras de deixar nosso código mais limpo e conciso, facilitando assim na manutenção futura e a evitar bugs que possam ocorrer. É melhor que um teste pegue o erro do que o cliente usando o seu produto :) &lt;/p&gt;

&lt;p&gt;Essa foi a primeira série de Testes em Python, espero que tenha ficado claro o entendimento dessa introdução e em breve teremos mais publicações sobre esse assunto. Dúvidas podem ser colocadas no comentário e lembre-se que testar faz parte do processo de escrever um bom código, segundo o programador Pete Goodliffe&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Um bom código não surge do nada. [...] Para ter um bom código é preciso trabalhar nele. Arduamente. E você só terá um código bom se realmente se importar com códigos bons."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como Ser Um Programador Melhor: um Manual Para Programadores que se Importam com Código (Pete Goodliffe)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen4ls4vpepbcofv2dd3e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen4ls4vpepbcofv2dd3e.gif" alt="Gif that's all folks"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>testes</category>
      <category>iniciante</category>
      <category>womenintech</category>
    </item>
    <item>
      <title>Celebração Hacktoberfest - Meetup Open Source RJ</title>
      <dc:creator>Gabrielly de Andrade</dc:creator>
      <pubDate>Tue, 31 Dec 2019 22:05:49 +0000</pubDate>
      <link>https://dev.to/womakerscode/celebracao-hacktoberfest-meetup-open-source-rj-9ed</link>
      <guid>https://dev.to/womakerscode/celebracao-hacktoberfest-meetup-open-source-rj-9ed</guid>
      <description>&lt;p&gt;No dia 17 de outubro de 2019, aconteceu o primeiro meetup de Open Source da comunidade WoMakersCode no Rio de Janeiro. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;O que rolou no meetup?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Com o objetivo de incentivar que mais mulheres participem da maior celebração do ano sobre Open Source, preparamos pequenas talks explicando alguns conceitos da filosofia, o que é a celebração Hacktoberfest, como começar a contribuir, a importância de contribuir com projetos inclusivos e exemplos de projetos.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;- Introdução ao Mundo Open Source&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Começamos a noite com a palestra da &lt;a href="https://www.linkedin.com/in/daianealvesrj/"&gt;Daiane Alves&lt;/a&gt; e &lt;a href="https://www.linkedin.com/in/gabriellydeandrade/"&gt;Gabrielly de Andrade&lt;/a&gt; sobre &lt;em&gt;Introdução ao Mundo Open Source&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;O termo Open Source veio com a chegada da OSI &lt;em&gt;(Open Source Initiative)&lt;/em&gt; que diz respeito a um código aberto, colaborativo, que está mantido seguindo &lt;a href="https://opensource.org/osd"&gt;10 critérios&lt;/a&gt; e uma licença de uso. Essa filosofia possui mais liberdade comparada ao &lt;a href="https://www.fsf.org/"&gt;Software Livre&lt;/a&gt; e foi apresentada suas principais diferenças.&lt;/p&gt;

&lt;p&gt;Na mesma linha, foi mostrado por que o Open Source é importante e por que celebrações como a &lt;a href="https://hacktoberfest.digitalocean.com"&gt;Hacktoberfest&lt;/a&gt; são organizadas. E isso é uma maneira de agradecer à comunidade por todas as colaborações em projetos, contribuindo com uma maior qualidade e segurança do software utilizado em empresas.&lt;/p&gt;

&lt;p&gt;Como benefício de participar da celebração - além da camiseta - você pode aprimorar suas habilidades, melhorar seu currículo e conhecer projetos/pessoas novas.&lt;/p&gt;

&lt;p&gt;Além disso, grandes empresas como a &lt;a href="https://www.microsoft.com/pt-br"&gt;Microsoft&lt;/a&gt; possuem projetos que podem receber contribuições que não são apenas código, você também pode contribuir com &lt;a href="https://docs.microsoft.com/pt-br/"&gt;documentação&lt;/a&gt;. E o mais legal disso tudo é que não importa o seu nível de conhecimento, seja iniciante ou avançado a celebração também é pra você!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://drive.google.com/file/d/12yBI4Na4Q8VWrwFfk7xB6eVKNFvVJ5cB/view?usp=sharing"&gt;Link da apresentação&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;- Apoiando intencionalmente projetos com diversidade e colaborando na prática&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Nessa palestra a &lt;a href="https://www.linkedin.com/in/camilla-martins-603344115/"&gt;Camilla Martins&lt;/a&gt; mostrou como contribuir em projetos sociais e de diversidade e nos deu exemplos de alguns projetos para contribuir (vide link da apresentação abaixo). &lt;/p&gt;

&lt;p&gt;Ela também reforçou a importância de participar de celebrações como a Hacktudo e de contriuir com projetos Open Source. No final, ela mostrou na prática como contribuir para o projeto &lt;a href="https://github.com/NodeGirlsCode/miga"&gt;miga&lt;/a&gt;, desde o momento de fazer um fork do projeto (clone para o seu github) até o momento de contribuir com um PR (contribuição de uma modificação que precisa ser revisada e aceitada antes de ser incluída no projeto)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/1_ltp7fS_jXuxcJFjiQMSoEPHi4_82iqV8km-TNV3qmo/edit?usp=sharing"&gt;Link da apresentação&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;- Aplicativo Tá tudo bem? e o uso da tecnologia como forma de prevenção ao suicídio&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;E para fechar com chave de ouro, a &lt;a href="https://www.linkedin.com/in/bezzocoaline/"&gt;Aline Bezzoco&lt;/a&gt; compartilhou conosco sobre o Aplicativo "Tá tudo bem?" e  a ideia por trás do projeto. &lt;/p&gt;

&lt;p&gt;O objetivo do aplicativo é oferecer apoio e suporte para pessoas que estejam passando por algum problema emocional, como a depressão. Com o aplicativo você consegue ter acesso a um botão de emergência que faz uma chamada direto para o CVV (Centro de Valorização da Vida), registrar suas razões para viver, obter informações a cerca de alguns mitos sobre a depressão, obter notificações diárias de apoio emocinal e ainda conseguir usar técnicas de respiração usando a sessão "Respire". &lt;/p&gt;

&lt;p&gt;Além disso, ela falou também sobre a API que lista todas as universidades e instituições que possuem atendimento psicológico gratuito. A API está aberta no github e pode ter contribuições aqui: &lt;a href="https://github.com/bezzocoaline/tatudobem-api"&gt;https://github.com/bezzocoaline/tatudobem-api&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Quem ajudou?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Esse evento não teria acontecido sem a ajuda das voluntárias da WomakersCode e as palestrantes que se ofereceram a compartilhar conteúdo. Realizamos isso tudo por amor a comunidade e as mulheres que dividimos conhecimento.&lt;/p&gt;

&lt;p&gt;Organização&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/in/daianealvesrj/"&gt;Daiane Alves&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/gabriellydeandrade/"&gt;Gabrielly de Andrade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/marianacoelhoneg/"&gt;Mariana Coelho&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Palestrantes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://www.linkedin.com/in/camilla-martins-603344115/"&gt;Camilla Martins&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/bezzocoaline/"&gt;Aline Bezzoco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/in/daianealvesrj/"&gt;Daiane Alves&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/gabriellydeandrade/"&gt;Gabrielly de Andrade&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Quem apoiou?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Queremos agradecer nossos apoioadores que sem eles esse encontro não teria sido possível:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.totvs.com/"&gt;Totvs&lt;/a&gt; que cedeu o espaço e forneceu coffee break&lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.caelum.com.br"&gt;Caelum&lt;/a&gt; que forneceu um curso online da &lt;a href="https://www.alura.com.br/"&gt;Alura&lt;/a&gt; para sorteio &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.jetbrains.com/"&gt;Jetbrains&lt;/a&gt; que nos forneceu uma licença para sorteio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obrigada a tod@s e até a próxima&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
