Pourquoi pour le nouveau projet, j'ai pris Robot Framework

Récemment, j'ai changé de projet - je suis arrivé à un nouveau développement, où avant moi, il n'y avait aucun test, manuel ou automatique. Le client n'a pas imposé de conditions sur la boîte à outils (sauf qu'il s'agissait de Python), j'ai donc fait mon propre choix. Dans cet article, je vais expliquer pourquoi dans de telles conditions j'ai choisi Robot Framework. Et à la fin, il y aura quelques exemples spécialement écrits pour l'article qui illustrent ce dont nous parlons.

image

Je fais de l'automatisation des tests depuis plus de 10 ans, et environ trois d'entre eux ont interagi avec le Framework Robot.

Comme je l'ai noté ci-dessus, il n'y a pas si longtemps, je suis arrivé à un nouveau projet, où j'ai commencé à tester l'automatisation à partir de zéro. Je ne peux pas vous parler du projet - NDA. Je note seulement qu'il s'agit d'un outil d'automatisation sympa, qui devrait à l'avenir économiser beaucoup de ressources humaines. Il est construit à partir de microservices. Jusqu'à présent, mon travail concerne quatre d'entre eux, mais à l'avenir, j'étendrai mes activités à d'autres - tout se résume au fait que je n'ai que 8 heures de travail par jour. Tout prend du temps.

Le manque de tests dans le cas de ce projet était identique au manque d'outils recommandés. Dans le cadre de la pile Python, j'avais la liberté de choix. Et j'en ai profité.

Pourquoi Robot Framework?


Je pense que je peux être attribué aux fans du Robot Framework. Il me semble que presque tout peut y être fait.

Sur d'autres projets, l'entreprise utilise pytest. Cependant, à mon avis, il n'a pas de telles capacités, car il est limité par les capacités de Python. Vous écrivez simplement du code Python et notez que vous attendez une certaine valeur dans une telle variable. À mon goût, c'est simple mais trop abstrait. Beaucoup a été laissé à la merci du développeur, qui devra ajouter toutes les fonctionnalités utiles à la main. Robot Framework le fait lui-même. Voici quatre points qui méritent d'être pris en compte dans votre projet.

Flexibilité


Le Robot Framework lui-même est écrit en Python (c'est-à-dire qu'il peut faire tout ce que Python peut faire), et pour cela il existe de nombreuses bibliothèques créées par la communauté, ce qui élargit considérablement la gamme des problèmes à résoudre.

Sous Robot Framework, vous pouvez facilement écrire vos propres bibliothèques, en l'intégrant à presque tout, et tout fonctionnera immédiatement. Aucune béquille ou vélo n'est requis.
De plus, le Robot Framework vous permet d'écrire des tests paramétriques (modèles), ce qui accélère considérablement le travail de l'outil d'automatisation.

Langue russe dans les tests


L'un des points fondamentaux est que le mot-clé (analogues des méthodes conventionnelles dans le Robot Framework, qui est historiquement appelé pour une raison quelconque) peut être écrit en russe. En conséquence, les textes de test sont, bien sûr, loin de la langue littéraire, mais à première vue, il devient clair ce qui s'y passe. Tout d'abord, cela n'est pas nécessaire aux développeurs finaux, mais, par exemple, aux parties prenantes. Ils peuvent ouvrir les tests indépendamment et voir ce qui s'y passe exactement: "Sélectionnez un élément aléatoire dans ...", etc.

Marquage


Robot Framework fonctionne bien avec les balises. Vous pouvez non seulement exécuter des tests avec une balise spécifique, mais également analyser des rapports avec leur aide. Le fichier journal contient des statistiques sur les balises, sur la base desquelles vous pouvez prendre des mesures si vous pensez à l'avance à la disposition des balises.

De manière pratique, vous n'avez pas besoin d'écrire toutes les balises dans un long footcloth dans chaque test, mais vous pouvez intégrer des tests dans une arborescence. Dans mon cas, cela ressemble à ceci: le premier niveau est un microservice, le second est le type de test, le troisième est les tests eux-mêmes (il est pratique de mettre un fichier init contenant des balises pour ce qui est incorporé à l'intérieur).

J'ai créé un tag pour chaque microservice, chaque approche de test (tests de fumée, tests CRUD, intégration, etc.). Je peux exécuter des tests d'un type spécifique ou uniquement pour un service spécifique. Je marque également le type de fonction - liste ou détaillée. Et si le produit responsable des fonctions de liste "casse" dans le produit, tous les tests avec cette balise deviendront rouges, indépendamment de l'endroit où ils se trouvent et de ce à quoi ils se rapportent.

Par des balises, je lie les autotests à Jira. Lorsque le bug du tracker se ferme et que le test du rouge devient vert, nous avons toujours un historique de ce qui a exactement changé. Plusieurs mois plus tard, si le test redevient rouge, nous pouvons voir quelles mesures ont été prises pour résoudre le problème la dernière fois, et même supposer que cela a conduit à la lecture répétée du bogue.

Une autre balise spéciale que j'ai ajoutée pour les bogues non critiques. GitLab ne nous permet pas de faire quoi que ce soit avec l'assembly si au moins un test se bloque. C'est logique - jusqu'à ce que tous les bugs soient corrigés, nous ne pouvons pas publier un produit ou même un sprint hebdomadaire. Mais nous avons des bogues de faible priorité et insignifiants. Pour eux, j'ai sélectionné une balise qui permet à Robot Framework de ne pas supprimer l'ensemble complet, sauf si ces tests (tests avec cette balise) échouent spécifiquement.

Grand journal


L'analyse des journaux fait partie intégrante des tests. Quoi qu'il arrive au moment où les tests sont exécutés, le Robot Framework écrit absolument tout. Jusqu'à ce que je devais écrire un wrapper spécial qui cache le login et le mot de passe du journal pour se connecter à la base de données.

De tels détails aident à comprendre beaucoup plus rapidement quelle est la raison de l'échec du test - le système testé fonctionne-t-il incorrectement ou quelque chose n'est-il pas pris en compte dans le test et doit être corrigé? La réponse à cette question n'est pas toujours évidente. Les erreurs des développeurs et des testeurs sont réparties 50/50.
Dans d'autres outils - dans le même pytest - vous pouvez créer le même journal détaillé. Mais la tâche de le générer incombe au développeur qui écrit les tests. Il doit réfléchir au type d'entrées de journal réellement nécessaires.

Quel est le projet en ce moment


Depuis le moment où j'ai commencé à utiliser Robot Framework, plusieurs mois se sont écoulés. À l'heure actuelle, le Robot Framework a mis en œuvre plus de 200 tests et, comme mentionné ci-dessus, il existe une intégration avec GitLab, qui permet de vérifier les modifications apportées au produit développé (les cas de test avec des identifiants qui vous permettent de lier des autotests à eux sont stockés dans testrail).

Pour calculer la couverture, j'ai écrit un utilitaire qui prend une liste d'API backend de Swagger et la compare avec ce qui a été testé. Ainsi, nous avons une compréhension claire de la couverture actuelle. Par exemple, nous savons qu'aujourd'hui ce microservice est couvert dans son intégralité, tandis que l'autre est couvert à 98%. Et après avoir ajouté de nouvelles fonctionnalités qui ne se reflètent pas encore dans les tests, la couverture diminue. En conséquence, vous pouvez planifier pour moi le prochain sprint.

Naturellement, le projet se développe encore. Par exemple, nous déployons maintenant un faux serveur ( mon collègue a déjà écrit sur Habré sur ce que c'est et pourquoi il est nécessaire).

Maintenant pour pratiquer


Les exemples ci-dessus sont conçus spécifiquement pour l'article afin d'illustrer les idées ci-dessus. Si vous souhaitez expérimenter vous-même ces exemples, ils sont tous publiés dans notre référentiel .

L'exemple de test le plus simple


Commençons par le test le plus simple sur Robot Framework.

Dans l'exemple ci-dessous, une session est d'abord créée vers une certaine ressource évidemment accessible (dans notre cas, en.wikipedia.org/wiki ). En appelant Get root (/), nous vérifions le code d'état 200.

*** Settings *** Documentation  smoke-. Library RequestsLibrary *** Variables *** ${base_url} https://en.wikipedia.org/wiki ${url} / *** Test Cases ***   Wiki Create session conn ${base_url} disable_warnings=1 ${response} Get request conn ${url} Delete all sessions Should be equal ${response.status_code} ${200} 

Tests de modèle (paramétriques)


Robot Framework vous permet de créer des modèles de test. Si nous transférons le test de l'exemple précédent vers la vue du modèle, nous pouvons facilement le mettre à l'échelle en ajoutant des appels avec les arguments nécessaires. Par exemple, vérifions la réponse 200 pour les pages avec des biographies de scientifiques.

 *** Settings *** Documentation  smoke-.    . ...    . Library RequestsLibrary Test Setup   Test Teardown    Test Template Smoke- *** Variables *** ${base_url} https://en.wikipedia.org/wiki *** Test Cases ***      /Isaac_Newton      /Albert_Einstein      /Stephen_Hawking *** Keywords ***   Create session conn ${base_url} disable_warnings=1    Delete all sessions Smoke- [Arguments] ${url} ${response} Get request conn ${url} Should be equal ${response.status_code} ${200} 

Marquage et lecture des journaux


Nous continuons d'améliorer le test le plus simple.

Ayant un modèle comme point d'entrée unique, nous pouvons facilement ajouter une vérification de l'année de naissance du scientifique. De cette façon, nous confirmons que la page chargée affiche les données correctes.

De plus, dans l'exemple ci-dessous, j'ai enveloppé le mot-clé existant dans des noms russes - à mon goût, donc le test se lit de manière plus organique. En tant que testeur, j'ai toujours été ennuyé par des méthodes appelées «comme si en anglais», mais complètement analphabète. Il vaut toujours mieux écrire dans la langue que vous connaissez.

 *** Settings *** Documentation  smoke-.    . ...    . ...      . ...  . Library RequestsLibrary Test Setup   Test Teardown    Test Template Smoke- *** Variables *** ${base_url} https://en.wikipedia.org/wiki *** Test Cases ***      [Tags] Newton /Isaac_Newton 1642      [Tags] Einstein /Albert_Einstein 1879      [Tags] Hawking /Stephen_Hawking 1942     (  ) [Tags] Numbers /123456789 1899 *** Keywords ***   Create session conn ${base_url} disable_warnings=1    Delete all sessions Smoke- [Arguments] ${url} ${expected_word} ${response} Get request conn ${url} Should be equal ${response.status_code} ${200} ... msg=  GET ${url}    ,   200 .      ${response.text} ${expected_word}      [Arguments] ${text} ${expected_word} Should contain ${text} ${expected_word} msg=    ${expected_word}! 

Faites attention aux [Tags] . Vous pouvez ajouter des balises ici, qui, comme je l'ai écrit ci-dessus, aideront à évaluer les problèmes au niveau du rapport. De même, Force Tags dans le fichier __init __. Robot (voir l'exemple dans notre référentiel ) vous permet de définir des balises pour tous les tests du répertoire, y compris ceux imbriqués. Si le balisage est effectué correctement, sans même lire les noms des tests eux-mêmes et sans explorer leur logique, nous pouvons supposer assez précisément qu'il ne fonctionne pas dans le projet de test.

Regardez le rapport sur le lancement de ces tests. Pour plus de clarté, j'ai ajouté un test qui trouvera une erreur.

Les statistiques des rapports sont sa partie la plus importante.

image

Dans notre exemple, les tests avec la balise numbers n'ont pas réussi complètement (nous en avons 1 sur 1, mais dans la vie réelle, il y en aura, par exemple, 17 sur 20). On peut supposer que le problème est dans cette page.

Les balises permettent d'exécuter des tests de manière sélective. Pour exécuter tous les tests avec une balise spécifique dans la ligne de lancement, vous devez spécifier:

 --include <tag> 

Même les opérations logiques avec balises sont prises en charge:

 -- include <tag>AND<tag> 

Par exemple, si vous souhaitez exécuter uniquement le test de fumée pour les tests avec la balise numérique, vous devez ajouter:

 --include smokeANDnumbers 

Tests non critiques


Passons à des astuces qui simplifient considérablement le travail.

Après avoir marqué le test avec des balises, vous pouvez définir un ou plusieurs d'entre eux comme «non critique». Un test avec une telle balise affichera toujours des erreurs (le cas échéant), mais à la fin, ces erreurs ne seront pas interprétées comme "non valides". J'utilise cette option lorsque certains bugs mineurs ont été pris en compte, saisis dans le bug tracker, mais n'ont pas encore été corrigés. Sans cela, les autotests inclus dans CI, lors de la détection de tels problèmes connus, ne vous permettront pas d'assembler le projet, ce qui n'est pas toujours pratique.

Ajoutez un nouveau test:

     (   ) [Tags] Letters Known /abcdefghi 1799 

Au démarrage, la balise ajoutée est définie comme «non critique» à l'aide de la clé:

 --noncritical Known 

Mot-clé en python


Avec l'exemple suivant, je vais illustrer comment ajouter ma bibliothèque.

Créez un nouveau mot-clé «Générer un tableau de nombres». Son but est évident (pour cela, j'aime les noms russes).

 from random import randint from typing import List from robot.api.deco import keyword class ArrayGeneratorLibrary: ROBOT_LIBRARY_SCOPE = 'GLOBAL' @keyword("  ") def generate_array(self, length: int, minimal: int, maximal: int) -> List[int]: result = [] for i in range(int(length)): result.append(randint(int(minimal), int(maximal))) return result 

Nous connectons la bibliothèque dans le test:

 Library libraries.ArrayGeneratorLibrary 

et l'utiliser:

   ,   python. ${array}    ${5} ${2} ${8} Log to console ${array} 

N'oubliez pas que si vous avez une structure imbriquée, vous devez la séparer par des points, comme dans l'exemple.
Autre astuce: les nombres passés dans ${} sont traités comme des int, pas comme des chaînes!

Arguments en ligne


Une autre bonne chose est les arguments intégrés, qui sont passés non pas à la fin de l'appel, comme d'habitude, mais directement dans son corps.

Pour illustrer, nous allons écrire un wrapper pour le générateur de tableau créé ci-dessus, qui permet d'utiliser les arguments intégrés:

  ${n} ,  ${from}  ${to} ${result}    ${n} ${from} ${to} [Return] ${result} 

Vous pouvez maintenant écrire comme ceci:

       . ${array}  5 ,  2  8 Log to console ${array} 

Substitution d'une partie du nom de la méthode, insert et boucles python


La prochaine astuce que j'aime vraiment à propos du Robot Framework est la substitution d'une partie du nom. Supposons que nous ayons deux méthodes: l'une sélectionne des nombres pairs, l'autre impaire.

      [Arguments] ${list} ${evens} Evaluate [i for i in $list if i % 2 == 0] [Return] ${evens}      [Arguments] ${list} ${odds} Evaluate [i for i in $list if i % 2 != 0] [Return] ${odds} 

Le mot-clé Evaluate utilisé ci-dessus vous permet d'exécuter une ligne de code python «ici». Veuillez noter que si vous ne voulez pas remplacer un morceau de la chaîne par le contenu de la variable, c'est-à-dire lui passer un lien, vous devez indiquer le nom de la variable immédiatement après le signe $ sans accolades!

Et donc, vous pouvez appeler les deux méthodes, en remplaçant les différentes parties de leur nom:

     ,   . . ${types} Create list   ${array}  5 ,  12  28 FOR ${type} IN @{types} ${numbers} Run keyword  ${type}    ${array} log to console ${numbers} END 

Décorateurs de méthode


Oui, Robot Framework vous permet d'écrire un décorateur pour d'autres mots clés!

Pour illustrer cette fonctionnalité, nous écrivons un décorateur qui sélectionne les nombres négatifs dans la réponse de toute méthode qui renvoie une liste.

     ,  [Arguments] ${keyword} @{args} &{kwargs} ${list} Run keyword ${keyword} @{args} &{kwargs} ${negs} Evaluate [i for i in $list if i < 0] [Return] ${negs} 

Veuillez noter:
@{args} sont tous des arguments sans nom;
&{kwargs} sont tous des arguments nommés.
Ayant ce groupe, vous pouvez les rediriger, créant en fait un décorateur.
Travailler avec le décorateur ressemblera à ceci:

    ${negs}     ,     10 -5 5 log to console ${negs} 

Au lieu d'une conclusion


Dans les exemples ci-dessus, j'ai montré les principales fonctionnalités de Robot Framework, qui facilitent la vie. Mais ses jetons ne se limitent pas à cette liste.

Si vous avez des questions, écrivez dans les commentaires. Nous allons identifier la direction principale de la lecture et répondre aux questions en continuant le texte.

L'auteur de l'article: Vladimir Vasyaev.

PS Nous publions nos articles sur plusieurs sites du Runet. Abonnez-vous à nos pages sur les chaînes VK , FB ou Telegram pour découvrir toutes nos publications et autres actualités Maxilect.

Source: https://habr.com/ru/post/fr470924/


All Articles