
Bonjour, chers lecteurs. Je m'appelle Victor Burov. Je travaille en tant que développeur chez ISPsystem et souhaite partager mon expérience dans l'automatisation des tests.
Il se trouve que les tests manuels ont prévalu dans notre pays, et les testeurs ont passé beaucoup de temps à effectuer les mêmes actions. Une fois que nous avons pensé: pourquoi ne pas apprendre au panel à répéter les actions du testeur, car, en fait, elles se transforment toutes en appels API spécifiques. Cela permettrait aux gens d'écrire des tests même sans compétences en programmation.
Nous avons décidé d'écrire un module pour créer des tests automatiques. Pour que le testeur puisse simplement appuyer sur le bouton pour créer un test, remplir les conditions du cas de test, à la fin, cliquez sur "Terminer" - et c'est tout, le test était prêt! Une idée simple, mais réaliser que ce n'était pas facile. Parce que nous voulions que ce module soit adapté au maximum à nos produits et profite d'une interface unifiée: pour que la vidéo enregistrée ressemble à un cas de test prêt à l'emploi. Cela éliminerait complètement le travail manuel d'écriture des tests. Le système résultant a été appelé «magnétophone».
Interface pour visualiser les conditions des cas de testPrincipe de fonctionnement
Tous les paramètres de demande (en-têtes HTTP, variables d'environnement, données POST, le cas échéant) et la réponse entière sont écrits dans le fichier xml. Chaque enregistrement se voit attribuer un numéro de série. Toutes les demandes sont divisées en modifications et non-modifications. Après l'enregistrement du test, de nombreuses requêtes non modificatrices sont supprimées, car elles n'affectent pas l'exécution des tests et ne font que retarder et confondre le processus d'exécution (d'où les numéros de séquence manquants dans la capture d'écran).
Pendant l'enregistrement, le magnétophone vous permet de régler la vérification des valeurs dans les champs des formulaires et dans les colonnes des listes en un clic. Il vous permet également d'enregistrer des tests négatifs, en se souvenant de l'erreur que le panneau a renvoyée lors de l'enregistrement d'un test.
Pendant la lecture, les demandes sont envoyées directement à l'API de l'application sans utiliser de navigateur.
En fait, un magnétophone est un module qui s'intègre à tous nos produits et vous permet d'installer des processeurs sensibles aux événements. Écrit à l'aide de COREmanager.
Un exemple d'enregistrement d'un appel effectué par un magnétophone:
Record<params> <param name="CONTENT_LENGTH">210</param> <param name="CONTENT_TYPE">application%2Fx%2Dwww%2Dform%2Durlencoded%3B%20charset%3DUTF%2D8</param> <param name="HTTPS">on</param> <param name="HTTP_ACCEPT">text%2Fhtml%2C%20%2A%2F%2A%3B%20q%3D0%2E01</param> <param name="HTTP_ACCEPT_LANGUAGE">en%2DUS%2Cen%3Bq%3D0%2E5</param> <param name="HTTP_CACHE_CONTROL">no%2Dcache</param> <param name="HTTP_CONNECTION">keep%2Dalive</param> <param name="HTTP_COOKIE">corelang5%3Dorion%3Aru%3B%20ispmgrlang5%3Dorion%3Aru%3B%20ipmgrlang5%3Dorion%3Aru%3B%20ipmgrses5%3Dbdd69179d627%3B%20ispmgrses5%3D14157f7bbc5e%3B%20menupane%3D30%5Faccount%2D1%253A30%5Fdomains%2D1%253A30%5Fwebserver%2D1%253A30%5Fantispam%2D1%253A30%5Fmaintain%2D1%253A30%5Ftool%2D1%253A30%5Fstat%2D1%253A30%5Fsrvset%2D1%253A30%5Fsysstat%2D1%253A30%5Fintegration%2D1%253A30%5Fset%2D1%253A30%5Fmgrhelp%2D1</param> <param name="HTTP_HOST">172%2E31%2E240%2E175%3A1500</param> <param name="HTTP_ISP_CLIENT">Web%2Dinterface</param> <param name="HTTP_PRAGMA">no%2Dcache</param> <param name="HTTP_REFERER">https%3A%2F%2F172%2E31%2E240%2E175%3A1500%2Fispmgr</param> <param name="HTTP_USER_AGENT">Mozilla%2F5%2E0%20%28X11%3B%20Ubuntu%3B%20Linux%20x86%5F64%3B%20rv%3A24%2E0%29%20Gecko%2F20100101%20Firefox%2F24%2E0</param> <param name="HTTP_X_REQUESTED_WITH">XMLHttpRequest</param> <param name="QUERY_STRING"/> <param name="REMOTE_ADDR"></param> <param name="REMOTE_PORT">38640</param> <param name="REQUEST_METHOD">POST</param> <param name="REQUEST_URI">%2Fispmgr</param> <param name="SCRIPT_NAME">%2Fispmgr</param> <param name="SERVER_ADDR">172%2E31%2E240%2E175</param> <param name="SERVER_NAME">172%2E31%2E240%2E175</param> <param name="SERVER_PORT">1500</param> </params> <postdata>func%3Demaildomain%2Eedit%26elid%3D%26name%3Dtest%2Eemail%26owner%3Dusr%26ipsrc%3Dauto%26defaction%3Derror%26redirval%3D%26spamassassin%3Doff%26avcheck%3Doff%26clicked%5Fbutton%3Dok%26progressid%3Dfalse%5F1424243906672%26sok%3Dok%26sfrom%3Dajax%26operafake%3D1424243906673</postdata> <answer> <doc lang="ru" func="emaildomain.edit" binary="/ispmgr" host="https://172.31.240.175:1500" features="cba82687e7756e2c0195c88d4180f5d50" notify="0" theme="/manimg/orion/" css="main.css" logo="logo-ispmgr.png" logolink="" favicon="favicon-ispmgr.ico" localdir="default/"> <metadata name="emaildomain.edit" type="form" mgr="ispmgr" decorated="yes"> <form> <field name="name"> <input type="text" name="name" required="yes" check="domain" convert="punycode" maxlength="255"/> </field> // <buttons> <button name="ok" type="ok"/> <button name="cancel" type="cancel"/> </buttons> </form> </metadata> <messages name="emaildomain.edit" checked="cba82687e7756e2c0195c88d4180f5d5"> <msg name="currentmonth"> </msg> // </messages> <doc lang="ru" func="emaildomain.edit" binary="/ispmgr" host="https://172.31.240.175:1500" features="cba82687e7756e2c0195c88d4180f5d50" notify="0" theme="/manimg/orion/" css="main.css" logo="logo-ispmgr.png" logolink="" favicon="favicon-ispmgr.ico" localdir="default/"> <slist name="owner"> <val key="usr">usr</val> </slist> <slist name="defaction"> <val msg="yes" key="error"> </val> </slist> <slist name="ipsrc"> <val msg="yes" key="auto"> </val> </slist> <name/> <avcheck>off</avcheck> <owner>usr</owner> <ipsrc>auto</ipsrc> </doc> <id>test.email</id> <ok/> <tparams> <clicked_button>ok</clicked_button> </tparams> </doc> </answer> <localmacro> <macros name="mpre_HostIP" field="ipsrc">auto</macros> </localmacro>
Améliorations (auxquelles nous n'avons pas pensé à l'avance)
En attente
Une personne peut "simplement attendre", un ordinateur - non. L'un des premiers problèmes que le magnétophone était censé résoudre était l'écriture des cuves. Ce que le peuple n'a pas inventé pour attendre la fin de l'opération. L'attente des tâches en arrière-plan et la possibilité d'ajouter un arrêt à l'étape spécifiée pendant un nombre de secondes spécifié ont été implémentées.
Enregistrement et modification des étapes de test
Probablement, tout le monde se souvient de l'époque des machines à écrire: une erreur - et vous devez réimprimer la page entière.

Pour que le testeur n'ait pas à réécrire tout le test avec une action erronée, un mécanisme a été ajouté pour réenregistrer le test à n'importe quelle étape après la sauvegarde. La possibilité de modifier est pratique lorsque vous devez adapter le test aux changements de comportement des fonctions testées.
Macros pour les variables
Lors des tests, les valeurs des paramètres transmis et vérifiés ont changé en fonction du serveur sur lequel ils s'exécutaient. Un exemple de telles données est les adresses IP. Il est impossible de les reconnaître au stade de l'enregistrement du test, j'ai donc ajouté un système de macro. Cela nous a permis de créer des tests qui ne sont pas si étroitement liés à l'environnement. L'inconvénient de la solution est qu'après l'enregistrement, les macros doivent être spécifiées manuellement.
Un autre problème qui complique considérablement le travail avec le magnétophone est l'utilisation de clés non natives. Nous ne l'avons pas remarqué tout de suite, car nous avons testé le magnétophone sur ISPmanager, qui utilise des identifiants natifs. Mais dans certains autres panneaux, l'enregistrement est identifié par un identifiant unique. Par conséquent, j'ai dû apprendre au magnétophone non seulement à obtenir l'identifiant après avoir créé l'enregistrement ou l'objet (car l'ID peut changer de début en début), mais aussi à le remplacer dans toutes les demandes suivantes.
Prise en charge du format JUnit
Les tests générés sur bande s'exécutent automatiquement dans l'environnement d'intégration continue Jenkins. Une fois les tests terminés, un fichier xml est créé contenant les données au format JUnit. Pour que le fichier soit correctement formé, une restriction sur la dénomination des tests a été introduite. Par exemple, le test User.Create.xml est tombé dans la suite de tests avec le nom User et, par conséquent, il avait un cas de test appelé Create. En cas d'erreur, un nœud d'échec avec une description complète de l'erreur lui a été ajouté.
Mesures
Le nombre de fonctions appelées uniques est calculé lors du passage des tests et le ratio est déterminé en pourcentage du nombre total de fonctions, à l'exclusion de celles disponibles uniquement pour un usage interne. Ainsi, la couverture de test la plus simple est mesurée. De plus, les mesures indiquent le temps total nécessaire pour terminer le test et le nombre de tests réussis et ayant échoué.
Référentiel de test
Le référentiel de tests résout tout d'abord le problème du transfert de tests prêts à l'emploi vers d'autres serveurs. Il est également utile lorsque plusieurs testeurs écrivent des tests. Un petit panneau pour stocker les tests de stockage a été développé et déployé également sur la base de notre COREmanager. Le magnétophone possède un module pour synchroniser les tests avec le stockage. Lors de l'écriture d'un nouveau test ou du déchargement des tests du référentiel, ils deviennent automatiquement indisponibles pour le chargement dans le référentiel afin qu'il n'y ait pas de confusion. Après avoir modifié le test, le numéro de révision est augmenté afin que seuls les tests après les modifications soient chargés dans le référentiel.
Difficultés (enfin, où sans elles)
L'utilisation d'un magnétophone a montré que toutes les fonctions de l'API ne suivaient pas nos recommandations internes. En particulier, toutes les fonctions n'ont pas retourné l'identifiant d'enregistrement après sa création. J'ai dû revenir, y compris à un code de travail, et le mettre en conformité avec les exigences.
L'impasse est un autre problème. Le panneau implique la réalisation de certaines actions critiques en mode exclusif. Et le magnétophone, faisant partie du même panneau, provoquant de telles fonctions, a provoqué le gel de l'ensemble du système. Il n'a été possible de le déterminer qu'avec l'aide de GDB (personne ne se souvenait de cette fonctionnalité). Malheureusement, il y avait des béquilles, car il a été décidé lors de l'exécution des tests du magnétophone d'effectuer ces fonctions en mode multi-thread. Théoriquement, il était possible de concevoir un magnétophone non pas avec un module, mais avec un panneau séparé. Mais nous n'avons pas essayé.
Malheureusement, l'écriture et l'oubli ont également échoué. L'interface de nos produits évolue et se complique. De plus, le nombre de composants d'interface est en pleine croissance. Par conséquent, le magnétophone doit être modifié de temps en temps, afin que lorsque de nouveaux composants apparaissent, il puisse analyser leur structure et traiter les résultats des requêtes.
Conclusion
La création d'un magnétophone a permis d'améliorer la qualité des produits testés. Gain de temps et de ressources pour la formation des testeurs. En cours de route, le magnétophone nous a permis de vérifier la conformité de notre API avec les recommandations internes et, par conséquent, de rendre l'API un peu plus «logique».