Salut, Habr !
Je m'appelle Maksim Ponomarenko et je suis développeur chez Sportmaster. J'ai dix ans d'expérience dans le secteur des TI. J'ai commencé ma carrière dans le domaine des tests manuels, puis j'ai évolué vers le développement de bases de données. Au cours des quatre dernières années, en accumulant les connaissances acquises en test et en développement, je me consacre à l'automatisation des tests au niveau de la SGBD.
Je fais partie de l'équipe de Sportmaster depuis un peu plus d'un an et sur l'un des grands projets, je travaille au développement de tests automatisés. En avril, mon équipe de Sportmaster Lab a présenté à une conférence à Krasnodar, ma présentation s'intitulait «Tests unitaires dans les SGBD», et maintenant je souhaite la partager avec vous. Il y aura beaucoup de texte, donc j'ai décidé de diviser la présentation en deux articles. Dans le premier, nous parlerons des autotests et des tests en général, et dans le second, je détaillerai notre système de tests unitaires et les résultats de son application.
Commençons par un peu de théorie ennuyeuse. Qu'est-ce que le test automatisé ? C'est un test effectué par des moyens logiciels, et dans le secteur moderne des TI, il est de plus en plus utilisé lors du développement de logiciels. Cela est lié au fait que les entreprises grandissent, leurs systèmes d'information se développent et par conséquent, le nombre de fonctionnalités à tester augmente également. Il devient de plus en plus coûteux d'effectuer des tests manuels.
J'ai travaillé dans une grande entreprise dont les versions sortent tous les deux mois. Dans ce cas, un mois entier était consacré à la vérification des fonctionnalités par une dizaine de testeurs manuellement. Grâce à l'implémentation de l'automatisation par une petite équipe de développeurs, nous avons réussi à réduire le temps de test à deux semaines en un an et demi. Nous avons non seulement augmenté la vitesse de test, mais également amélioré sa qualité. Les tests automatisés sont exécutés régulièrement et ils effectuent toujours l'intégralité des contrôles qu'ils contiennent, c'est-à-dire que nous excluons le facteur humain.
Dans l'IT moderne, il est courant que le développeur soit également amené à écrire non seulement le code du produit, mais aussi les tests unitaires qui vérifient ce code.
Mais que faire si votre système est principalement basé sur la logique serveur ? Il n'existe pas de solution universelle ni de bonnes pratiques sur le marché. En général, les entreprises résolvent ce problème en créant leur propre système de test sur mesure. C'est un système de test automatisé sur mesure qui a été créé pour notre projet, et j'en parlerai dans ma présentation.

Testons la fidélité
Pour commencer, parlons du projet où nous avons déployé le système de test automatisé. Notre projet est le système de fidélité de Sportmaster (d'ailleurs, nous en avons déjà parlé dans ).
Si votre entreprise est suffisamment grande, votre système de fidélité aura trois caractéristiques standards :
- Votre système sera très sollicité
- Votre système contiendra des processus de calcul complexes
- Votre système sera activement amélioré.
Allons-y dans l'ordre… Au total, si l'on considère toutes les marques de Sportmaster, nous avons plus de 1000 magasins sur le territoire de la Russie, de l'Ukraine, de la Chine, du Kazakhstan et de la Biélorussie. Dans ces magasins, environ 300 000 achats sont effectués quotidiennement. Cela signifie qu'une à quatre transactions entrent dans notre système chaque seconde. Par conséquent, notre système de fidélité est fortement sollicité. Et comme il est utilisé activement, nous devons offrir les normes de qualité les plus élevées, car toute erreur dans le logiciel entraîne de grandes pertes financières, réputationnelles et autres.
En même temps, plus d'une centaine de promotions différentes sont en cours chez Sportmaster. Les promotions sont diverses : il y a des promotions sur les produits, des promotions liées aux jours de la semaine, des promotions spécifiques à certains magasins, des promotions basées sur le montant du ticket et sur le nombre de produits. En résumé, ce n'est pas trivial. Les clients disposent de bonus et de codes promo utilisés lors des achats. Tout cela fait que le calcul de toute commande est une tâche plutôt complexe.
L'algorithme qui implémente le traitement des commandes est vraiment horrible et complexe. Toute modification de cet algorithme est assez risquée. Même les modifications qui semblent insignifiantes peuvent entraîner des effets assez imprévisibles. Ces processus de calcul complexes, surtout lorsqu'ils mettent en œuvre des fonctionnalités critiques, sont les meilleurs candidats à l'automatisation. Vérifier manuellement des dizaines de cas identiques représente une charge de travail considérable. Étant donné que le point d'entrée dans le processus reste inchangé, une fois que nous l'avons décrit, nous pouvons rapidement générer des tests automatisés et être certains du bon fonctionnement de la fonctionnalité.
Comme notre système est utilisé activement, les entreprises s'attendront à ce que vous leur apportiez quelque chose de nouveau, à évoluer avec le temps et à être orienté client. Dans notre système de fidélité, des mises à jour sortent tous les deux mois. Cela signifie que tous les deux mois, nous devons effectuer un test de régression complet de tout le système. De plus, comme dans toute entreprise informatique moderne, le développement ne passe pas directement du développeur à la production. Il naît sur l'environnement du développeur, puis traverse successivement l'environnement de test, l'environnement de mise en production, l'acceptation, et ce n'est qu'ensuite qu'il se retrouve en production. Au minimum, nous devons effectuer un test de régression complet sur les environnements de test et de mise en production.
Les propriétés décrites sont standard pour pratiquement tout système de fidélité. Parlons des particularités de notre projet.
Techniquement, 90 % de la logique de notre système de fidélité est côté serveur et est implémentée sur Oracle. Il existe un client sur Delphi qui remplit la fonction d'administrateur APM. Il existe des services web pour des applications externes (comme un site web). Il est donc tout à fait logique que si nous déployons un système de test automatisé, nous le fassions sur Oracle.
Le système de fidélité chez Sportmaster existe depuis plus de 7 ans et a été développé par des développeurs uniques... Le nombre moyen de développeurs sur notre projet au cours de ces 7 années était de 3 à 4 personnes. Mais au cours de la dernière année, notre équipe a considérablement augmenté, et maintenant 10 personnes travaillent sur le projet. Cela signifie que des personnes arrivent sur le projet qui ne sont pas familières avec les tâches, les processus et l'architecture classiques. Il y a un risque accru que nous passons à côté d'erreurs.
Le projet se caractérise par l'absence de testeurs dédiés en tant qu'unités à temps plein. Il y a bien des tests, mais ce sont les analystes qui s'en charge, en plus de leurs autres responsabilités : en communiquant avec les clients, les utilisateurs, en élaborant les exigences du système, etc. Malgré le fait que les tests soient réalisés de manière très qualitative (surtout pertinent à mentionner car l'un des analystes peut lire ce rapport), l'efficacité de la spécialisation et de la concentration sur un seul élément n'est pas à négliger.
Compte tenu de tout ce qui précède, pour améliorer la qualité du produit livré et réduire les délais de développement, l'idée d'automatisation des tests dans le projet semble tout à fait logique. À différentes étapes de l'existence du système de fidélité, certains développeurs ont tenté de couvrir leur code par des tests unitaires. Cela a en général été un processus assez éclaté, où chacun utilisait sa propre architecture et ses méthodes. Les résultats finaux des tests unitaires étaient communs : les tests étaient développés, utilisés pendant un certain temps, stockés dans un dépôt de fichiers versionné, mais à un moment donné, ils n'étaient plus exécutés et ont été oubliés. Cela se produisait principalement parce que les tests étaient davantage liés à un exécuteur spécifique qu'au projet.
utPLSQL vient à la rescousse.

Savez-vous quelque chose sur Steven Feuerstein ?
C'est un homme brillant qui a consacré une grande partie de sa carrière à travailler avec Oracle et PL/SQL, et a écrit un nombre considérable d'ouvrages sur le sujet. L'un de ses livres les plus connus s'intitule : « Oracle PL/SQL. Pour les professionnels ». C'est à Stephen que l'on doit le développement de la solution utPLSQL, ou, comme son nom l'indique, le cadre de test unitaire pour Oracle PL/SQL. La solution utPLSQL a été créée en 2016, mais elle continue d'être activement développée et de nouvelles versions sont régulièrement publiées. Au moment de la présentation, la dernière version date du 24 mars 2019.
Qu'est-ce que c'est donc ? C'est un projet open source distinct. Il pèse quelques mégaoctets, y compris des exemples et de la documentation. Il représente physiquement un schéma séparé dans la base de données ORACLE avec un ensemble de paquets et de tables pour organiser les tests unitaires. L'installation ne prend que quelques secondes. La simplicité d'exploitation est l'une des caractéristiques distinctives d'utPLSQL.
Globalement, utPLSQL constitue un mécanisme pour exécuter des tests unitaires, où un test unitaire désigne des procédures de paquet Oracle ordinaires, dont l'organisation respecte certaines règles. En plus de l'exécution, utPLSQL conserve un journal de tous vos lancements de tests, ainsi qu'un système de reporting interne.
Regardons un exemple pour voir à quoi ressemble le code d'un test unitaire, implémenté selon cette méthodologie.

Ainsi, à l'écran apparaît le code d'une spécification typique de paquet avec des tests unitaires. Quelles sont les exigences obligatoires ? Le paquet doit avoir le préfixe « utp_ ». Toutes les procédures de test doivent avoir le même préfixe. Le paquet doit impérativement inclure deux procédures standard : « utp_setup » et « utp_teardown ». La première procédure est appelée avant chaque test unitaire, la seconde après son exécution.
« utp_setup » prépare généralement notre système pour l'exécution du test unitaire, par exemple en créant des données d'essai. « utp_teardown » — au contraire, ramène tout aux paramètres d'origine et réinitialise les résultats de l'exécution.
Voici un exemple du test unitaire le plus simple, qui vérifie la normalisation du numéro de téléphone du client au format standard de notre système de fidélité. Il n'existe pas de normes obligatoires concernant la rédaction de procédures avec des tests unitaires. En général, un appel est effectué à une méthode du système testé, et le résultat retourné par cette méthode est comparé à une référence. Il est important que la comparaison entre le résultat de référence et le résultat obtenu se fasse via les méthodes standards d'utPLSQL.
Un test unitaire peut comporter un nombre quelconque de vérifications. Comme on peut le voir dans l'exemple, nous effectuons quatre appels consécutifs à la méthode testée pour la normalisation du numéro de téléphone, et après chaque appel, nous évaluons le résultat. Lors de l'élaboration d'un test unitaire, il faut tenir compte du fait qu'il existe des vérifications qui n'ont aucun impact sur le système, tandis que certaines nécessitent un retour à l'état initial du système.
Par exemple, dans le test unitaire présenté, nous formatons simplement le numéro de téléphone d'entrée, ce qui n'a aucun impact sur le système de fidélité.
Mais si nous écrivons des tests unitaires pour la méthode de création d'un nouveau client, alors après chaque vérification, un nouveau client sera créé dans le système, ce qui peut influencer le lancement des tests suivants.

C'est ainsi que les tests unitaires sont lancés. Deux options de lancement sont acceptables : lancer tous les tests unitaires d'un package spécifique ou lancer un test unitaire donné dans un package spécifique.

Voici à quoi ressemble un exemple de système interne de reporting. À la suite du travail des tests unitaires, utPLSQL génère un petit rapport. Dans celui-ci, nous voyons le résultat de chaque vérification spécifique et le résultat global de l'exécution du test unitaire.
6 règles des tests automatisés
Avant de commencer la création d'un nouveau système de tests automatisés pour le système de fidélité, nous avons défini avec la direction les principes auxquels nos futurs tests automatisés doivent se conformer.

- Les tests automatisés doivent être efficaces et apporter une réelle valeur ajoutée. Nous avons d'excellents développeurs dont il est impératif de parler, car certains d'entre eux verront sûrement cette présentation, et ils écrivent un code remarquable. Mais même leur code exceptionnel n'est pas parfait et contenait, contient et contiendra des erreurs. Les tests automatisés doivent détecter ces erreurs. Si ce n'est pas le cas, alors soit nous écrivons de mauvais tests automatisés, soit nous sommes dans un domaine mort qui n'est de toute façon pas amélioré. Dans les deux cas, nous faisons quelque chose de mal, et notre approche devient tout simplement inutile.
- Les tests automatisés doivent être utilisés. Il est absurde de consacrer énormément de temps et d'efforts à la création d'un produit logiciel, de le livrer dans un dépôt et d'oublier ensuite son existence. Les tests doivent être exécutés, et aussi régulièrement que possible.
- Les tests automatisés doivent fonctionner de manière stable. Quelle que soit l'heure, l'environnement de test ou d'autres paramètres du système, les exécutions des tests doivent mener au même résultat. En général, cela est garanti par le fait que les tests automatisés utilisent des données de test spéciales avec des paramètres système fixés.
- Les tests automatisés doivent s'exécuter à une vitesse acceptable pour votre projet. Ce temps est déterminé individuellement pour chaque système. Certains peuvent se permettre de fonctionner toute la journée, tandis que pour d'autres, il est crucial de respecter des limites de quelques secondes. Je vous parlerai plus tard des performances que nous avons atteintes dans notre projet.
- Le développement de tests automatisés doit être flexible. Il est indésirable de renoncer à vérifier une fonctionnalité simplement parce que nous ne l'avons pas encore fait ou pour d'autres raisons. utPLSQL n'impose aucune restriction au développement, et Oracle permet en principe de réaliser des choses très diverses. La plupart des tâches ont une solution, la question n'est que du temps et des efforts investis.
- Déployabilité. Nous avons plusieurs environnements qui nécessitent le lancement de tests. À tout moment, une copie de données sur chaque environnement peut être mise à jour. Il est nécessaire de gérer le projet avec des tests automatisés de manière à pouvoir installer complètement ou partiellement sans douleur.
Et dans le deuxième post dans quelques jours, je vous parlerai de ce que nous avons réalisé et des résultats que nous avons obtenus.
Source : habr.com
