L’importance des tests unitaires en SQL
Les tests unitaires sont un élément essentiel du développement de logiciels de qualité. Cela est vrai aussi bien pour le monde des données que pour le monde du développement de logiciels. Dans cet article, nous examinerons l’importance des tests unitaires en SQL et les différentes options disponibles pour les implémenter.
SCENARIO D’EXEMPLE
Pour illustrer certaines de ces idées, prenons un scénario. Supposons que je travaille sur une requête particulièrement compliquée qui prend 30 minutes et 10 $ pour s’exécuter contre l’ensemble de données de production. Au cours du développement, je dois exécuter la requête 5 fois en apportant de petits ajustements, dépensant à chaque fois un autre dollar et 2 minutes pour que ma requête d’audit se termine (notons que cette étape pourrait être beaucoup plus coûteuse si je devais vérifier manuellement les résultats). En tant qu’ingénieur de données américain moyen gagnant 120 000 $ par an, mon temps coûte environ 57 $ par heure (en ignorant les taxes, les avantages sociaux, etc.). Mon coût de développement est de 171 $ en main-d’œuvre et de 55 $ en traitement, pour un total de 226 $.
L’IMPORTANCE DES TESTS UNITAIRES
La mise en œuvre de tests unitaires pour couvrir la même requête pourrait me prendre une ou deux heures, car elle est vraiment compliquée. Mais maintenant, mes 4 premières exécutions de la requête sont essentiellement gratuites ; comme nous traiterons une poignée d’enregistrements, l’exécution prendra quelques secondes, et je ne serai responsable que de la dernière exécution pour validation : 11 $ et 30 minutes de temps (28,50 $), pour un total de 39,50 $. Combiné avec le surcoût des tests unitaires, nous en avons pour 153,50 $, une économie d’environ 33 %.
Il y a bien sûr des contre-arguments. Que se passe-t-il si la requête ne coûte que quelques centimes et prend seulement quelques secondes à s’exécuter au départ ? Et s’il ne fallait apporter qu’un léger changement et terminer le travail en une seule fois ? Et si je travaillais sur un environnement de développement restreint qui réduisait mes coûts de moitié ou plus ?
Vos cas d’utilisation spécifiques peuvent dicter la quantité de valeur que vous pouvez retirer des tests unitaires, mais je soutiendrais que quelle que soit votre situation, vous devez réfléchir à votre stratégie de test et aux compromis que vous faites. Les tests ont des coûts mais sont cruciaux pour le développement de produits de haute qualité : cela fonctionne de la même manière dans le monde des données que dans le développement de logiciels.
QUELS SONT LES “UNITÉS” EN SQL ?
Mais bien sûr, il y a un hic. Dans le monde SQL, qu’est-ce qu’une “unité” ? Pour un langage comme Python ou Java, les tests unitaires sont souvent effectués au niveau de la méthode ou de la classe ; comme son nom l’indique, ce sont les fonctionnalités les plus basiques à tester.
En SQL, une unité est-elle l’ensemble de la requête ? Est-ce une seule CTE ? Un groupe de CTEs qui transmettent un sens commun ? Cette dernière option ajoute de la complexité aux solutions de tests unitaires, car SQL n’est pas facilement composable comme les langages à usage général ; vous ne pouvez pas simplement “appeler” une CTE comme vous le feriez pour une méthode. Une bonne modélisation des données peut aider à réduire cette charge en rendant vos requêtes plus modulaires, mais une bonne conception de test est toujours difficile, et il existe peu de bonnes pratiques disponibles.
OPTIONS DE TESTS UNITAIRES DISPONIBLES
Il existe plusieurs options pré-construites pour les tests unitaires en SQL, mais il n’y a pas encore de norme à ce stade. Il y a un excellent fil dbt qui détaille les avantages et les approches potentielles, mais malheureusement, cela n’a pas encore fait partie de la feuille de route.
tSQLt est un projet open source maintenu par Redgate, une grande entreprise dans l’espace du développement de SQL Server. Comme beaucoup de solutions SQL Server, tSQLt est implémenté comme une série de procédures stockées ajoutées en tant qu’objets de base de données dans votre base de données cible.
dbt-unit-testing est un paquet dbt maintenu par Equal Experts, un cabinet de conseil en technologie mondial. L’approche consiste à créer des tests personnalisés qui utilisent les macros du package, puis à les exécuter. Ici, les mocks peuvent être définis sous forme de requêtes ou de fichiers CSV, et un travail astucieux avec des macros Jinja substitue les mocks pour les références de table réelles.
dbt-datamocktool est un autre paquet dbt qui adopte une approche légèrement différente. Les mocks et les attentes sont créés sous forme de fichiers seeds, puis les tests sont définis en tant qu’entrées dans le schema.yml du package.
SQLMesh est une nouveauté dans l’espace du SQL. Les tests sont définis dans des fichiers YAML, puis exécutés sur demande. Des mocks et des attentes sont définis dans le même fichier.
CONCLUSION
Au final, les solutions existantes sont toutes assez proches en termes de fonctionnalité et souffrent de problèmes similaires. Tous les outils font plus ou moins la même chose : exécuter vos requêtes avec des entrées de test et comparer la sortie de la requête à une attente. Certains sont plus sophistiqués que d’autres dans la façon dont ils construisent les scénarios de test et génèrent une sortie, mais les différences sont relativement petites.