Commit 51d9f1f7 authored by Bonnegent Sebastien's avatar Bonnegent Sebastien
Browse files

cours 6 ok

parent e1d7bc1c
% Django par la pratique #06
% Sébastien Bonnegent
% https://framagit.org/bonnegent/cours\_django
% version 2018
# Objectifs
## Pour la séance
# Prérequis
## Virtual Env
* source /opt/venv/django/bin/activate
* pipenv shell
### Objectif
* Mettre en place des tests
## Prérequis
### VirtualEnv
## Base de départ
~~~
$ pip install pytest-django
$ #!! settings.py et db.sqlite3 dans le dépôt !!
$ git clone \
https://gitlab.insa-rouen.fr/bonnegent/vehicules.git
$ cd vehicules
$ git checkout cours_6_debut
~~~
### pytest.ini
~~~{.py .numberLines}
[pytest]
DJANGO_SETTINGS_MODULE = conf.settings
python_files = tests.py test_*.py *_tests.py
FAIL_INVALID_TEMPLATE_VARS = True
~~~
## Doc
* https://docs.djangoproject.com/fr/2.1/topics/testing/tools/
### Exécution
### Comment faire ?
~~~
$ source /opt/venv/spyder/bin/activate
$ echo "créer le fichier pytest.ini"
$ pytest
$ pytest -v
$ ./manage.py test
~~~
# Exemples
## webui/tests.py
### Accès anonyme
~~~{.py .numberLines}
import pytest
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
from webui.models import Parefeu
from webui.models import Regle
from webui.models import Service
def test_home_anon(client):
response = client.get('/parefeux/')
assert response.status_code == 302
~~~
### Accès admin
~~~{.py .numberLines}
def test_an_admin_view(admin_client):
response = admin_client.get('/admin/')
assert response.status_code == 200
# Tests sur les URLs en anonyme
## URLs en connexion anonyme
### garage/tests.py
~~~python
from django.test import TestCase
from django.test import Client
from django.urls import reverse
from django.contrib.auth.models import User
from django.core import mail
class URLAnonymeTest(TestCase):
def test_index(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
~~~
### URL simple
~~~{.py .numberLines}
def test_urls_simple(admin_client):
response = admin_client.get('/services/')
assert response.status_code == 200
response = admin_client.get('/ports/')
assert response.status_code == 200
response = admin_client.get('/parefeux/')
assert response.status_code == 200
response = admin_client.get('/contact/')
assert response.status_code == 200
## test_login
### garage/tests.py
~~~python
def test_login(self):
response = self.client.get(reverse('login'))
self.assertEqual(response.status_code, 200)
uri = reverse('garage:vehicule-list')
response = self.client.get(uri)
self.assertRedirects(response,
'/accounts/login/?next=/vehicule/')
~~~
### URL simple v2
~~~{.py .numberLines}
def test_urls_simple(admin_client):
urls = ['services', 'ports', 'parefeux',
'contact']
for url in urls:
response = admin_client.get(reverse(url))
assert response.status_code == 200
## À faire
* test_logout
* test_admin
* test_home
* ...
# Tests sur les URLs avec connexion
## Des objets pour les tests #1
### garage/tests.py
~~~python
def create_data(self):
self.user1 = User.objects.create(username="user1")
self.user1.save()
self.user2 = User.objects.create(username="user2")
self.user2.save()
self.admin = User.objects.create(username="admin",
is_staff=True,
is_superuser=True)
self.admin.save()
create = Vehicule.objects.create
self.vehicule1 = create(marque="Toto", modele="TX",
proprietaire=self.user1)
~~~
### Données pour les tests
~~~{.py .numberLines}
@pytest.fixture
def parefeu1(admin_user):
get_or_create = Parefeu.objects.get_or_create
(parefeu, created) = get_or_create(nom="parefeu1",
admin=admin_user)
return parefeu
## Des objets pour les tests #2
### garage/tests.py
~~~python
class URLUserTest(TestCase):
def setUp(self):
self.client = Client()
create_data(self)
self.user1.set_password("pour_les_tests")
self.user1.save()
response = self.client.login(
username=self.user1.username,
password="pour_les_tests")
self.assertEqual(response, True)
~~~
# À faire
## webui/tests.py
### test\_parefeu(admin\_client, parefeu1)
* affiche un parefeu
* test du code de retour (200)
### test\_nb\_regles\_parefeu(admin\_user, parefeu1)
* on crée plusieurs règles
* Parefeu.nombre\_de\_regles() doit donner le bon nombre
### test\_nb\_regles\_modele(admin\_user, parefeu1, parefeu2)
* comme précédent mais pour les règles sur un modèle
* parefeu2 est le modele de parefeu1
* parefeu1 n'a pas de règles
* parefeu2 a des règles
* nb\_regles doit retourner nb\_regle de parefeu1 + parefeu2
### test\_parefeu\_level1(admin\_client, parefeu1, parefeu2)
## test_vehicule_detail
### garage/tests.py
~~~python
def test_vehicule_detail(self):
uri = reverse('garage:vehicule-detail',
kwargs={'pk': self.vehicule1.pk})
response = self.client.get(uri)
self.assertEqual(response.status_code, 200)
# test du context
self.assertEqual(response.context['vehicule'],
self.vehicule1)
~~~
* un parefeu ne peut être le modèle de son modèle
* parefeu1.modele = parefeu2
* parefeu2.modele = parefeu1
* raise ValidationError
* [webui/models.py] définir Parefeu.clean()
* voir la documentation
* prise en compte dans les formulaires
* raise ValidationError
* écrire le test
## test_contact #1
### garage/tests.py
~~~python
def test_contact(self):
response = self.client.get(reverse('garage:contact'))
self.assertEqual(response.status_code, 200)
# il n'y a aucun message dans la mailbox
self.assertEqual(len(mail.outbox), 0)
mon_sujet = "un sujet !"
uri = reverse('garage:contact')
response = self.client.post(uri,
{'sujet': mon_sujet, 'message': "blablabla"})
self.assertRedirects(response, '/')
~~~
### test\_parefeu\_level2(admin\_client, parefeu1, parefeu2, parefeu3)
## test_contact #2
### garage/tests.py
~~~python
# il y a 1 message dans la mailbox
self.assertEqual(len(mail.outbox), 1)
* un parefeu ne peut être le modèle du modèle du modèle ... de son modèle
* [webui/models.py] modifier Parefeu.clean()
* définir une profondeur maximum de parcous (12)
* raise ValidationError
* écrire le test
* parefeu1.modele = parefeu2
* parefeu2.modele = parefeu3
* parefeu3.modele = parefeu1
# on vérifie le sujet du premier mail
self.assertEqual(mail.outbox[0].subject, mon_sujet)
~~~
## Documentations
### liens
## Commandes disponibles
### garage/tests.py
~~~python
self.client.get(uri, {args, ...})
self.client.post(uri, {args, ...})
uri = reverse('garage:vehicule-visible',
kwargs={'pk': self.vehicule1.pk})
self.client.force_login(self.user2)
...
~~~
* https://docs.pytest.org/en/latest/
* https://pytest-django.readthedocs.io/en/latest/
* https://pytest-django.readthedocs.io/en/latest/tutorial.html
* https://docs.djangoproject.com/fr/1.11/topics/forms/modelforms/
## À faire
* test_vehicule_visible
* test_garage_create
* test_vehicule_update
## test_vehicule_visible
### garage/tests.py
~~~python
def test_vehicule_visible(self):
self.assertEqual(self.vehicule1.visible, False)
uri_visible = reverse('garage:vehicule-visible',
kwargs={'pk': self.vehicule1.pk})
uri_detail = reverse('garage:vehicule-detail',
kwargs={'pk': self.vehicule1.pk})
response = self.client.post(uri_visible)
self.assertRedirects(response, uri_detail)
# self.assertEqual(self.vehicule1.visible, True)
vehicule1 = Vehicule.objects.get(pk=self.vehicule1.pk)
...
~~~
* https://framagit.org/bonnegent/fwm
## Problème détecté
* User2 peut modifier les véhicules de User1 !
## Résolution du problème
### garage/views.py
~~~python
def form_valid(self, form):
if form.instance.proprietaire != self.request.user:
messages.warning(self.request,
"Vous ne pouvez modifier ce véhicule")
return redirect('garage:vehicule-detail',
form.instance.pk)
return super().form_valid(form)
~~~
No preview for this file type
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment