{"title":"Escrevendo sua primeira aplicação Django, parte 5","version":"4.0","locale":"pt-br","docname":"intro/tutorial05","url":"/pt-br/4.0/intro/tutorial05/","canonical":"https://djangodocs.dev/pt-br/4.0/intro/tutorial05/","summary":"This tutorial begins where Tutorial 4 left off. We’ve built a web-poll application, and we’ll now create some automated tests for it. Onde obter ajuda: Se tiver…","html":"<h1>Escrevendo sua primeira aplicação Django, parte 5<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-5\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This tutorial begins where <a class=\"reference internal\" href=\"/pt-br/4.0/intro/tutorial04/\"><span class=\"doc\">Tutorial 4</span></a> left off.\nWe’ve built a web-poll application, and we’ll now create some automated tests\nfor it.</p>\n<aside class=\"admonition-where-to-get-help admonition\">\n<p class=\"admonition-title\">Onde obter ajuda:</p>\n<p>Se tiver problemas enquanto caminha por este tutorial, por favor consulte a seção <a class=\"reference internal\" href=\"/pt-br/4.0/faq/help/\"><span class=\"doc\">Obtendo ajuda</span></a> da FAQ.</p>\n</aside>\n<section id=\"introducing-automated-testing\">\n<h2>Apresentando testes automatizados<a class=\"heading-anchor\" href=\"#introducing-automated-testing\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"what-are-automated-tests\">\n<h3>O que são testes automatizados?<a class=\"heading-anchor\" href=\"#what-are-automated-tests\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Testes são rotinas que verificam o funcionamento do seu código.</p>\n<p>Testes funcionam em diferentes níveis. Alguns testes podem ser aplicados a um pequeno detalhe (<em>um determinado método de um modelo retorna o valor esperado?</em>) enquanto outros examinam o funcionamento global do software (<em>a sequência de entradas do usuário no site produz o resultado desejado?</em>). Isso não é diferente do teste que você fez anteriormente no <a class=\"reference internal\" href=\"/pt-br/4.0/intro/tutorial02/\"><span class=\"doc\">Tutorial 2</span></a>, usando o <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a> para examinar o comportamento de um método, ou executar a aplicação e entrar com um dado para verificar como ele se comporta.</p>\n<p>A diferença em testes <em>automatizados</em> é que o trabalho de testar é feito para você pelo sistema. Você cria um conjunto de testes uma vez, e então conforme faz mudanças em sua aplicação, você pode checar se o seu código continua funcionando como você originalmente pretendia, sem ter que gastar tempo executando o teste manualmente.</p>\n</section>\n<section id=\"why-you-need-to-create-tests\">\n<h3>Porque você precisa criar testes<a class=\"heading-anchor\" href=\"#why-you-need-to-create-tests\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Então, por que criar testes, e por que agora?</p>\n<p>Você pode achar que já tem coisa suficiente no seu prato apenas aprendendo Python/Django, e tendo ainda outra coisa para aprender e fazer pode parecer exagerado e talvez desnecessário. Afinal, nossa aplicação de enquetes está funcionando muito bem agora; passar pelo trabalho de criar testes automatizados não vai fazê-la funcionar melhor. Se criar a aplicação de enquetes é a última coisa que você vai programar em Django, então realmente, você não precisa saber sobre como criar testes automatizados. Mas, se esse não é o caso, agora é uma excelente hora para aprender.</p>\n<section id=\"tests-will-save-you-time\">\n<h4>Teste vão salvar seu tempo<a class=\"heading-anchor\" href=\"#tests-will-save-you-time\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Até um certo ponto, ‘verificar que parece funcionar’ será um teste satisfatório. Em uma aplicação mais sofisticada, você pode ter dúzias de interações complexas entre componentes.</p>\n<p>A change in any of those components could have unexpected consequences on the\napplication’s behavior. Checking that it still ‘seems to work’ could mean\nrunning through your code’s functionality with twenty different variations of\nyour test data to make sure you haven’t broken something - not a good use\nof your time.</p>\n<p>Isso é verdade especialmente quando testes automatizados poderiam fazer isso pra você em segundos. Se alguma coisa errada acontecer, os testes também ajudarão em identificar o código que está causando o comportamento inesperado.</p>\n<p>Às vezes pode parece uma tarefa para afastar você da sua produtividade e criatividade em programar para enfrentar o trabalho nada excitante e glamouroso de escrever testes, particularmente quando você sabe que seu código está funcionando corretamente.</p>\n<p>No entanto, a tarefa de escrever testes é muito mais satisfatório do que gastar horas testando sua aplicação manualmente, ou tentando identificar a causa de um problema recém-introduzido.</p>\n</section>\n<section id=\"tests-don-t-just-identify-problems-they-prevent-them\">\n<h4>Testes não só identificam problemas, mas também os previnem<a class=\"heading-anchor\" href=\"#tests-don-t-just-identify-problems-they-prevent-them\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>É um erro pensar nos testes simplesmente como um aspecto negativo do desenvolvimento.</p>\n<p>Sem testes, o objetivo ou comportamento desejado de uma aplicação pode não ser tão claro. Mesmo quando é seu próprio código, algumas vezes você vai se encontrar bisbilhotando nele tentando descobrir exatamente o que está fazendo.</p>\n<p>Testes mudam isso; eles mostram seu código por dentro, e quando algumas coisas saem errado, eles revelam parte do erro.</p>\n</section>\n<section id=\"tests-make-your-code-more-attractive\">\n<h4>Testes fazem seu código mais atraente.<a class=\"heading-anchor\" href=\"#tests-make-your-code-more-attractive\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>You might have created a brilliant piece of software, but you will find that\nmany other developers will refuse to look at it because it lacks tests; without\ntests, they won’t trust it. Jacob Kaplan-Moss, one of Django’s original\ndevelopers, says “Code without tests is broken by design.”</p>\n<p>Assim, esses outros desenvolvedores procuram ver os testes do seu software antes de levar a sério, e isso é uma outra razão para você iniciar a escrita dos testes.</p>\n</section>\n<section id=\"tests-help-teams-work-together\">\n<h4>Testes ajudam as equipes a trabalharem juntos<a class=\"heading-anchor\" href=\"#tests-help-teams-work-together\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Os pontos anteriores foram escritos do ponto de vista de um único desenvolvedor mantendo uma aplicação. Aplicações complexas serão mantidas por times. Testes garantem que seus colegas de trabalho não quebrem acidentalmente o seu código (e que você não quebre o deles sem saber). Se você deseja trabalhar como um programador Django, deve ser bom escrevendo testes!</p>\n</section>\n</section>\n</section>\n<section id=\"basic-testing-strategies\">\n<h2>Estratégias básicas de testes<a class=\"heading-anchor\" href=\"#basic-testing-strategies\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Há várias maneiras de abordar a escrita de testes.</p>\n<p>Some programmers follow a discipline called “<a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Test-driven_development\">test-driven development</a>”; they\nactually write their tests before they write their code. This might seem\ncounter-intuitive, but in fact it’s similar to what most people will often do\nanyway: they describe a problem, then create some code to solve it. Test-driven\ndevelopment formalizes the problem in a Python test case.</p>\n<p>Comumente, um novato em testes irá criar algum código e depois decidir que ele deveria ser testado. Talvez seria melhor escrever alguns testes antes, mas nunca é tarde para começar.</p>\n<p>Às vezes é difícil saber por onde devemos começar a escrever testes. Se você tiver escrito milhares de linhas em Python, escolher algo para testar pode não ser fácil. Nesse caso, é interessante escrever seu primeiro teste na próxima vez que você fizer alguma alteração, seja a adição de uma nova função ou correção de um bug.</p>\n<p>Então vamos fazer isso a partir de agora.</p>\n</section>\n<section id=\"writing-our-first-test\">\n<h2>Escrevendo nosso primeiro teste<a class=\"heading-anchor\" href=\"#writing-our-first-test\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"we-identify-a-bug\">\n<h3>Nós identificamos um bug<a class=\"heading-anchor\" href=\"#we-identify-a-bug\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Felizmente, há um pequeno bug na aplicação <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> para corrigirmos imediatamente: O método <code class=\"docutils literal notranslate\"><span class=\"pre\">Question.was_published_recently()</span></code> retorna <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>  se a <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> foi publicada dentro do último dia (o que está correto), mas também se o campo  <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> de <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> está no futuro (o que certamente não é o caso).</p>\n<p>Confirme o bug utilizando <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a> para verificar o método numa questão em que a data encontra-se no futuro:</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>shell\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py shell\n</code></pre></div></div></div>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">polls.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># create a Question instance with pub_date 30 days in the future</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">future_question</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"p\">(</span><span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">+</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># was it published recently?</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">future_question</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">()</span>\n<span class=\"go\">True</span>\n</code></pre></div>\n<p>Desde que coisas no futuro não são ‘recent’, isto é claramente um erro.</p>\n</section>\n<section id=\"create-a-test-to-expose-the-bug\">\n<h3>Criar um teste para expor um bug<a class=\"heading-anchor\" href=\"#create-a-test-to-expose-the-bug\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>O que nós fizemos no <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a> para testar o problema é exatamente o que podemos fazer em um teste automatizado, então vamos voltar para o teste automatizado</p>\n<p>Um lugar convencional para os testes da aplicação é o arquivo <code class=\"docutils literal notranslate\"><span class=\"pre\">tests.py</span></code>; o sistema de testes irá encontrar automaticamente todos os testes que estiverem em qualquer arquivo cujo o nome comece com <code class=\"docutils literal notranslate\"><span class=\"pre\">test</span></code>.</p>\n<p>Coloque o seguinte código no arquivo <code class=\"docutils literal notranslate\"><span class=\"pre\">tests.py</span></code> na aplicação <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/tests.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QuestionModelTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_was_published_recently_with_future_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        was_published_recently() returns False for questions whose pub_date</span>\n<span class=\"sd\">        is in the future.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">time</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">+</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n        <span class=\"n\">future_question</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"p\">(</span><span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">time</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"n\">future_question</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">(),</span> <span class=\"kc\">False</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Aqui criamos uma subclasse de <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.TestCase</span></code></a> com um método que cria uma instância de <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> com uma <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> no futuro. Então verificamos a saída de <code class=\"docutils literal notranslate\"><span class=\"pre\">was_published_recently()</span></code> - o qual <em>deve</em> ser False.</p>\n</section>\n<section id=\"running-tests\">\n<h3>Executando o teste<a class=\"heading-anchor\" href=\"#running-tests\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>No terminal, podemos rodar nosso teste:</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-1-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span><span class=\"nb\">test</span><span class=\"w\"> </span>polls\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-1-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py test polls\n</code></pre></div></div></div>\n<p>E você verá algo como:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">Creating</span> <span class=\"n\">test</span> <span class=\"n\">database</span> <span class=\"k\">for</span> <span class=\"n\">alias</span> <span class=\"s1\">&#39;default&#39;</span><span class=\"o\">...</span>\n<span class=\"n\">System</span> <span class=\"n\">check</span> <span class=\"n\">identified</span> <span class=\"n\">no</span> <span class=\"n\">issues</span> <span class=\"p\">(</span><span class=\"mi\">0</span> <span class=\"n\">silenced</span><span class=\"p\">)</span><span class=\"o\">.</span>\n<span class=\"n\">F</span>\n<span class=\"o\">======================================================================</span>\n<span class=\"n\">FAIL</span><span class=\"p\">:</span> <span class=\"n\">test_was_published_recently_with_future_question</span> <span class=\"p\">(</span><span class=\"n\">polls</span><span class=\"o\">.</span><span class=\"n\">tests</span><span class=\"o\">.</span><span class=\"n\">QuestionModelTests</span><span class=\"p\">)</span>\n<span class=\"o\">----------------------------------------------------------------------</span>\n<span class=\"n\">Traceback</span> <span class=\"p\">(</span><span class=\"n\">most</span> <span class=\"n\">recent</span> <span class=\"n\">call</span> <span class=\"n\">last</span><span class=\"p\">):</span>\n  <span class=\"n\">File</span> <span class=\"s2\">&quot;/path/to/mysite/polls/tests.py&quot;</span><span class=\"p\">,</span> <span class=\"n\">line</span> <span class=\"mi\">16</span><span class=\"p\">,</span> <span class=\"ow\">in</span> <span class=\"n\">test_was_published_recently_with_future_question</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"n\">future_question</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">(),</span> <span class=\"kc\">False</span><span class=\"p\">)</span>\n<span class=\"ne\">AssertionError</span><span class=\"p\">:</span> <span class=\"kc\">True</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">False</span>\n\n<span class=\"o\">----------------------------------------------------------------------</span>\n<span class=\"n\">Ran</span> <span class=\"mi\">1</span> <span class=\"n\">test</span> <span class=\"ow\">in</span> <span class=\"mf\">0.001</span><span class=\"n\">s</span>\n\n<span class=\"n\">FAILED</span> <span class=\"p\">(</span><span class=\"n\">failures</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"n\">Destroying</span> <span class=\"n\">test</span> <span class=\"n\">database</span> <span class=\"k\">for</span> <span class=\"n\">alias</span> <span class=\"s1\">&#39;default&#39;</span><span class=\"o\">...</span>\n</code></pre></div>\n<aside class=\"admonition-different-error admonition\">\n<p class=\"admonition-title\">Erro diferente?</p>\n<p>Se no lugar disso, você recebeu uma exceção <code class=\"docutils literal notranslate\"><span class=\"pre\">NameError</span></code>, você pode ter pulado algo passo da <a class=\"reference internal\" href=\"/pt-br/4.0/intro/tutorial02/#tutorial02-import-timezone\"><span class=\"std std-ref\">Parte 2</span></a> onde nós adicionamos “imports” de``datetime`` e <code class=\"docutils literal notranslate\"><span class=\"pre\">timezone</span></code> em <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code>. Copie os “imports” dessa seção, e tente executar seus testes novamente.</p>\n</aside>\n<p>O que ocorreu foi o seguinte:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">test</span> <span class=\"pre\">polls</span></code> looked for tests in the <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> application</p></li>\n<li><p>ele encontrou uma subclass da classe <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.TestCase</span></code></a></p></li>\n<li><p>ele cria um banco de dados especial com o propósito de teste</p></li>\n<li><p>ele procurou por métodos de test - aquele cujo nome começam com <code class=\"docutils literal notranslate\"><span class=\"pre\">test</span></code></p></li>\n<li><p>em <code class=\"docutils literal notranslate\"><span class=\"pre\">test_was_published_recently_with_future_question</span></code> é criado uma instância de <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> na qual o campo <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> está 30 dias no futuro</p></li>\n<li><p>… e usando o método <code class=\"docutils literal notranslate\"><span class=\"pre\">assertIs()</span></code>, descobrimos que <code class=\"docutils literal notranslate\"><span class=\"pre\">was_published_recently()</span></code> retorna <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, mas queremos que retorne <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code></p></li>\n</ul>\n<p>O teste nos informa que teste falhou e até mesmo a linha na qual a falha ocorreu.</p>\n</section>\n<section id=\"fixing-the-bug\">\n<h3>Corrigindo o erro<a class=\"heading-anchor\" href=\"#fixing-the-bug\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Nós sabemos onde o problema está. “Question.was_published_recently()” deveria retornar “False” se “pub_date” está no futuro. Corrija o método no “models.py”, dessa forma ele só retornará “True” se a data também estiver no passado:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">was_published_recently</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"n\">now</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span>\n    <span class=\"k\">return</span> <span class=\"n\">now</span> <span class=\"o\">-</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">&lt;=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">pub_date</span> <span class=\"o\">&lt;=</span> <span class=\"n\">now</span>\n</code></pre></figure>\n<p>execute e teste novamente</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">Creating</span> <span class=\"n\">test</span> <span class=\"n\">database</span> <span class=\"k\">for</span> <span class=\"n\">alias</span> <span class=\"s1\">&#39;default&#39;</span><span class=\"o\">...</span>\n<span class=\"n\">System</span> <span class=\"n\">check</span> <span class=\"n\">identified</span> <span class=\"n\">no</span> <span class=\"n\">issues</span> <span class=\"p\">(</span><span class=\"mi\">0</span> <span class=\"n\">silenced</span><span class=\"p\">)</span><span class=\"o\">.</span>\n<span class=\"o\">.</span>\n<span class=\"o\">----------------------------------------------------------------------</span>\n<span class=\"n\">Ran</span> <span class=\"mi\">1</span> <span class=\"n\">test</span> <span class=\"ow\">in</span> <span class=\"mf\">0.001</span><span class=\"n\">s</span>\n\n<span class=\"n\">OK</span>\n<span class=\"n\">Destroying</span> <span class=\"n\">test</span> <span class=\"n\">database</span> <span class=\"k\">for</span> <span class=\"n\">alias</span> <span class=\"s1\">&#39;default&#39;</span><span class=\"o\">...</span>\n</code></pre></div>\n<p>Depois de identificar um erro, nós escrevemos um teste que demonstra e corrige o erro no código, então o nosso teste passa.</p>\n<p>Many other things might go wrong with our application in the future, but we can\nbe sure that we won’t inadvertently reintroduce this bug, because running the\ntest will warn us immediately. We can consider this little portion of the\napplication pinned down safely forever.</p>\n</section>\n<section id=\"more-comprehensive-tests\">\n<h3>Testes mais abrangentes<a class=\"heading-anchor\" href=\"#more-comprehensive-tests\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Enquanto estamos aqui, nós podemos nos aprofundar no método <code class=\"docutils literal notranslate\"><span class=\"pre\">was_published_recently()</span></code>; De fato, seria certamente embaraçoso introduzir um novo bug enquanto arruma outro.</p>\n<p>Adicione mais dois métodos de teste na mesma classe, para testá-la melhor.</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/tests.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_was_published_recently_with_old_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    was_published_recently() returns False for questions whose pub_date</span>\n<span class=\"sd\">    is older than 1 day.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">time</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"n\">seconds</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n    <span class=\"n\">old_question</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"p\">(</span><span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">time</span><span class=\"p\">)</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"n\">old_question</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">(),</span> <span class=\"kc\">False</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_was_published_recently_with_recent_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    was_published_recently() returns True for questions whose pub_date</span>\n<span class=\"sd\">    is within the last day.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">time</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">hours</span><span class=\"o\">=</span><span class=\"mi\">23</span><span class=\"p\">,</span> <span class=\"n\">minutes</span><span class=\"o\">=</span><span class=\"mi\">59</span><span class=\"p\">,</span> <span class=\"n\">seconds</span><span class=\"o\">=</span><span class=\"mi\">59</span><span class=\"p\">)</span>\n    <span class=\"n\">recent_question</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"p\">(</span><span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">time</span><span class=\"p\">)</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"n\">recent_question</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">(),</span> <span class=\"kc\">True</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>E agora nós temos 3 testes que confirmam que <code class=\"docutils literal notranslate\"><span class=\"pre\">Question.was_published_recently()</span></code> retorna valores sensíveis de perguntas do passado, recente e futuro.</p>\n<p>Again, <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> is a minimal application, but however complex it grows in the\nfuture and whatever other code it interacts with, we now have some guarantee\nthat the method we have written tests for will behave in expected ways.</p>\n</section>\n</section>\n<section id=\"test-a-view\">\n<h2>Teste a View<a class=\"heading-anchor\" href=\"#test-a-view\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>A aplicação de enquete é bastante indiscriminatória: irá publicar qualquer questão, incluindo aquelas que o campo <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> está no futuro. Devemos melhorar isso. Definindo um <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> no futuro deveria fazer com que a Question seja publicada naquele  momento, mas que esteja invisível até lá.</p>\n<section id=\"a-test-for-a-view\">\n<h3>Um teste para uma view<a class=\"heading-anchor\" href=\"#a-test-for-a-view\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>When we fixed the bug above, we wrote the test first and then the code to fix\nit. In fact that was an example of test-driven development, but it doesn’t\nreally matter in which order we do the work.</p>\n<p>Em nosso primeiro teste, focamos no comportamento interno do código. Para este teste, nós queremos checar seu comportamento como seria experienciado por um usuário através de um navegador web.</p>\n<p>Antes de tentarmos consertar alguma coisa, vamos dar uma olhada nas ferramentas à nossa disposição.</p>\n</section>\n<section id=\"the-django-test-client\">\n<h3>O cliente de testes do Django<a class=\"heading-anchor\" href=\"#the-django-test-client\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>o Django fornece um test <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.Client\" title=\"django.test.Client\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Client</span></code></a> para simular um usuário interagindo com o código no nível de view. POdemos usá-lo em <code class=\"docutils literal notranslate\"><span class=\"pre\">tests.py</span></code> ou memso no <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a>.</p>\n<p>We will start again with the <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a>, where we need to do a couple of\nthings that won’t be necessary in <code class=\"docutils literal notranslate\"><span class=\"pre\">tests.py</span></code>. The first is to set up the test\nenvironment in the <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a>:</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-2-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>shell\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-2-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py shell\n</code></pre></div></div></div>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">setup_test_environment</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">setup_test_environment</span><span class=\"p\">()</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/advanced/#django.test.utils.setup_test_environment\" title=\"django.test.utils.setup_test_environment\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">setup_test_environment()</span></code></a> installs a template renderer\nwhich will allow us to examine some additional attributes on responses such as\n<code class=\"docutils literal notranslate\"><span class=\"pre\">response.context</span></code> that otherwise wouldn’t be available. Note that this\nmethod <em>does not</em> set up a test database, so the following will be run against\nthe existing database and the output may differ slightly depending on what\nquestions you already created. You might get unexpected results if your\n<code class=\"docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code> in <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> isn’t correct. If you don’t remember setting\nit earlier, check it before continuing.</p>\n<p>A diante precisamos importar a classe cliente de teste (depois iremos usar a classe <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.TestCase</span></code></a>  no <code class=\"docutils literal notranslate\"><span class=\"pre\">tests.py</span></code>, a qual traz seu próprio cliente, então isso não será necessário):</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Client</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># create an instance of the client for our use</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Com isso pronto, podemos pedir que o cliente faça algum trabalho para a gente:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># get a response from &#39;/&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">&#39;/&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">Not Found: /</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># we should expect a 404 from that address; if you instead see an</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># &quot;Invalid HTTP_HOST header&quot; error and a 400 response, you probably</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># omitted the setup_test_environment() call described earlier.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span>\n<span class=\"go\">404</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># on the other hand we should expect to find something at &#39;/polls/&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># we&#39;ll use &#39;reverse()&#39; rather than a hardcoded URL</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:index&#39;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span>\n<span class=\"go\">200</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span>\n<span class=\"go\">b&#39;\\n    &lt;ul&gt;\\n    \\n        &lt;li&gt;&lt;a href=&quot;/polls/1/&quot;&gt;What&amp;#x27;s up?&lt;/a&gt;&lt;/li&gt;\\n    \\n    &lt;/ul&gt;\\n\\n&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">]</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"improving-our-view\">\n<h3>Melhorando a nossa view<a class=\"heading-anchor\" href=\"#improving-our-view\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A lista de enquete mostra enquetes que não estão publicadas ainda (isto é aqueles que tem um <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>pub_date``no futuro). Vamos concertar isso.</p>\n<p>No <a class=\"reference internal\" href=\"/pt-br/4.0/intro/tutorial04/\"><span class=\"doc\">Tutorial 4</span></a> nós introduzimos o class-based views, baseado no <a class=\"reference internal\" href=\"/pt-br/4.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">IndexView</span><span class=\"p\">(</span><span class=\"n\">generic</span><span class=\"o\">.</span><span class=\"n\">ListView</span><span class=\"p\">):</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;polls/index.html&#39;</span>\n    <span class=\"n\">context_object_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;latest_question_list&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;Return the last five published questions.&quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n</code></pre></figure>\n<p>Precisamos fazer uma adição no método <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> e alterá-lo de modo que ele verifique também a data comparando com <code class=\"docutils literal notranslate\"><span class=\"pre\">timezone.now()</span></code>. Antes precisamos adicionar uma importação:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n</code></pre></figure>\n<p>e então devemos fazer uma adição ao método <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset</span></code> como a seguir:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Return the last five published questions (not including those set to be</span>\n<span class=\"sd\">    published in the future).</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"k\">return</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span>\n        <span class=\"n\">pub_date__lte</span><span class=\"o\">=</span><span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span>\n    <span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n</code></pre></figure>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">Question.objects.filter(pub_date__lte=timezone.now())</span></code> retorna um queryset contendo <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>s cujo o <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> é menor ou igual a - que quer dizer, anterior ou igual a - <code class=\"docutils literal notranslate\"><span class=\"pre\">timezone.now</span></code>.</p>\n</section>\n<section id=\"testing-our-new-view\">\n<h3>Testando nossa nova view<a class=\"heading-anchor\" href=\"#testing-our-new-view\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Agora você pode se certificar se isso se comporta como esperado executando <code class=\"docutils literal notranslate\"><span class=\"pre\">runserver</span></code>, carregando o site no seu navegador, criando <code class=\"docutils literal notranslate\"><span class=\"pre\">Questions</span></code> com datas no passado e no futuro, e verificando que somente aqueles que foram publicados são listados. Você não quer ter que fazer isso <em>toda vez  que fizer uma alterações que possa afetar isso</em> - então vamos também criar um teste, baseado no nossa sessão <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-shell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">shell</span></code></a> acima.</p>\n<p>Adicione o seguinte a “polls/tests.py”:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/tests.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n</code></pre></figure>\n<p>e nós vamos criar uma função de atalho para criar perguntas assim como uma nova classe de teste:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/tests.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Create a question with the given `question_text` and published the</span>\n<span class=\"sd\">    given number of `days` offset to now (negative for questions published</span>\n<span class=\"sd\">    in the past, positive for questions that have yet to be published).</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">time</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">+</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"n\">days</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"n\">question_text</span><span class=\"p\">,</span> <span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">time</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QuestionIndexViewTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_no_questions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        If no questions exist, an appropriate message is displayed.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:index&#39;</span><span class=\"p\">))</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertContains</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"s2\">&quot;No polls are available.&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertQuerysetEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">],</span> <span class=\"p\">[])</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_past_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Questions with a pub_date in the past are displayed on the</span>\n<span class=\"sd\">        index page.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;Past question.&quot;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=-</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:index&#39;</span><span class=\"p\">))</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertQuerysetEqual</span><span class=\"p\">(</span>\n            <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">],</span>\n            <span class=\"p\">[</span><span class=\"n\">question</span><span class=\"p\">],</span>\n        <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_future_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Questions with a pub_date in the future aren&#39;t displayed on</span>\n<span class=\"sd\">        the index page.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;Future question.&quot;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:index&#39;</span><span class=\"p\">))</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertContains</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"s2\">&quot;No polls are available.&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertQuerysetEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">],</span> <span class=\"p\">[])</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_future_question_and_past_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Even if both past and future questions exist, only past questions</span>\n<span class=\"sd\">        are displayed.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;Past question.&quot;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=-</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n        <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;Future question.&quot;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:index&#39;</span><span class=\"p\">))</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertQuerysetEqual</span><span class=\"p\">(</span>\n            <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">],</span>\n            <span class=\"p\">[</span><span class=\"n\">question</span><span class=\"p\">],</span>\n        <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_two_past_questions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        The questions index page may display multiple questions.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">question1</span> <span class=\"o\">=</span> <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;Past question 1.&quot;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=-</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n        <span class=\"n\">question2</span> <span class=\"o\">=</span> <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;Past question 2.&quot;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=-</span><span class=\"mi\">5</span><span class=\"p\">)</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:index&#39;</span><span class=\"p\">))</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertQuerysetEqual</span><span class=\"p\">(</span>\n            <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">],</span>\n            <span class=\"p\">[</span><span class=\"n\">question2</span><span class=\"p\">,</span> <span class=\"n\">question1</span><span class=\"p\">],</span>\n        <span class=\"p\">)</span>\n</code></pre></figure>\n<p>Vejamos algumas delas mais de perto.</p>\n<p>O primeiro é uma função de atalho para questão, <code class=\"docutils literal notranslate\"><span class=\"pre\">create_question</span></code>, para retirar algumas repetições do processo de criar questões.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">test_no_questions</span></code> não cria nenhuma questão, mas verifica a mensagem:”Nenhuma enquete disponível.” e verifica que <code class=\"docutils literal notranslate\"><span class=\"pre\">latest_question_list</span></code> está vazia. Note que a classe <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.TestCase</span></code></a> fornece alguns métodos adicionais de assertividade. Nestes exemplos nós usamos <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.SimpleTestCase.assertContains\" title=\"django.test.SimpleTestCase.assertContains\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertContains()</span></code></a> e <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.TransactionTestCase.assertQuerysetEqual\" title=\"django.test.TransactionTestCase.assertQuerysetEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertQuerysetEqual()</span></code></a>.</p>\n<p>Em <code class=\"docutils literal notranslate\"><span class=\"pre\">test_past_question</span></code>, criamos uma questão e verificamos se esta aparece na lista.</p>\n<p>Em <code class=\"docutils literal notranslate\"><span class=\"pre\">test_future_question</span></code>, nós criamos uma <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> no futuro. O banco de dados é resetado para cada método de teste, quer dizer que a primeira questão não está mais lá, então novamente o index não deve ter nenhuma questão.</p>\n<p>E assim por diante. De fato, estamos usando os testes para contar uma história de entradas no site de administração e da experiencia do usuário, e verificando se para cada estado e para cada nova alteração no estado do sistema, o resultado esperado é publicado.</p>\n</section>\n<section id=\"testing-the-detailview\">\n<h3>Testando o <code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code><a class=\"heading-anchor\" href=\"#testing-the-detailview\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>O que temos funciona bem; Porém, mesmo quando questões futuras não aparecem no * index*, os usuários ainda podem acessá-las se eles conhecem ou adivinham a URL correta. Então precisamos adicionar uma regra similar ao <code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">DetailView</span><span class=\"p\">(</span><span class=\"n\">generic</span><span class=\"o\">.</span><span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Excludes any questions that aren&#39;t published yet.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">pub_date__lte</span><span class=\"o\">=</span><span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">())</span>\n</code></pre></figure>\n<p>We should then add some tests, to check that a <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> whose <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code>\nis in the past can be displayed, and that one with a <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> in the future\nis not:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/tests.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QuestionDetailViewTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_future_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        The detail view of a question with a pub_date in the future</span>\n<span class=\"sd\">        returns a 404 not found.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">future_question</span> <span class=\"o\">=</span> <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;Future question.&#39;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">5</span><span class=\"p\">)</span>\n        <span class=\"n\">url</span> <span class=\"o\">=</span> <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:detail&#39;</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">future_question</span><span class=\"o\">.</span><span class=\"n\">id</span><span class=\"p\">,))</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">url</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">404</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_past_question</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        The detail view of a question with a pub_date in the past</span>\n<span class=\"sd\">        displays the question&#39;s text.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">past_question</span> <span class=\"o\">=</span> <span class=\"n\">create_question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;Past Question.&#39;</span><span class=\"p\">,</span> <span class=\"n\">days</span><span class=\"o\">=-</span><span class=\"mi\">5</span><span class=\"p\">)</span>\n        <span class=\"n\">url</span> <span class=\"o\">=</span> <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls:detail&#39;</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">past_question</span><span class=\"o\">.</span><span class=\"n\">id</span><span class=\"p\">,))</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">url</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertContains</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"n\">past_question</span><span class=\"o\">.</span><span class=\"n\">question_text</span><span class=\"p\">)</span>\n</code></pre></figure>\n</section>\n<section id=\"ideas-for-more-tests\">\n<h3>Ideias para mais testes<a class=\"heading-anchor\" href=\"#ideas-for-more-tests\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Devemos adicionar um método similar ao <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset</span></code> ao <code class=\"docutils literal notranslate\"><span class=\"pre\">ResultsView</span></code> e criar uma nova classe de teste para essa “view”. Isso será muito parecido com o que criamos há pouco; defato terá muitas repetições.</p>\n<p>Podemos também melhorar nossa aplicação de várias outras maneiras, adicionando testes no caminho. Por exemplo é estranho que <code class=\"docutils literal notranslate\"><span class=\"pre\">Questions</span></code> possam ser publicadas no site sem que tenham <code class=\"docutils literal notranslate\"><span class=\"pre\">Choices</span></code>. Então, nossas “views” podem verificar isso, e excluir tais <code class=\"docutils literal notranslate\"><span class=\"pre\">Questions</span></code>. Nossos testes podem criar uma <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> sem <code class=\"docutils literal notranslate\"><span class=\"pre\">Choices</span></code> e então testar que não estão publicadas, também criar uma <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> parecida <em>com</em> <code class=\"docutils literal notranslate\"><span class=\"pre\">Choices</span></code>, e testar se <em>estão</em>  publicadas.</p>\n<p>Talvez usuários registrados no admin devam ser permitidos a ver <code class=\"docutils literal notranslate\"><span class=\"pre\">Questions</span></code> não publicadas, mas não os visitantes comuns. Denovo: independente da necessidade a serem adicionadas ao software para que isso seja realizado, isso deve ser acompanhado por um teste, não importando se você escreve o teste primeiro e então faz o código para passar no teste, ou escreva o código da lógica primeiro e então escreva o teste para fazer a prova.</p>\n<p>Em um certo ponto, você precisará olhar seus testes e se perguntar se o seu código está sofrendo de inchaço de testes, o que nos trás a:</p>\n</section>\n</section>\n<section id=\"when-testing-more-is-better\">\n<h2>Quando estiver testando, mais é melhor<a class=\"heading-anchor\" href=\"#when-testing-more-is-better\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Pode parecer que nossos testes estão crescendo fora de controle. Nessa taxa teremos logo mais código nos testes do que em nossa aplicação, e a repetição não é muito estética, comparado a concisa elegância  do resto do nosso código.</p>\n<p><strong>Isso não importa</strong>. Deixe eles crescerem. Por boa parte do tempo, você pode escrever um teste uma vez e então esquecer dele. Ele vai continuar a executar sua função útil enquanto você continua a escrever seu programa.</p>\n<p>Algumas vezes os testes precisarão ser atualizados. Suponha que emendamos nossas “views” para que somente <code class=\"docutils literal notranslate\"><span class=\"pre\">Questions``com</span> <span class=\"pre\">``Choices</span></code> são publicadas. Neste caso, muitos dos nossos testes existentes irão falahar - <em>nos dizendo exatamente quais testes precisam ter ajustes para que sejam atualizados</em>, assim que os próprios testes auxiliam na manutenção deles mesmos.</p>\n<p>Na pior das hipóteses, ao continuar a desenvolver, você talvez encontre alguns tests que são reduntantes agora. Mesmo isso não é um problema; em testes redundância é uma boa coisa.</p>\n<p>Enquanto seus testes estiverem organizados sensatamente, eles não vão se tornar desorganizados. Boas práticas incluem ter:</p>\n<ul class=\"simple\">\n<li><p>um “TestClass” separado para cada modelo ou view</p></li>\n<li><p>um método de teste separado para cada conjunto de condições que você quer testar</p></li>\n<li><p>nomes de métodos de teste que descrevem a sua função</p></li>\n</ul>\n</section>\n<section id=\"further-testing\">\n<h2>Mais testes<a class=\"heading-anchor\" href=\"#further-testing\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Esse tutorial apenas introduz alguns conceitos básicos de testes. Há muito mais do que você pode fazer, e uma série de ferramentas muito úteis à sua disposição para conseguir algumas coisas muito inteligentes.</p>\n<p>Por exemplo, enquanto nossos testes aqui tem coberto algumas lógicas internas de um modelo e a informação publicada nas nossas “views”, você pode usar um framework para navegador como o <a class=\"reference external\" href=\"https://www.selenium.dev/\">Selenium</a> para testar a maneira como seu HTML é processado de verdade pelo navegador. Isso permite a você testar não somente o comportamento do seu código Django, mas também, por exemplo, do seu JavaScript. É bem legal ver seus testes iniciarem um navegador, e começar a interagir com seu site, como se fosse um ser humano guiando! O Django inclue a <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/tools/#django.test.LiveServerTestCase\" title=\"django.test.LiveServerTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">LiveServerTestCase</span></code></a> para facilitar a integração com ferramentas como o Selenium.</p>\n<p>Se você tem uma aplicação complexa, você pode querer rodar testes automaticamente com cada commit pelo propósito de <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Continuous_integration\">integração contínua</a>, e o próprio controle de qualidade - ao menos parcialmente - é automatizado.</p>\n<p>Uma boa forma de encontrar partes não testadas de sua aplicação é verificar a cobertura de código. Isto também ajuda a identificar códigos frágeis ou mesmo morto. Se você não pode testar um pedaço do código, isso normalmente significa que o código precisa ser refatorado ou removido. Cobertura vai ajudar a identificar código morto. Veja <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/advanced/#topics-testing-code-coverage\"><span class=\"std std-ref\">Integration with coverage.py</span></a> para mais detalhes.</p>\n<p><span class=\"xref std std-doc\">Testes no django</span> tem informações sobre testes.</p>\n</section>\n<section id=\"what-s-next\">\n<h2>E agora?<a class=\"heading-anchor\" href=\"#what-s-next\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Para maiores detalhes sobre testing, veja <a class=\"reference internal\" href=\"/pt-br/4.0/topics/testing/\"><span class=\"doc\">Testando no Django</span></a>.</p>\n<p>Quando estiver confortável testando “views” Django, leia: doc:parte 6 deste tutorial&lt;/intro/tutorial06&gt; para aprender sobre gerenciamente de arquivos estáticos.</p>\n</section>","rootId":"writing-your-first-django-app-part-5","toc":[{"title":"Apresentando testes automatizados","anchor":"introducing-automated-testing","children":[{"title":"O que são testes automatizados?","anchor":"what-are-automated-tests","children":[]},{"title":"Porque você precisa criar testes","anchor":"why-you-need-to-create-tests","children":[{"title":"Teste vão salvar seu tempo","anchor":"tests-will-save-you-time","children":[]},{"title":"Testes não só identificam problemas, mas também os previnem","anchor":"tests-don-t-just-identify-problems-they-prevent-them","children":[]},{"title":"Testes fazem seu código mais atraente.","anchor":"tests-make-your-code-more-attractive","children":[]},{"title":"Testes ajudam as equipes a trabalharem juntos","anchor":"tests-help-teams-work-together","children":[]}]}]},{"title":"Estratégias básicas de testes","anchor":"basic-testing-strategies","children":[]},{"title":"Escrevendo nosso primeiro teste","anchor":"writing-our-first-test","children":[{"title":"Nós identificamos um bug","anchor":"we-identify-a-bug","children":[]},{"title":"Criar um teste para expor um bug","anchor":"create-a-test-to-expose-the-bug","children":[]},{"title":"Executando o teste","anchor":"running-tests","children":[]},{"title":"Corrigindo o erro","anchor":"fixing-the-bug","children":[]},{"title":"Testes mais abrangentes","anchor":"more-comprehensive-tests","children":[]}]},{"title":"Teste a View","anchor":"test-a-view","children":[{"title":"Um teste para uma view","anchor":"a-test-for-a-view","children":[]},{"title":"O cliente de testes do Django","anchor":"the-django-test-client","children":[]},{"title":"Melhorando a nossa view","anchor":"improving-our-view","children":[]},{"title":"Testando nossa nova view","anchor":"testing-our-new-view","children":[]},{"title":"Testando o DetailView","anchor":"testing-the-detailview","children":[]},{"title":"Ideias para mais testes","anchor":"ideas-for-more-tests","children":[]}]},{"title":"Quando estiver testando, mais é melhor","anchor":"when-testing-more-is-better","children":[]},{"title":"Mais testes","anchor":"further-testing","children":[]},{"title":"E agora?","anchor":"what-s-next","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"Introdução","url":"/pt-br/4.0/intro/"}],"prev":{"docname":"intro/tutorial04","title":"Escrevendo sua primeira aplicação Django, parte 4","url":"/pt-br/4.0/intro/tutorial04/"},"next":{"docname":"intro/tutorial06","title":"Escrevendo sua primeira aplicação Django, parte 6","url":"/pt-br/4.0/intro/tutorial06/"},"formats":{"html":"/pt-br/4.0/intro/tutorial05/","markdown":"/pt-br/4.0/intro/tutorial05.md","json":"/pt-br/4.0/intro/tutorial05.json"},"source":"https://github.com/django/django/blob/stable/4.0.x/docs/intro/tutorial05.txt","official":"https://docs.djangoproject.com/pt-br/4.0/intro/tutorial05/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}