0% ont trouvé ce document utile (0 vote)
4 vues21 pages

Python TestsUnitaires

Le document présente les tests unitaires en Python, en se concentrant sur plusieurs frameworks tels que unittest, doctest et pytest. Il fournit des exemples de code illustrant la création et l'exécution de tests unitaires, ainsi que des fonctionnalités avancées comme les fixtures et les tests paramétrés. Enfin, il met en avant les avantages et inconvénients de chaque framework pour aider à choisir le plus adapté aux besoins de développement.

Transféré par

Abdul Jalil Sana
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
4 vues21 pages

Python TestsUnitaires

Le document présente les tests unitaires en Python, en se concentrant sur plusieurs frameworks tels que unittest, doctest et pytest. Il fournit des exemples de code illustrant la création et l'exécution de tests unitaires, ainsi que des fonctionnalités avancées comme les fixtures et les tests paramétrés. Enfin, il met en avant les avantages et inconvénients de chaque framework pour aider à choisir le plus adapté aux besoins de développement.

Transféré par

Abdul Jalil Sana
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Python

Tests Unitaires

Nicolas Delestre

Tests Unitaires - v1.1 1 / 21


Plan

1 Les frameworks

2 pytest

Tests Unitaires - v1.1 2 / 21


Exemple d’erreur

[Link]
def _get_x(self):
return self._x

def _set_x(self, x):


self._x = x

x = property(_get_x, _set_x)

@property
def y(self):
return self._x

Tests Unitaires - v1.1 3 / 21


Les frameworks

Plusieurs frameworks

Il y a eu historiquement plusieurs frameworks de développement de


tests unitaires sour python :
unittest
nose
doctest
pytest

Tests Unitaires - v1.1 4 / 21


Les frameworks

unittest 1 / 2
Caractéristiques
S’inspire des framework de tests unitaires des autres langages,
comme JUnit
Intégré de base à python
Il ne tire pas parti des aspects introspections du python

Développement du test unitaire : test [Link]


import unittest
from point import Point2D

class TestPoint2D([Link]):
def test_abscisse(self):
[Link](Point2D(1,2).x, 1)

def test_ordonnee(self):
[Link](Point2D(1,2).y, 2)

if __name__ == "__main__":
[Link]()

Tests Unitaires - v1.1 5 / 21


Les frameworks

unittest 2 / 2

Exécution du test unitaire


$ python3 test_point.py
.F
======================================================================
FAIL: test_ordonnee (__main__.TestPoint2D)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_point.py", line 11, in test_ordonnee
[Link](Point2D(1,2).y, 2)
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (failures=1)

Tests Unitaires - v1.1 6 / 21


Les frameworks

doctest 1 / 5

Caractéristiques
Très pythonic
Avantages :
intégré de base à python
la documentation intègre les tests unitaires (tests à jour, sert aussi de
documentation)
Le module et les tests unitaires forment un tout (exécution des tests
dans la partie if name == " main ")
Inconvénients :
si les tests sont long, la documentation prend beaucoup de place
attention aux espaces (ou tabulations) après le résultat attendu

Tests Unitaires - v1.1 7 / 21


Les frameworks

doctest 2 / 5

Définition des tests unitaires : [Link]


@property
def x(self):
""" Propriété permettant d’obtenir et de fixer l’abscisse d’un Point2D

>>> p = Point2D(1,2)
>>> p.x
1
>>> p.x = 3
>>> p.x
3
"""
return self._x

@[Link]
def x(self, x):
self._x = x

Tests Unitaires - v1.1 8 / 21


Les frameworks

doctest 3 / 5

Définition des tests unitaires : [Link] (suite et fin)


@property
def y(self):
""" Propriété permettant d’obtenir et de fixer l’ordonnée d’un Point 2D

>>> p = Point2D(1,2)
>>> p.y
2
>>> p.y = 3
>>> p.y
3
"""
return self._x

Code d’exécution : [Link]


if __name__ == "__main__":
import doctest
[Link]()

Tests Unitaires - v1.1 9 / 21


Les frameworks

doctest 4 / 5
Exécution directement depuis le module
$ python3 [Link]
**********************************************************************
File "[Link]", line ?, in __main__.Point2D.y
Failed example:
p.y
Expected:
2
Got:
1
**********************************************************************
File "[Link]", line ?, in __main__.Point2D.y
Failed example:
p.y
Expected:
3
Got:
1
**********************************************************************
1 items had failures:
2 of 4 in __main__.Point2D.y
***Test Failed*** 2 failures.

Tests Unitaires - v1.1 10 / 21


Les frameworks

doctest 5 / 5
Apparition des tests dans la documentation
$ python3
>>> import point
>>> help(point.Point2D)
Help on class Point2D in module point:

class Point2D([Link])
| Methods defined here:
...
| Data descriptors defined here:
|
...
| x
| Propriété permettant d’obtenir et de fixer l’abscisse d’un Point2D
|
| >>> p = Point2D(1,2)
| >>> p.x
| 1
| >>> p.x = 3
| >>> p.x
| 3
|
| y
| Propriété permettant d’obtenir et de fixer l’ordonnée d’un Point 2D
|
| >>> p = Point2D(1,2)
| >>> p.y
| 2
| >>> p.y = 3
| >>> p.y
| 3
Tests Unitaires - v1.1 11 / 21
pytest

Pytest

Caractéristiques
Le plus populaire !
Très simple à mettre en oeuvre (utilisation poussée de
l’introspection)
Recherche de lui même les tests unitaires (modules/fonctions dont
le nom commence par test )
Des messages clairs
Les méthodes avant (setup()) et après (teardown()) les tests
unitaires sont remplacées par des fixtures
Possibilité de paramétrer des tests
Sait utiliser les tests unittest et doctest
Ne fait pas parti de l’installation de base :
pipenv install pytest

Tests Unitaires - v1.1 12 / 21


pytest

Premier exemple 1 / 2

test [Link]
#!/usr/bin/env python

from point import Point2D

def test_abscisse():
assert Point2D(1,2).x == 1

def test_ordonnee():
assert Point2D(1,2).y == 2

Tests Unitaires - v1.1 13 / 21


pytest

Premier exemple 2 / 2

Exécution
python3 -m pytest
=================================== test session starts ===================================
platform linux -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir:/home/delestre/Documents/Cours/ASI/Python/Cours/08-TestsUnitaires/Version1.1/exemples
/pytest/erreursSurPoint
collected 2 items

test_point.py .F [100%]

======================================== FAILURES =========================================


______________________________________ test_ordonnee ______________________________________

def test_ordonnee():
> assert Point2D(1,2).y == 2
E assert 1 == 2
E + where 1 = Point2D(1,1).y
E + where Point2D(1,1) = Point2D(1, 2)

test_point.py:9: AssertionError
=============================== 1 failed, 1 passed in 0.03s ===============================

Tests Unitaires - v1.1 14 / 21


pytest

Deuxième exemple

test [Link] (on suppose [Link] corrigé)


#!/usr/bin/env python3

import pytest
from polyligne import Polyligne, MemePointInterditErreur
from point import Point2D

def test_polyligne_est_fermee():
polyligne_fermee = Polyligne(True, Point2D(1,1), Point2D(2,2), Point2D(1,2))
assert polyligne_fermee.est_ferme

def test_polyligne_longueur():
polyligne_fermee = Polyligne(True, Point2D(1,1), Point2D(2,2), Point2D(1,2))
assert len(polyligne_fermee) == 3

def test_polyligne_longueur_apres_ajout():
polyligne_fermee = Polyligne(True, Point2D(1,1), Point2D(2,2), Point2D(1,2))
longueur = len(polyligne_fermee)
polyligne_fermee.ajouter(Point2D(0,0))
assert len(polyligne_fermee) == longueur + 1

def test_polyligne_ajout_avec_erreur():
polyligne_fermee = Polyligne(True, Point2D(1,1), Point2D(2,2), Point2D(1,2))
with [Link](MemePointInterditErreur):
polyligne_fermee.ajouter(Point2D(1,1))

Tests Unitaires - v1.1 15 / 21


pytest

Fixture 1/3

Remarques sur l’exemple


Du code a été copié/collé (création de polyligne fermee)
Une solution serait de faire une variable globale
Sauf que certains tests la modifieraient (par exemple
est polyligne longueur apres ajout)

Fixture
les fixtures permettent de générer des données de tests
les fixtures sont paramétrable à l’aide des paramètres nommés, entre
autres :
scope qui définit la portée de création (session, module, class,
function)
params et le paramètre formel request qui possède un champ param
des fixtures sont utilisés comme paramètres formels des tests

Tests Unitaires - v1.1 16 / 21


pytest

Fixture 2/3

test [Link]
@[Link](scope="function")
def polyligne_fermee():
return Polyligne(True, Point2D(1,1), Point2D(2,2), Point2D(1,2))

@[Link](scope="function", params=[Point2D(1,1), Point2D(2,2), Point2D(1,2)])


def point_a_ajouter_qui_pose_probleme(request):
return [Link]

@[Link](scope="function", params=[Point2D(0,0), Point2D(2,1), Point2D(3,3)])


def point_a_ajouter_qui_ne_pose_pas_probleme(request):
return [Link]

def test_polyligne_est_fermee(polyligne_fermee):
assert polyligne_fermee.est_ferme

def test_polyligne_longueur_apres_ajout(polyligne_fermee):
longueur = len(polyligne_fermee)
polyligne_fermee.ajouter(Point2D(0,0))
assert len(polyligne_fermee) == longueur + 1

def test_polyligne_ajout_avec_erreur(polyligne_fermee, point_a_ajouter_qui_pose_probleme):


with [Link](MemePointInterditErreur):
polyligne_fermee.ajouter(point_a_ajouter_qui_pose_probleme)

def test_polyligne_ajout_sans_erreur(polyligne_fermee, point_a_ajouter_qui_ne_pose_pas_probleme):


polyligne_fermee.ajouter(point_a_ajouter_qui_ne_pose_pas_probleme)

Tests Unitaires - v1.1 17 / 21


pytest

Fixture 3/3

Exécution : il y a bien 8 tests unitaires qui sont exécutés


$ python3 -m pytest
=================================== test session starts ===================================
platform linux -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /home/delestre/Documents/Cours/ASI/Python/Cours/08-TestsUnitaires/Version1.1/exemples
/pytest/erreursSurPolyligne
collected 11 items

test_polyligne.py ........... [100%]

=================================== 11 passed in 0.03s ====================================

Tests Unitaires - v1.1 18 / 21


pytest

Paramètre 1 / 3
Tests unitaires paramétrés
Quelques fois on veut tester une fonction ou une méthode avec
plusieurs valeurs
Il est possible de définir une fonction de tests qui possède un ou
plusieurs paramètres formels et de demander l’exécution de cette
fonction, grâce au décorateur @[Link], avec
une liste de paramètres effectifs (qui sont des tuples si la fonction
admet plusieurs paramètres formels)

Exemple
On voudrait vérifier que la longueur d’une polyligne fonctionne bien
après la création de la dı̂te polyligne :
quelles soient fermées ou pas
qu’il y ait utilisation ou pas des paramètres non nommés optionnels

def __init__(self, est_ferme, pt1, pt2, *args):


Tests Unitaires - v1.1 19 / 21
pytest

Paramètre 2 / 3

test [Link] : ajout d’un test paramétré


@[Link]("polyligne, longueur",
[(Polyligne(False, Point2D(1,1), Point2D(2,2)), 2),
(Polyligne(True, Point2D(1,1), Point2D(2,2)), 2),
(Polyligne(False, Point2D(1,1), Point2D(2,2), Point2D(1,2)), 3)
])
def test_polyligne_longueur_apres_init(polyligne, longueur):
assert len(polyligne) == longueur

Tests Unitaires - v1.1 20 / 21


pytest

Paramètre 3 / 3

Exécution : il y a bien 11 (8+3) tests unitaires qui sont exécutés


$ python -m pytest
=================================== test session starts ===================================
platform linux -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /home/delestre/Documents/Cours/ASI/Python/Cours/08-TestsUnitaires/Version1.1/exemples
/pytest/erreursSurPolyligne
collected 11 items

test_polyligne.py ........... [100%]

=================================== 11 passed in 0.02s ====================================..

Tests Unitaires - v1.1 21 / 21

Vous aimerez peut-être aussi