Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🧪
Intermediaire 25 min Django

Tester Django avec Pytest

Pourquoi Tester Django avec Pytest ?

Dans le monde professionnel, tester son code est une pratique essentielle pour garantir la qualité et la stabilité de l'application. Lorsque vous travaillez sur un projet Django, il est crucial d'avoir des tests automatisés pour vous assurer que chaque partie du code fonctionne comme prévu. Pytest est un framework de test Python populaire qui offre une grande flexibilité et une simplicité d'utilisation, parfaitement adapté à tester Django.

Un cas concret où le testing est essentiel est lors de la mise en production d'une application web. Sans tests automatisés, il est difficile de s'assurer que toutes les fonctionnalités sont correctement développées et que l'application est stable avant son déploiement. Pytest simplifie ce processus en permettant de créer des tests rapides et fiables qui peuvent être exécutés facilement à chaque modification du code.

Prerequis

Avant de commencer à tester Django avec Pytest, vous devez avoir les éléments suivants :

  • Python 3.6 ou plus récent
  • Django 2.2 ou plus récent
  • Pytest
  • virtualenv (facultatif mais recommandé)

Outils à installer

Pour installer Pytest et Django, vous pouvez utiliser pip. Assurez-vous d'avoir une environnement virtuel activé :

pip install pytest django

Concepts fondamentaux

1. Structure de projet

Pytest utilise une structure simple et intuitive pour organiser les tests. Les fichiers de test doivent être nommés en commençant par test_ ou en se terminant par _test.py. Ils doivent être placés dans un répertoire appelé tests.

myproject/
├── manage.py
├── myapp/
│   ├── __init__.py
│   ├── models.py
│   └── tests.py
└── tests/
    ├── __init__.py
    ├── test_models.py
    └── test_views.py

2. Fixture

Une fixture est une fonction qui fournit des données ou des objets à un test. Pytest permet de créer des fixtures pour faciliter le setup et le teardown des tests.

## myapp/tests.py

import pytest
from django.contrib.auth.models import User

@pytest.fixture
def user():
    return User.objects.create_user(username='testuser', password='12345')

3. Assertions

Pytest utilise les assertions Python standard pour vérifier que les résultats des tests sont corrects.

## myapp/tests.py

def test_user_creation(user):
    assert user.username == 'testuser'
    assert user.password != '12345'  # Vérifie que le mot de passe n'est pas stocké en clair

4. Paramétrisation des tests

Pytest permet d'exécuter les mêmes tests avec différents paramètres, ce qui est utile pour tester différentes conditions.

## myapp/tests.py

import pytest

@pytest.mark.parametrize("value, expected", [
    (1, 2),
    (-1, -2),
    (0, 0)
])
def test_square(value, expected):
    assert value * 2 == expected

Mise en pratique : projet fil rouge

Nous allons créer un petit gestionnaire de tâches avec Django et Pytest. Le projet comprendra les fonctionnalités suivantes :

  1. Créer une tâche
  2. Marquer une tâche comme terminée
  3. Supprimer une tâche

Étape 1 : Configuration du projet

Commencez par créer un nouveau projet Django et un application.

django-admin startproject mytaskmanager
cd mytaskmanager
python manage.py startapp tasks

Étape 2 : Création des modèles

Ajoutez les modèles nécessaires dans tasks/models.py.

## tasks/models.py

from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=255)
    completed = models.BooleanField(default=False)

    def __str__(self):
        return self.title

Étape 3 : Migrations

Créez et appliquez les migrations pour le modèle.

python manage.py makemigrations tasks
python manage.py migrate

Étape 4 : Création des vues et des URLs

Ajoutez les vues et les URL dans tasks/views.py et tasks/urls.py.

## tasks/views.py

from django.shortcuts import render, redirect
from .models import Task

def task_list(request):
    tasks = Task.objects.all()
    return render(request, 'tasks/task_list.html', {'tasks': tasks})

def create_task(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        Task.objects.create(title=title)
        return redirect('task_list')
    return render(request, 'tasks/create_task.html')

def toggle_task(request, task_id):
    task = Task.objects.get(id=task_id)
    task.completed = not task.completed
    task.save()
    return redirect('task_list')

def delete_task(request, task_id):
    task = Task.objects.get(id=task_id)
    task.delete()
    return redirect('task_list')
python
## tasks/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.task_list, name='task_list'),
    path('create/', views.create_task, name='create_task'),
    path('toggle/<int:task_id>/', views.toggle_task, name='toggle_task'),
    path('delete/<int:task_id>/', views.delete_task, name='delete_task'),
]

Étape 5 : Templates

Créez les templates dans tasks/templates/tasks/.

<!-- tasks/templates/tasks/task_list.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Task List</title>
</head>
<body>
    <h1>Task List</h1>
    <ul>
        {% for task in tasks %}
            <li>
                task.title
                <a href="{% url 'toggle_task' task.id %}">{% if not task.completed %}Mark as Done{% else %}Unmark{% endif %}</a>
                <a href="{% url 'delete_task' task.id %}">Delete</a>
            </li>
        {% endfor %}
    </ul>
    <a href="{% url 'create_task' %}">Create New Task</a>
</body>
</html>

<!-- tasks/templates/tasks/create_task.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Create Task</title>
</head>
<body>
    <h1>Create Task</h1>
    <form method="post">
        {% csrf_token %}
        <input type="text" name="title" placeholder="Task title" required>
        <button type="submit">Create</button>
    </form>
</body>
</html>

Étape 6 : Configuration des tests

Ajoutez les tests dans tasks/tests.py.

## tasks/tests.py

import pytest
from django.urls import reverse
from .models import Task
from .views import task_list, create_task, toggle_task, delete_task

@pytest.mark.django_db
def test_task_creation(client):
    response = client.post(reverse('create_task'), {'title': 'Test Task'})
    assert response.status_code == 302
    assert Task.objects.count() == 1

@pytest.mark.django_db
def test_task_toggle(client, task_factory):
    response = client.get(reverse('toggle_task', args=[task_factory().id]))
    assert response.status_code == 302
    assert Task.objects.get(id=task_factory().id).completed is True

@pytest.mark.django_db
def test_task_delete(client, task_factory):
    response = client.get(reverse('delete_task', args=[task_factory().id]))
    assert response.status_code == 302
    assert Task.objects.count() == 0

Étape 7 : Exécution des tests

Exécutez les tests pour vous assurer qu'ils fonctionnent correctement.

pytest

Erreurs fréquentes et debugging

Voici quelques erreurs courantes lors de l'utilisation de Pytest avec Django :

Erreur 1 : ImportError: cannot import name 'settings' from 'django.conf'

Cela peut se produire si vous n'avez pas correctement configuré votre environnement de test.

## ❌ Mauvais
import settings

## ✅ Correct
from django.conf import settings

Erreur 2 : AttributeError: module 'myapp.tests' has no attribute 'test_task_creation'

Cela peut se produire si le nom du fichier de test ne suit pas les conventions Pytest.

## ❌ Mauvais
## myapp/tests.py

def test_task_creation():
    pass

## ✅ Correct
## tasks/tests.py

import pytest

@pytest.mark.django_db
def test_task_creation(client):
    pass

Erreur 3 : pytest: error: no tests found in path(s): .

Cela peut se produire si le répertoire tests n'est pas correctement configuré.

## ❌ Mauvais
myproject/
├── manage.py
└── myapp/

## ✅ Correct
myproject/
├── manage.py
└── myapp/
    └── tests/
        └── test_models.py

Pour aller plus loin

Voici quelques pistes pour approfondir votre compréhension et vos compétences en testant Django avec Pytest :

  1. Tests fonctionnels : Apprenez à créer des tests fonctionnels qui simulent les interactions utilisateur.
  2. Mocking et stubbing : Utilisez des mocks et stubs pour isoler le code sous test et faciliter la répétition des tests.
  3. Coverage de code : Utilisez des outils comme pytest-cov pour mesurer la couverture de code de vos tests.

Défi pratique

Créez un petit scraper en utilisant Django et Pytest pour extraire les données d'un site web et les stocker dans une base de données. Assurez-vous d'avoir des tests automatisés pour vérifier que le scraper fonctionne correctement.


Ce tutoriel vous a hopefully aidé à comprendre comment tester Django avec Pytest. N'hésitez pas à me poser des questions si vous avez besoin d'aide supplémentaire !

Besoin d'aide sur Django ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Quelle est l'importance de tester un projet Django avec Pytest?
Pytest offre une grande flexibilité et rapidité dans la création et la exécution des tests, facilitant ainsi le développement et la maintenance du code.
Comment installer Pytest pour un projet Django existant?
Pour installer Pytest dans votre environnement virtuel Django, vous pouvez utiliser la commande 'pip install pytest' dans le terminal de votre projet.
Quelles sont les principales commandes Pytest que je devrais connaitre pour tester un projet Django?
Les principales commandes incluent 'pytest' qui exécute tous les tests, 'pytest --cov=app_name' pour mesurer la couverture de code et 'pytest -v' pour obtenir une sortie plus détaillée.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.