Tutorial

Como adicionar o teste de unidade ao seu projeto Django

PythonDjangoPython FrameworksApplicationsDevelopmentProgramming Project

O autor selecionou a Open Internet/Free Speech Fund para receber uma doação como parte do programa Write for DOnations.

Introdução

É quase impossível desenvolver sites que funcionem perfeitamente na primeira vez, sem erro algum. Por este motivo, você deve testar seu aplicativo Web em busca de erros e trabalhar neles proativamente. Para melhorar a eficiência dos testes, é comum dividir os testes em unidades que testam funcionalidades específicas de um aplicativo Web. Esta prática é conhecida como teste de unidade. Esta prática facilita a detecção de erros, pois os testes focam em partes menores (unidades) do seu projeto, independentemente das outras.

O teste de um site pode ser uma tarefa complexa de se realizar, pois um site é composto de várias camadas lógicas, como o processamento de solicitações HTTP, validação do formulário e renderização de modelos. No entanto, o Django fornece um conjunto de ferramentas que simplifica o teste de seu aplicativo Web. No Django, o melhor método de escrever os testes é através do uso do módulo unittest do Python, embora seja possível utilizar outros frameworks de teste.

Neste tutorial, você configurará um conjunto de testes em seu projeto Django e escreverá os testes de unidade para os modelos e visualizações em seu aplicativo. Você executará esses testes, analisará os resultados e aprenderá como encontrar as causas das falhas dos testes.

Pré-requisitos

Antes de começar este tutorial será necessário:

Passo 1 — Adicionando um conjunto de testes para seu aplicativo Django

Um conjunto de teste é uma coleção de todos os casos de teste em todos os aplicativos em seu projeto. Para que seja possível que o utilitário de testes do Django descubra os casos de teste que você possui, escreva os casos de teste em scripts cujos nomes comecem com test. Neste passo você criará a estrutura do diretório e os arquivos para seu conjunto de testes e criará um caso de teste vazio nele.

Se você seguiu o a série de tutoriais de desenvolvimento do Django, você terá consigo um aplicativo Django chamado blogsite.

Vamos criar uma pasta para armazenar todos os nossos scripts de testes. Primeiro, ative o ambiente virtual:

  • cd ~/my_blog_app
  • . env/bin/activate

Em seguida, vá até o diretório do aplicativo chamado blogsite. Esta é a pasta que contém os arquivos models.py e views.py. Crie nela uma nova pasta chamada tests:

  • cd ~/my_blog_app/blog/blogsite
  • mkdir tests

Depois disso, você transformará esta pasta em um pacote Python. Por este motivo, adicione um arquivo __init__.py:

  • cd ~/my_blog_app/blog/blogsite/tests
  • touch __init__.py

Agora, você adicionará um arquivo para testar seus modelos e outro arquivo para testar suas visualizações:

  • touch test_models.py
  • touch test_views.py

Por fim, você criará um caso de teste vazio em test_models.py. Você precisará importar a classe Django TestCase e torná-la uma superclasse de sua própria classe de caso de teste. Mais à frente, você adicionará métodos para este caso de teste para testar a lógica em seus modelos. Abra o arquivo test_models.py​​​:

  • nano test_models.py

Agora, adicione o código a seguir ao arquivo:

~/my_blog_app/blog/blogsite/tests/test_models.py
from django.test import TestCase

class ModelsTestCase(TestCase):
    pass

Você adicionou um conjunto de testes ao aplicativo blogsite. Em seguida, você preencherá os detalhes do modelo do caso de teste vazio criado aqui.

Passo 2 — Testando o código Python

Neste passo você testará a lógica do código escrito no arquivo models.py. Você estará testando especificamente o método save do modelo Post para garantir que ele crie o campo de dados dinâmico correto do título de uma postagem quando ela for chamada.

Vamos começar analisando o código que você já tem em seu arquivo models.py para o método save do modelo Post:

  • cd ~/my_blog_app/blog/blogsite
  • nano models.py

Você verá o seguinte:

~/my_blog_app/blog/blogsite/models.py
class Post(models.Model):
    ...
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)
    ...

Como podemos ver, ele verifica se a postagem que está prestes a ser salva possui algum valor do campo de dados dinâmico. Se não tiver, ele chama o slugify para criar um valor do campo de dados dinâmico. Esta é lógica que queremos para testar e garantir que os campos de dados dinâmicos sejam criados ao salvar uma postagem.

Feche o arquivo.

Para testar isso, volte para o test_models.py:

  • nano test_models.py

Em seguida, atualize-o para o seguinte, adicionando as partes destacadas:

~/my_blog_app/blog/blogsite/tests/test_models.py
from django.test import TestCase
from django.template.defaultfilters import slugify
from blogsite.models import Post


class ModelsTestCase(TestCase):
    def test_post_has_slug(self):
        """Posts are given slugs correctly when saving"""
        post = Post.objects.create(title="My first post")

        post.author = "John Doe"
        post.save()
        self.assertEqual(post.slug, slugify(post.title))

Este novo método test_post_has_slug cria uma nova postagem com o título "My first post" e, em seguida, fornece um autor à postagem e a salva. Após isso, use o método assertEqual do módulo unittest do Python para verificar se o campo de dados dinâmico para a postagem está correto. O método assertEqual verifica se os dois argumentos passados a ele são iguais aos argumentos determinados pelo operador "==". Caso não sejam iguais, o método gera um erro.

Salve e saia do test_models.py​​​.

Este é um exemplo do que pode ser testado. Quanto mais lógica você adicionar ao seu projeto, mais conteúdo haverá para testar. É aconselhável que você crie mais testes caso adicione mais lógica ao método save ou crie novos métodos para o modelo Post. Você pode adicioná-los ao método test_post_has_slug ou criar novos métodos de teste, mas os nomes devem começar com test.

Você criou um caso de teste para o modelo Post com êxito, onde você definiu que os campos de dados dinâmicos foram criados corretamente após salvar. No próximo passo você escreverá um caso de teste para testar as visualizações.

Passo 3 — Utilizando o cliente de teste do Django

Neste passo, você escreverá um caso de teste que testa uma visualização utilizando o cliente de testes do Django. O test client é uma classe Python que age como um navegador Web fictício. Ele permite que você teste suas visualizações e interaja com seu aplicativo Django da mesma forma que um usuário faria. Você pode acessar o cliente de teste referindo-se ao self.client em seus métodos de teste. Por exemplo, vamos criar um caso de teste em test_views.py. Primeiro, abra o arquivo test_views.py​​​:

  • nano test_views.py

Depois, adicione o seguinte:

~/my_blog_app/blog/blogsite/tests/test_views.py
from django.test import TestCase


class ViewsTestCase(TestCase):
    def test_index_loads_properly(self):
        """The index page loads properly"""
        response = self.client.get('your_server_ip:8000')
        self.assertEqual(response.status_code, 200)

O ViewsTestCase contém um método test_index_loads_properly que utiliza o cliente de teste do Django para visitar a página inicial do site (http://your_server_ip:8000, onde o your_server_ip é o endereço IP do servidor que você está utilizando). Em seguida, o método de teste verifica se a resposta tem um código de status 200, o que significa que a página respondeu sem erros. Pelo resultado do teste, podemos concluir que quando os usuários visitarem a página, ela responderá sem erros também.

Além do código de status, você pode ler sobre outras propriedades da resposta do cliente de teste que você confere na página de respostas de testes da documentação do Django.

Neste passo, você criou um caso de teste para conferir se a renderização da visualização da página inicial funciona sem erros. Agora, existem dois casos de teste em seu conjunto. No próximo passo, você os executará para ver os resultados.

Passo 4 — Executando seus testes

Agora que você terminou de desenvolver um conjunto de testes para o projeto, é hora de executá-los e ver os resultados. Para executar os testes, vá para a pasta blog (que contém o arquivo manage.py do aplicativo):

  • cd ~/my_blog_app/blog

Em seguida, execute-os com:

  • python manage.py test

Você verá um resultado parecido com o seguinte em seu terminal:

Output
Creating test database for alias 'default'... System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.007s OK Destroying test database for alias 'default'...

Neste resultado, existem dois pontos .., cada um dos quais representa um caso de teste aprovado. Agora, você modificará o test_views.py para acionar uma falha no teste. Primeiro, abra o arquivo com:

  • nano test_views.py

Em seguida, altere o código destacado para:

~/my_blog_app/blog/blogsite/tests/test_views.py
from django.test import TestCase


class ViewsTestCase(TestCase):
    def test_index_loads_properly(self):
        """The index page loads properly"""
        response = self.client.get('your_server_ip:8000')
        self.assertEqual(response.status_code, 404)

Aqui, você alterou o código de status de 200 para 404. Agora, execute o teste novamente do diretório com o manage.py:

  • python manage.py test

Você verá o seguinte resultado:

Output
Creating test database for alias 'default'... System check identified no issues (0 silenced). .F ====================================================================== FAIL: test_index_loads_properly (blogsite.tests.test_views.ViewsTestCase) The index page loads properly ---------------------------------------------------------------------- Traceback (most recent call last): File "~/my_blog_app/blog/blogsite/tests/test_views.py", line 8, in test_index_loads_properly self.assertEqual(response.status_code, 404) AssertionError: 200 != 404 ---------------------------------------------------------------------- Ran 2 tests in 0.007s FAILED (failures=1) Destroying test database for alias 'default'...

Veja que existe uma mensagem de erro informando o script, o caso de teste e o método que falhou. Ele também diz a causa da falha, o código de status diferente de 404 neste caso, com a mensagem AssertionError: 200 ! = 404. O AssertionError é criado na linha de código destacada no arquivo test_views.py:

~/my_blog_app/blog/blogsite/tests/test_views.py
from django.test import TestCase


class ViewsTestCase(TestCase):
    def test_index_loads_properly(self):
        """The index page loads properly"""
        response = self.client.get('your_server_ip:8000')
        self.assertEqual(response.status_code, 404)

Ele informa a você que a afirmação é falsa, ou seja, o código de status da resposta (200) não era o esperado (404). Antes da mensagem de falha, vemos que os dois pontos .. foram modificados para . F, que diz que o primeiro caso de teste foi aprovado enquanto o segundo falhou.

Conclusão

Neste tutorial, você criou um conjunto de testes em seu projeto Django, adicionou casos de teste para testar o modelo e a lógica de visualização. Também aprendeu como executar testes e analisou o resultado deles. Como um próximo passo, você pode criar novos scripts de teste para código Python que não sejam do models.py e do views.py.

Em seguida, temos alguns artigos que podem ser úteis ao desenvolver e testar sites com o Django:

Você também pode verificar nossa página de tópicos relacionados ao Django para obter mais tutoriais e projetos.

Creative Commons License