6.2 Iterando para um Novo Design da Aplicação
O processo para evoluir uma aplicação é trabalhoso e deve ser feito de forma incremental. Às vezes dá aquele desejo de sairmos modificando tudo quanto antes, mas, nessas horas temos que nos conter e planejar as ações a serem tomadas. Não há necessidade de alterarmos todo o projeto e arquitetura da aplicação de uma única vez.
Considerando nossa lista de tarefas apresentada no início do capítulo, o Teste Funcional, devido à falha apresentada, sugere que devemos iniciar pelo segundo item, ou seja, oferecer URLs únicos para cada lista.
Para dar início a mudança, precisamos alterar nosso teste unitário para refletir o que desejamos. O teste alterado fica conforme abaixo:
Alteremos o método test_redirects_after_POST para que, o redirecionamento seja para outro URL, diferente de '/'. No caso, usamos a URL /lists/the-only-list-in-the-world/ (linhas 26 a 30).
from django.urls import resolve
from django.test import TestCase
from lists.views import home_page
class HomePageTest(TestCase):
def test_root_url_resolves_to_home_page_view(self):
found = resolve('/')
self.assertEquals(found.func, home_page)
def test_home_page_returns_correct_html(self):
response = self.client.get('/')
self.assertTemplateUsed(response, 'home.html')
def test_only_saves_items_when_necessary(self):
self.client.get('/')
self.assertEquals(Item.objects.count(), 0)
def test_can_save_a_POST_request(self):
self.client.post('/', data={'item_text': 'A new list item'})
self.assertEquals(Item.objects.count(), 1)
new_item = Item.objects.first()
self.assertEquals(new_item.text, 'A new list item')
def test_redirects_after_POST(self):
response = self.client.post('/', data={'item_text': 'A new list item'})
self.assertEquals(response.status_code, 302)
self.assertEquals(response['location'], '/lists/the-only-list-in-the-world/')
def test_displays_all_list_itens(self):
Item.objects.create(text='itemey 1')
Item.objects.create(text='itemey 2')
response = self.client.get('/')
self.assertIn('itemey 1', response.content.decode())
self.assertIn('itemey 2', response.content.decode())
from lists.models import Item
class ItemModelTest(TestCase):
def test_saving_and_retriving_items(self):
first_item = Item()
first_item.text = 'The first (ever) list item'
first_item.save()
second_item = Item()
second_item.text = 'Item the second'
second_item.save()
saved_items = Item.objects.all()
self.assertEquals(saved_items.count(),2)
first_saved_item = saved_items[0]
second_saved_item = saved_items[1]
self.assertEquals(first_saved_item.text, 'The first (ever) list item')
self.assertEquals(second_saved_item.text, 'Item the second')
Ao executar esse os testes unitários acima temos a seguinte saída:
Para resolver o primeiro problema detectado (AssertionError: '/' != '/lists/the-only-list-in-the-world/'- linha 12) podemos alterar nossa função home_page no arquivo lists/views.py, conforme abaixo:
Para corrigir o problema precisamos editar nossa função de view conforme abaixo (linha 8):
Fica claro que essa alteração fará o teste unitário passar, mas outros testes falharem, como os testes funcionais:
Isso que provocamos é chamado de regressão, ou seja, não apenas o teste inicial esta falhando, mas outros passaram a falhar.
Para continuar, inicialmente vamos escrever um novo teste unitário para avaliar o retorno nessa nova URL. O arquivo lists/tests.py passará a ter o seguinte conteúdo. Observa-se que uma nova classe de teste foi adicionada no arquivo (ListViewTest) com um método de teste denominado test_display_all_items (linhas 43 a 51).
Com a execução desses testes, obtemos um erro 404, pois a URL ainda não existe.
A correção do erro 404 passa pela alteração no nosso arquivo superlists/urls.py, fazendo com que o Django considere essa nova URL não prevista inicialmente, conforme abaixo:
Ao reexecutar os testes unitários novamente, obtemos um novo erro, cuja correção implica em implementarmos a função view_lists para tratar a requisição nesse URL.
A alteração no arquivo lists/views.py conforme abaixo, resolve o problema acima parcialmente.
Reexecutando os testes unitários, obtemos a seguinte saída:
Como era de se esperar, os testes mostram que a função recém-implementada não retorna um objeto do tipo HttpResponse e o teste falha. Para corrigi-la, vamos implementar a função view_list conforme abaixo:
Feita a correção, os testes unitários executam com sucesso.
Mas ao executar os testes funcionais, apesar de avançarem, continuam falhando e ainda não chegamos ao estado funcional que tínhamos antes de iniciar o capítulo.
Como enfatiza Percival (2017), as mensagens acima não são assim tão esclarecedoras e, nessa horas, temos que assumir o papel do depurador e tentar descobrir o motivo das falhas. Ele argumenta que, sabemos que a página inicial está funcionando, pois nossos testes funcionais passaram da linha 65, portanto, temos certeza que um item foi adicionado a nossa lista.
Os testes unitários estão todos passando e, desse modo, sabemos que as URLs e views estão funcionando como deveriam, os templates corretos estão sendo renderizados e é capaz de tratar requisições POST. A view que criamos para only-list-in-the-world sabe como exibir seus itens, mas não sabe como tratar requisições POST e isso nos dá uma dica de onde o problema pode estar.
"...quanto todos os testes de unidade estiverem passando, mas os testes funcionais não, geralmente eles estão apontado para um problema que não foi coberto pelos testes unitários e, ... com frequência é um problema de template." (Percival, 2017)
Quando observamos nosso template, vimos que nosso form está assim: <form method="POST">. Com essa configuração, por padrão, o navegador envia os dados de volta para o mesmo URL que está no momento. Desse modo, os testes funcionaram enquanto estávamos usando sempre o mesmo URL, como mudamos a mesma para a página da only-list-in-the-world, isso deixa de funcionar. Para adotarmos a solução mais simples, vamos apenas incluir um atributo action e redirecionar para a nossa view existente que já funcionava para as requisições POST. Para isso, o código completo do template fica conforme abaixo:
Com a inclusão do action="/" na linha 7, os testes funcionais iniciais voltam a funcionar e atingimos um estado consistente com o que tínhamos antes. Vejamos abaixo a saída dos testes funcionais:
Desse modo, é um ótimo momento para colocarmos o código sob controle de versão para darmos prosseguimento.
Last updated
Was this helpful?