Maison >développement back-end >Tutoriel Python >Un guide des tests d'unité Python avec unittest et pytest

Un guide des tests d'unité Python avec unittest et pytest

William Shakespeare
William Shakespeareoriginal
2025-02-19 08:57:13821parcourir

A Guide to Python Unit Testing with unittest and pytest

Cet article explore l'importance des tests de logiciels et pourquoi vous devriez y faire attention. Nous apprendrons à concevoir des tests unitaires et à rédiger des tests unitaires Python. En particulier, nous explorerons deux des cadres de test unitaires les plus couramment utilisés dans Python: unittest et pytest.

Points clés

  • Les tests unitaires sont un élément crucial du développement de logiciels, permettant aux développeurs de tester des composants ou des unités spécifiques d'un programme pour s'assurer qu'ils s'exécutent comme prévu. Les cadres de test unitaires populaires dans Python incluent unittest et pytest.
  • Les tests unitaires bien conçus doivent être rapides, indépendants, reproductibles, fiables et bien nommés. Le mode «Préparation, exécution, assertion (AAA)» est souvent utilisé pour organiser des tests unitaires, séparer la configuration, l'exécution et la vérification.
  • Le framework unittest fait partie de la bibliothèque standard Python et s'inspire de JUnit, le cadre des tests unitaires en Java. Il utilise une méthode d'affirmation spéciale et nécessite que le test soit écrit comme une méthode d'une classe héritée de la classe unittest.testcase.
  • Le cadre Pytest permet des tests complexes avec moins de code, prend en charge les suites de test unittest et fournit plus de 800 plug-ins externes. Contrairement à unittest, Pytest utilise des méthodes d'affirmation Python normales pour la rendre plus simple et plus intuitive.
  • Bien que les tests unitaires présentent de nombreux avantages, il faut se rappeler que les tests ne peuvent prouver que l'existence de défauts, mais pas l'absence de défauts. Même si tous les tests passent, cela ne peut pas prouver que le système logiciel n'a pas d'erreurs.

Introduction aux tests logiciels

Les tests logiciels sont un processus de vérification du comportement des produits logiciels pour évaluer et vérifier qu'ils sont conformes aux spécifications. Un produit logiciel peut contenir des milliers de lignes de code et des centaines de composants qui fonctionnent ensemble. Si une ligne de code ne fonctionne pas correctement, l'erreur peut se propager et provoquer d'autres erreurs. Par conséquent, pour s'assurer que le programme fonctionne comme prévu, il doit être testé.

Parce que les logiciels modernes peuvent être assez complexes, il existe plusieurs niveaux de tests pour évaluer différents aspects de l'exactitude. Selon le programme de niveau de test de certification ISTQB, il y a quatre niveaux de test de logiciels:

  1. Test unitaire: Test des lignes de code spécifiques
  2. Test d'intégration: intégration de test entre plusieurs unités
  3. Test du système: tester l'ensemble du système
  4. Test d'acceptation: vérifiez s'il répond aux objectifs commerciaux

Cet article discutera des tests unitaires, mais avant d'y entrer, je voudrais introduire un principe important dans les tests de logiciels.

Les tests

ne peuvent prouver que l'existence de défauts, mais ne peuvent pas prouver l'absence de défauts.

- ISTQB SYLLABUS CTFL 2018

En d'autres termes, même si tous les tests que vous exécutez n'affichent aucune échelle, cela ne prouvera pas que votre système logiciel est exempt d'erreurs, ou un autre cas de test ne trouvera aucun défaut dans votre comportement logiciel.

Qu'est-ce que les tests unitaires?

Il s'agit du premier niveau de test, également connu sous le nom de test de composants. Dans cette section, un seul composant logiciel est testé. Selon le langage de programmation, une unité logicielle peut être une classe, une fonction ou une méthode. Par exemple, si vous avez une classe Java appelée opération arithmétique qui contient des méthodes multiples et diviser, les tests unitaires de la classe arithmétique doivent tester le comportement correct des méthodes de multiplication et de division.

Les tests unitaires sont généralement effectués par des testeurs de logiciels. Pour exécuter des tests unitaires, les testeurs (ou développeurs) doivent accéder au code source car le code source lui-même est l'objet testé. Par conséquent, cette méthode de test de logiciel qui teste directement le code source est appelée test de boîte blanche.

Vous vous demandez peut-être pourquoi vous devriez vous soucier des tests de logiciels et si cela en vaut la peine. Dans la section suivante, nous analyserons les motivations derrière le système de logiciel de test.

Pourquoi devriez-vous effectuer des tests unitaires

Le principal avantage des tests de logiciels est qu'il améliore la qualité du logiciel. La qualité des logiciels est cruciale, en particulier dans le monde où le logiciel gère toutes sortes de choses dans nos activités quotidiennes. L'amélioration de la qualité des logiciels est toujours un objectif trop vague. Essayons de mieux illustrer ce que nous appelons la qualité des logiciels. Selon ISO / IEC Standard 9126-1 ISO 9126, la qualité du logiciel comprend les facteurs suivants:

  • fiabilité
  • fonctionnel
  • Efficacité
  • Disponibilité
  • maintenabilité
  • porabilité

Si vous possédez une entreprise, vous devez soigneusement considérer les activités de test de logiciels car cela affectera votre entreprise. Par exemple, en mai 2022, Tesla a rappelé 130 000 voitures en raison de problèmes avec le système d'infodivertissement du véhicule. Ce problème a ensuite été résolu via une mise à jour logicielle distribuée "dans l'air". Ces échecs ont causé du temps et de l'argent à l'entreprise et ont également causé des problèmes aux clients, car ils n'ont pas pu utiliser leurs voitures pendant un certain temps. Le logiciel de test coûte de l'argent, mais les entreprises peuvent également économiser des millions de supports techniques.

Les tests unitaires se concentrent sur la vérification que le logiciel s'exécute correctement, ce qui signifie vérifier que le mappage entre l'entrée et la sortie est effectué correctement. En tant qu'activité de test de bas niveau, les tests unitaires aident à identifier les erreurs tôt afin qu'ils ne les propagent pas à des niveaux plus élevés du système logiciel.

Les autres avantages des tests unitaires comprennent:

  • Intégration simplifiée: il est plus facile de résoudre les problèmes d'intégration en s'assurant que tous les composants fonctionnent indépendamment.
  • Minimiser la régression du code: avec un grand nombre de cas de test, il est plus facile de trouver des problèmes si certaines modifications du code source à l'avenir causeront des problèmes.
  • Documentation fournie: en testant le mappage correct entre l'entrée et la sortie, les tests unitaires fournissent une documentation sur la façon d'utiliser la méthode ou la classe testée.

Stratégies de test de conception

Voyons maintenant comment concevoir une stratégie de test.

Définition de la portée du test

Avant de commencer à planifier votre stratégie de test, il y a une question importante à répondre. Quelles parties du système logiciel souhaitez-vous tester?

Il s'agit d'un problème clé, car les tests exhaustifs sont impossibles. Par conséquent, vous ne pouvez pas tester toutes les entrées et sorties possibles, mais vous devez prioriser les tests en fonction des risques impliqués.

Un certain nombre de facteurs doivent être pris en compte lors de la définition de la portée du test:

  • Risque: quelles conséquences commerciales se produiront si l'erreur affecte ce composant?
  • Temps: Combien de temps voulez-vous que le produit logiciel soit prêt? Avez-vous une date limite?
  • Budget: Combien d'argent êtes-vous prêt à investir dans des activités de test?

Une fois que vous avez défini la portée du test (spécifiant ce que vous devez tester et ce que vous ne devez pas tester), vous pouvez discuter des fonctionnalités d'un bon test unitaire.

Caractéristiques des tests unitaires

  • rapide. Les tests unitaires sont principalement effectués automatiquement, ce qui signifie qu'ils doivent être rapides. Les tests unitaires lents sont plus susceptibles d'être ignorés par les développeurs car ils ne fournissent pas de commentaires instantanés.
  • indépendant. Les tests unitaires sont indépendants par définition. Ils testent des unités de code individuelles et ne s'appuient pas sur des facteurs externes (tels que les fichiers ou les ressources réseau).
  • reproductible. Les tests unitaires sont exécutés à plusieurs reprises et les résultats doivent être cohérents au fil du temps.
  • fiable. Les tests unitaires échoueront uniquement s'il y a une erreur dans le système testé. L'ordre dans lequel l'environnement ou les tests sont exécutés ne doit pas être important.
  • correctement nommé. Le nom du test doit fournir des informations pertinentes sur le test lui-même.

Une étape est manquante avant de plonger dans les tests unitaires dans Python. Comment organisons-nous les tests pour les rendre propres et lisibles? Nous utilisons un modèle appelé préparation, exécution et assertion (AAA).

Mode AAA

Le modèle de préparation, d'exécution et d'affirmation (AAA) est une stratégie courante pour écrire et organiser des tests unitaires. Il fonctionne comme suit:

  • Dans la phase de préparation, définissez tous les objets et variables requis pour le test.
  • Ensuite, pendant la phase d'exécution, la fonction / la méthode / la classe à tester est appelée.
  • Enfin, dans la phase d'affirmation, nous vérifions les résultats du test.

Cette stratégie fournit un moyen propre d'organiser des tests unitaires en séparant toutes les parties principales du test (configuration, exécution et validation). De plus, les tests unitaires sont plus faciles à lire car ils suivent tous la même structure.

Tests unitaires dans Python: unittest ou pytest?

Nous allons maintenant discuter de deux cadres de test unitaires différents dans Python. Ces deux cadres sont unittest et pytest.

introduction unittest

La bibliothèque standard Python contient le cadre de test unitaire unittest. Ce cadre est inspiré par JUnit, qui est un cadre de test unitaire en Java.

Comme indiqué dans la documentation officielle, unittest prend en charge plusieurs concepts importants que nous mentionnerons dans cet article:

  • Cas de test, il s'agit d'une seule unité de test
  • Test Suite, il s'agit d'un ensemble de cas de test exécutés ensemble
  • Runner de test, qui est le composant qui gère l'exécution et les résultats de tous les cas de test

Unittest a sa propre façon d'écrire des tests. En particulier, nous avons besoin:

  1. Rédaction de nos tests en tant que méthode de classe héritée de la classe unittest.testcase
  2. Utiliser la méthode d'affirmation spéciale

Étant donné que Unittest est déjà installé, nous sommes prêts à écrire notre premier test unitaire!

Écriture des tests unitaires à l'aide d'un unittest

Supposons que nous ayons la classe BankAccount:

<code class="language-python">import unittest

class BankAccount:
  def __init__(self, id):
    self.id = id
    self.balance = 0

  def withdraw(self, amount):
    if self.balance >= amount:
      self.balance -= amount
      return True
    return False

  def deposit(self, amount):
    self.balance += amount
    return True</code>

Nous ne pouvons pas retirer de l'argent qui dépasse le montant disponible de la dépôt, alors testons si notre code source gère correctement cette situation.

Dans le même fichier Python, nous pouvons ajouter le code suivant:

<code class="language-python">class TestBankOperations(unittest.TestCase):
    def test_insufficient_deposit(self):
      # Arrange
      a = BankAccount(1)
      a.deposit(100)
      # Act
      outcome = a.withdraw(200)
      # Assert
      self.assertFalse(outcome)</code>

Nous créons une classe appelée TestBankOperations qui est une sous-classe de UnitTest.TestCase. De cette façon, nous créons un nouveau cas de test.

Dans cette classe, nous définissons une seule fonction de test dont la méthode commence par le test. Ceci est important car chaque méthode de test doit commencer par le test de mots.

Nous nous attendons à ce que cette méthode de test retourne false, ce qui signifie que l'opération a échoué. Pour affirmer le résultat, nous utilisons une méthode d'affirmation spéciale appelée ASSERTFALSE ().

Nous sommes prêts à effectuer le test. Exécutons cette commande sur la ligne de commande:

<code class="language-bash">python -m unittest example.py</code>

Ici, Exemple.py est le nom du fichier contenant tout le code source. La sortie doit ressembler à ceci:

<code>.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK</code>

Très bien! Cela signifie que notre test a réussi. Voyons maintenant à quoi ressemble la sortie lorsqu'il y a un échec. Nous ajoutons un nouveau test à la classe précédente. Essayons de déposer des montants négatifs, ce qui est certainement impossible. Notre code va-t-il gérer cette situation?

Ceci est notre nouvelle méthode de test:

<code class="language-python">  def test_negative_deposit(self):
    # Arrange
    a = BankAccount(1)
    # Act
    outcome = a.deposit(-100)
    # Assert
    self.assertFalse(outcome)</code>

Nous pouvons utiliser le mode détaillé de UnitTest pour effectuer ce test en utilisant le drapeau -v:

<code class="language-bash">python -m unittest -v example.py</code>

La sortie est différente maintenant:

<code>test_insufficient_deposit (example.TestBankOperations) ... ok
test_negative_deposit (example.TestBankOperations) ... FAIL

======================================================================
FAIL: test_negative_deposit (example.TestBankOperations)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "example.py", line 35, in test_negative_deposit
    self.assertFalse(outcome)
AssertionError: True is not false

----------------------------------------------------------------------
Ran 2 tests in 0.002s

FAILED (failures=1)</code>

Dans ce cas, le logo détaillé nous donne plus d'informations. Nous savons que Test_Negative_Deposit échoue. En particulier, AssertionError nous dit que le résultat attendu devrait être faux, mais vrai n'est pas faux, ce qui signifie que la méthode renvoie vrai.

Unittest Framework fournit différentes méthodes d'affirmation en fonction de nos besoins:

  • assertequal (x, y), testez si x == y est vrai
  • assertraises (exception_type), vérifiez si une exception spécifique a été soulevée
  • assertisnone (x), testez si x n'est aucun
  • affirmer (x, y), tester si x est en y

Maintenant que nous avons une compréhension de base de la façon d'écrire des tests unitaires à l'aide du framework unittest, jetons un coup d'œil à un autre framework Python appelé PyTest.

Introduction à pytest

Pytest Framework est un framework de test d'unité Python qui a certaines fonctionnalités connexes:

  • Il permet des tests complexes avec moins de code
  • Il prend en charge la suite de test unittest
  • Il propose plus de 800 plugins externes

Étant donné que Pytest n'est pas installé par défaut, nous devons d'abord l'installer. Notez que PyTest nécessite Python 3.7.

Installez Pytest

L'installation de Pytest est très facile. Il vous suffit d'exécuter la commande suivante:

<code class="language-python">import unittest

class BankAccount:
  def __init__(self, id):
    self.id = id
    self.balance = 0

  def withdraw(self, amount):
    if self.balance >= amount:
      self.balance -= amount
      return True
    return False

  def deposit(self, amount):
    self.balance += amount
    return True</code>

Vérifiez ensuite que tout est installé correctement en tapant:

<code class="language-python">class TestBankOperations(unittest.TestCase):
    def test_insufficient_deposit(self):
      # Arrange
      a = BankAccount(1)
      a.deposit(100)
      # Act
      outcome = a.withdraw(200)
      # Assert
      self.assertFalse(outcome)</code>

La sortie doit ressembler à ceci:

<code class="language-bash">python -m unittest example.py</code>

Très bien! Écrivons le premier test à l'aide de PyTest.

Écriture des tests unitaires en utilisant pytest

Nous utiliserons la classe BankAccount que nous avons écrite plus tôt et nous testerons la même méthode qu'auparavant. De cette façon, il est plus facile de comparer les efforts nécessaires pour rédiger des tests à l'aide de ces deux cadres.

Pour utiliser PyTest pour les tests, nous avons besoin:

  • Créez un répertoire et y met nos fichiers de test.
  • Écriture de nos tests dans des fichiers dont les noms commencent par test_ ou se terminent par _test.py. PyTest recherchera ces fichiers dans le répertoire actuel et ses sous-répertoires.

Nous créons donc un fichier nommé test_bank.py et le mettons dans un dossier. C'est à quoi ressemble notre première fonction de test:

<code>.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK</code>

Comme vous l'avez remarqué, le seul changement par rapport à la version unittest est la partie Assert. Ici, nous utilisons la méthode d'affirmation Python normale.

Maintenant, nous pouvons jeter un œil au fichier test_bank.py:

<code class="language-python">  def test_negative_deposit(self):
    # Arrange
    a = BankAccount(1)
    # Act
    outcome = a.deposit(-100)
    # Assert
    self.assertFalse(outcome)</code>

Pour exécuter ce test, ouvrons une invite de commande dans le dossier contenant le fichier test_bank.py. Ensuite, exécutez la commande suivante:

<code class="language-bash">python -m unittest -v example.py</code>

La sortie ressemblera à ceci:

<code>test_insufficient_deposit (example.TestBankOperations) ... ok
test_negative_deposit (example.TestBankOperations) ... FAIL

======================================================================
FAIL: test_negative_deposit (example.TestBankOperations)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "example.py", line 35, in test_negative_deposit
    self.assertFalse(outcome)
AssertionError: True is not false

----------------------------------------------------------------------
Ran 2 tests in 0.002s

FAILED (failures=1)</code>

Dans ce cas, nous pouvons voir à quel point il est facile d'écrire et d'exécuter des tests. De plus, nous pouvons voir que nous écrivons moins de code que Unittest. Les résultats du test sont également faciles à comprendre.

Continuons à regarder les tests échoués!

Nous utilisons la deuxième méthode que nous avons écrite auparavant, ce qui est appelé test_negative_deposit. Nous refacteurs la partie affirmer et le résultat est le suivant:

<code class="language-bash">pip install -U pytest</code>

Nous exécutons les tests comme auparavant, qui devraient être la sortie:

<code class="language-bash">pytest --version</code>

En analysant la sortie, nous pouvons lire 2 éléments collectés, ce qui signifie que deux tests ont été effectués. Faites défiler vers le bas et nous pouvons voir une erreur s'est produite lors du test de la méthode Test_Negative_Deposit. En particulier, des erreurs se produisent lors de l'évaluation des affirmations. De plus, le rapport indique également que la valeur de la variable de résultat est vraie, ce qui signifie que la méthode de dépôt contient des erreurs.

Étant donné que PyTest utilise le mot-clé Python Assertion par défaut, nous pouvons comparer toutes les sorties que nous atteignons avec une autre variable qui stocke le résultat attendu. Tout cela ne nécessite aucune méthode d'affirmation spéciale.

Conclusion

Dans cet article, nous présentons les bases des tests logiciels. Nous avons découvert pourquoi les tests de logiciels sont cruciaux et pourquoi chacun devrait tester son code. Nous discutons des tests unitaires et de la façon de concevoir et d'implémenter des tests unitaires simples dans Python.

Nous utilisons deux frameworks Python appelés unittest et pytest. Les deux ont des fonctionnalités utiles, et ils sont deux des cadres les plus couramment utilisés dans les tests d'unité Python.

Enfin, nous voyons deux cas de test de base pour vous donner une idée de la façon d'écrire des tests dans les modèles de préparation, d'exécution et d'affirmation.

J'espère que je vous ai convaincu l'importance des tests de logiciels. Choisissez un cadre, comme unittest ou pytest, et commencez à tester - car l'effort supplémentaire en vaut la peine!

Si vous aimez cet article, vous pouvez également trouver le suivant utile:

  • Test de cyprès: un guide pour exécuter les applications Web
  • comment tester les composants de réaction avec une plaisanterie
  • Apprenez des tests de bout en bout avec des marionnettistes
  • 3 façons de tester en continu les mains libres
  • Réintroduction Jenkins: Utilisez des tuyaux pour les tests automatisés

FAQ sur Python Unit Testing

Que sont les tests unitaires dans Python? Les tests unitaires dans Python sont une technique de test de logiciels dans laquelle une seule unité ou un composant d'un programme est testée isolée pour s'assurer que chaque unité fonctionne comme prévu.

Pourquoi les tests unitaires sont-ils importants dans le développement de Python? Les tests unitaires aident à garantir l'exactitude des composants individuels dans un programme Python. Il aide à détecter tôt les erreurs, fournit un filet sûr pour les modifications de code et prend en charge la maintenabilité du code.

Comment écrire des tests unitaires dans Python? Les tests unitaires dans Python sont souvent écrits à l'aide du module unittest intégré. Vous créez des classes de test héritées à partir des méthodes de test unittest.testcase et d'écriture dans ces classes. Les méthodes de test commencent généralement par "test".

Quels autres frameworks puis-je utiliser pour les tests d'unité Python en plus d'Unittest? Oui, en plus d'Unittest, il existe d'autres cadres de test Python populaires tels que PyTest et Nose2. Ces cadres offrent différentes fonctionnalités et syntaxes, permettant aux développeurs de choisir celui qui répond le mieux à leurs besoins.

Quel est le rôle du luminaire dans les tests unitaires Python? Le luminaire est un moyen de définir des conditions préalables à Python et de nettoyer après les tests. Ils aident à s'assurer que les tests sont indépendants et peuvent fonctionner indépendamment.

Qu'est-ce que la couverture des tests et pourquoi est-ce important? La couverture des tests mesure le pourcentage de la base de code que vos tests exécutent. Il aide à identifier le code non testé et garantit que vos tests sont complets, réduisant ainsi la possibilité que les erreurs soient découvertes.

Quelles sont les meilleures pratiques pour rédiger des tests unitaires efficaces à Python? Oui, certaines meilleures pratiques incluent la rédaction de tests indépendants et isolés, en utilisant des noms de méthode de test descriptifs et tester les situations limites. De plus, essayez d'obtenir une bonne couverture de test et d'exécuter fréquemment des tests.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn