Tests unitaires automatisés d’une Application Web en Python

#Python #Unittest #Selenium #Automation

Dans cet article, nous allons examiner comment tester une application Web en Python afin de vérifier l’exactitude des fonctionnalités. Ouah! Cette phrase a une poignée de jargon: test unitaire, application Web et test de fonctionnalité.

Nous avons examiné le test unitaire d’un programme Python dans un article précédent. Nous vous encourageons à le parcourir, si vous n’êtes pas familier avec les tests unitaires.

Qu’est-ce qu’un test unitaire ?L’unité

est la plus petite partie testable d’un programme ou d’une application.

Ainsi, les tests unitaires sont utilisés pour tester par programme chaque composant testable.

Vous pouvez tester un programme backend ou un programme frontend tel qu’une application web.

Pour un programme backend, vous écririez un test unitaire pour chaque fonction ou méthode dans le code car ce sont des unités logiques les plus petites.

Cependant, pour un frontend, vous identifierez les différentes fonctionnalités que vous souhaitez vérifier et écrirez des tests unitaires en conséquence.

Dans cet article, nous allons tester un programme frontend, à savoir une application web.

Qu’est-ce qu’une application web ?

Toute application qui s’affiche sur un navigateur Web tel que Chrome, Firefox ou Safari.

Toutes les applications Web ont un point commun : elles sont visibles par les utilisateurs finaux une page HTML (Hypertext Markup Language). HTML est simplement un langage de formatage pour décrire comment les choses doivent être organisées. Il s’agit simplement d’un fichier texte.

Les navigateurs obtiennent cette page HTML et interprètent les balises (par exemple HEAD, BODY, HREF, TABLE, etc.) afin de vous montrer une jolie page.

Les applications Web fonctionnent dans l’architecture client-serveur – où le serveur Web héberge le contenu auquel vous souhaitez accéder et le navigateur Web agit en tant que client.

Architecture Web Client-serveur

Qu’est-ce que le test de fonctionnalité ?

Comme son nom l’indique, lorsque vous écrivez du code de test fonctionnel, votre objectif est de tester la fonctionnalité de l’application. En d’autres termes, vous voulez vous assurer que l’application respecte les spécifications fonctionnelles.

Il existe d’autres types de tests tels que des tests de performance, des tests de sécurité (pénétration) et des tests d’acceptabilité de l’utilisateur.

Le code de test fonctionnel que vous écrivez peut être inclus dans ce qu’on appelle un test de régression qui est exécuté périodiquement afin de s’assurer que l’ancienne fonctionnalité n’est pas interrompue en raison d’un nouveau développement.

A la fin de ce post, vous comprendrez le code complet mentionné ci-dessous.

Ne soyez pas découragé si vous avez l’impression que c’est trop. Le but de cet article est de disséquer cela et de vous montrer comment vous pouvez comprendre ce code, puis écrire le vôtre!

Le diagramme suivant montre l’approche de haut niveau pour tester automatiquement une application Web (page).

Étapes de test d’application Web

Afin d’écrire nos tests, nous utilisons un framework de test appelé unittest. Il est très similaire à junit en Java ou nunit en .Net.

unittest vous permet de regrouper votre code d’initialisation dans une fonction de configuration et de nettoyer le code d’une fonction de démontage.

Le diagramme suivant montre l’approche globale derrière les tests unitaires.

Cadre de test unitaire

Comme vous pouvez le voir sur le diagramme ci-dessus, une suite de tests se compose d’un ou plusieurs cas de test.

Un scénario de test peut avoir un ou plusieurs tests. Dans cet article, nous allons nous concentrer sur un cas de test avec un test. Nous montrerons à la fin comment ajouter plus de tests au même cas de test ainsi que créer une suite de tests.

Comme mentionné précédemment, chaque cas de test a des méthodes setUp (exécuté au début) et tearDown (exécuté à la fin) pour effectuer respectivement l’initialisation et le nettoyage.

Structure d’un scénario de test unitaire

L’extrait de code ci-dessus montre la structure d’un scénario de test unitaire.

Ligne 1 : Importez les bibliothèques nécessaires. Dans notre cas, nous utilisons des bibliothèques sélénium et unittest.

Ligne 3 : Vous créez une classe nommée MyTestCase qui étend unittest.Classe TestCase. Nous disons cela unittest.TestCase est la classe parent et MyTestCase est la classe enfant.

Ligne 4: Nous ajoutons notre code d’initialisation dans la méthode de configuration. Vous devez utiliser le nom exact de la méthode pour faire savoir à unittest que vous ajoutez votre code d’initialisation ici. Lorsque vous exécutez ce cas de test, cette méthode est exécutée en premier.

Ligne 7: Un échantillon de test que nous voulons inclure dans le scénario de test.

Ligne 10: Un autre échantillon de test que nous avons dans notre cas de test.

Ligne 16: Nous ajoutons notre code de nettoyage à l’intérieur de cette méthode de démontage. À l’opposé de la méthode d’installation, la méthode de démontage est exécutée la dernière.

Ainsi, l’ordre d’invocation de la méthode est:

setUp > test1 > test2 > … > tearDown

Ligne 20: Cela indique que le programme principal démarre à cet endroit.

Ligne 21: Voici comment vous exécutez le scénario de test.

Il est maintenant temps pour nous de mettre la main sur le test réel que nous voulions faire. Rappelons que nous voulons tester si la boîte de recherche Google renvoie au moins 5 résultats pour un mot-clé de recherche donné.

Regardons d’abord la méthode de configuration:

Dans cet extrait de code, nous créons le pilote du navigateur Chrome.

Vous devez télécharger le pilote selenium Chrome à partir d’ici si vous ne l’avez pas déjà. Au moment d’écrire ces lignes, Chrome a également la version 74. Puisque mon navigateur Chrome est la version 73, j’ai téléchargé la version 73 pour cet exercice.

Les lignes 2 et 3 créent l’option Chrome et informent selenium webdriver que nous ne voulons pas rendre le navigateur visible lorsque nous exécutons le test.

Si vous n’ajoutez pas cette option, votre test est bloqué au point où le navigateur s’ouvre.

Regardons maintenant la méthode de démontage:

Nous nettoyons simplement le pilote en appelant la méthode quit().

Enfin, il est temps de jeter un coup d’œil au test que nous voulons inclure dans ce cas de test. Rappelons que nous pouvons tester (affirmer) si le nombre de résultats de recherche retournés est supérieur ou égal à 5.

Le code de test réel

Ligne 1: La méthode de test commence par le mot « test ».

Ligne 3: Charge www.google.com page web dans le pilote (Notez que self.le pilote est créé pendant le temps de configuration).

Ligne 6: Localisez la zone de recherche par nom d’élément HTML « q ». Vous devez inspecter la page HTML afin de l’identifier.

Ligne 7: Rendez la zone de recherche vide au cas où il y aurait des valeurs par défaut.

Ligne 10: Remplissez la zone de recherche avec la chaîne de recherche « Tests automatisés ».

Ligne 11: Soumettez la requête de recherche à Google.

Ligne 14 : XPath identifiant les en-têtes des résultats de recherche.

Ligne 17: Attendez 10 secondes jusqu’à ce que la page de résultats Google soit chargée.

Ligne 20 : Obtenez tous les en-têtes de résultats de recherche en utilisant le XPath défini à la ligne 14.

Lignes 25 et 26: Les en-têtes des résultats de recherche sont en fait une liste et nous les parcourons pour les afficher à l’écran. Nous avons ajouté ces deux lignes à des fins de démonstration uniquement. Habituellement, les scripts de test n’ont pas d’écrans d’impression car il n’y a personne disponible pour regarder l’écran pour voir une telle sortie lorsqu’elle est automatisée.

Ligne 30: C’est l’affirmation réelle que nous faisons. assertGreater est une méthode définie dans unittest.Classe TestCase qui nous permet de vérifier si une sortie est supérieure à la valeur some.

test unitaire.TestCase nous fournit en fait un ensemble de cette méthode pour vérifier l’égalité, supérieure à, inférieure à, etc. selon ce que vous voulez affirmer. Le tableau suivant montre certaines des méthodes d’assertion courantes disponibles.

Méthodes d’affirmation courantes dans unittest.TestCase

Comme indiqué au début, vous pouvez écrire le scénario de test en invoquant ce qui suit dans votre code:

unittest.main()

Dans la ligne de commande, vous pouvez simplement taper le nom de fichier que vous avez utilisé pour enregistrer le scénario de test.

python google_search_test.py

Il exécute setUp(), puis test_result_count() et enfin tearDown().

Vous devriez voir une sortie similaire à ce qui suit:

Sortie de l’exécution du scénario de test

Si un test échoue, vous verrez le message d’ÉCHEC avec la méthode de test qui a échoué.

C’est votre premier cas de test Sélénium / unittest réussi. Bravo! C’est une étape importante.

Bonus

Si vous avez la vapeur, je vous encourage à suivre le reste afin d’approfondir encore plus les tests automatisés de l’application web de base Selenium / unittest.

Disons que vous voulez tester si l’en-tête est égal à « Google ».

Le code de test se présente comme suit:

def test_header(self):
self.driver.get("http://www.google.com")
self.assertEqual("Google", self.driver.title)

Maintenant, tout notre cas de test se présente comme suit:

class GoogleSearchTest(unittest.TestCase):
def setUp(self): def test_header(self): def test_result_count(self): def tearDown(self):
if __name__ == "__main__":
unittest.main()

Supposons que les écrans d’impression ci-dessus soient commentés. Lorsque vous exécutez le scénario de test mis à jour, vous devez obtenir une sortie comme suit:

test_header (__main__.GoogleSearchTest) ... ok
test_result_count (__main__.GoogleSearchTest) ... ok----------------------------------------------------------------------
Ran 2 tests in 13.799s
OK

Il dit qu’il a effectué deux tests et que les deux sont réussis.

Disons que je change la condition assertEqual dans le premier test à la suivante:

self.assertEqual("Microsoft", self.driver.title)

Que pensez-vous que cela arriverait ici?

Oui, vous l’avez bien deviné. Le premier cas de test échouera en tant que self.pilote.le titre est égal à Google, pas à Microsoft.

Vous obtiendrez une sortie similaire à ce qui suit:

test_header (__main__.GoogleSearchTest) ... FAIL
test_result_count (__main__.GoogleSearchTest) ... ok
====================================================================
FAIL: test_header (__main__.GoogleSearchTest)
--------------------------------------------------------------------
Traceback (most recent call last):
File "google_search_test.py", line 19, in test_header
self.assertEqual("Microsoft", self.driver.title)
AssertionError: 'Microsoft' != 'Google'
- Microsoft
+ Google
--------------------------------------------------------------------
Ran 2 tests in 14.011s
FAILED (failures=1)

La sortie ci-dessus indique qu’un seul test a réussi et que le test a échoué.

Lorsque vous écrivez vos cas de test pour la première fois, vous pouvez rencontrer des situations comme celle-ci.

En supposant que votre scénario de test est correct, vous identifierez les bogues dans le code et vous demanderez aux développeurs respectifs de résoudre le problème et de retester.

Si cette erreur se produit lors d’un test de régression, ce bogue est introduit en raison du nouveau développement logiciel effectué au-dessus de la base de code existante.

Cela montre qu’il y a un problème avec la nouvelle base de code qui doit être corrigé pour s’assurer que l’ancienne fonctionnalité fonctionne. Encore une fois, les développeurs doivent s’en occuper.

Que diriez-vous d’avoir de nombreux cas de test? Disons que nous avons TestCase1 et TestCase2, chacun ayant plusieurs tests.

Vous pouvez créer ce qu’on appelle une suite de tests et l’exécuter à l’aide d’un coureur de tests comme suit:

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestCase1))
suite.addTest(unittest.makeSuite(TestCase2))
runner = unittest.TextTestRunner()
runner.run(suite)

Le code ci-dessus exécutera tous les tests dans TestCase1 puis dans TestCase2.

C’est tout pour aujourd’hui. J’espère que ça aide.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.