Devrait-il y avoir des tests unitaires pour les expressions régulières complexes?

34

Devrais-je écrire des tests unitaires pour les expressions régulières complexes dans mon application?

  • D'une part, ils sont faciles à tester, car les formats d'entrée et de sortie sont souvent simples et bien définis, et ils peuvent souvent devenir si complexes que leurs tests sont particulièrement utiles.
  • Par contre, ils font rarement partie de l'interface d'une unité. Il serait peut-être préférable de ne tester que l'interface et de le faire d'une manière qui teste implicitement les expressions rationnelles.

MODIFIER:

Je suis d'accord avec Doc Brown qui, dans son commentaire, note qu'il s'agit d'un cas particulier de test unitaire de composants internes .

Mais comme composants internes, les expressions rationnelles ont quelques caractéristiques spéciales:

  1. Une regex sur une seule ligne peut être vraiment complexe sans être vraiment un module séparé.
  2. Les regex associent l'entrée à la sortie sans aucun effet secondaire et sont donc très faciles à tester séparément.
Lii
la source
12
"Ils font eux-mêmes rarement partie de l'interface d'une unité." - Si vos classes ont un code intéressant enfoui au fond de l'interface, séparez vos classes. Ceci est un exemple de la façon dont penser à tess peut améliorer le design.
Nathan Cooper
3
La même question d'une manière plus générale: quels composants internes doivent être testés? Voir programmers.stackexchange.com/questions/16732/…
Doc Brown
En quelque sorte, voir Regex101. Ils ont une section pour écrire des tests unitaires pour votre regex.Par exemple: regex101.com/r/tR3mJ2/2
David dit Réintégrer Monica
3
Avertissement - ce commentaire est mon humble avis: 1 d'abord , je crois que les regexps complexes sont mal pur - voir aussi blog.codinghorror.com/... 2 valeur réelle de tester ces expressions vient quand vous les tester sur une grande base de données réelle data blog.codinghorror.com/testing-with-the-force 3 J'ai un sentiment étrange que ces tests ne sont pas exactement des tests unitaires
Boris Treukhov

Réponses:

101

Mis à part le dogmatisme mis à part, la vraie question est de savoir s'il apporte de la valeur aux expressions régulières complexes du test unitaire. Il semble assez clair que cela apporte de la valeur (que la regex fasse ou non partie d'une interface publique) si la regex est suffisamment complexe, car cela vous permet de rechercher et de reproduire des bogues et d'éviter les régressions.

JacquesB
la source
25
+1, mais si une expression régulière est assez complexe que c'est un problème, alors il est probablement judicieux de le déplacer dans une unité « enveloppe » avec des méthodes appropriées ( isValid, parse, tryParseou tout le reste, selon exactement comment il est utilisé), alors que le code client n'a pas besoin de savoir qu'il est actuellement implémenté en utilisant une expression régulière. L’unité d’emballage disposerait alors de tests détaillés qui - là encore - n’auraient pas besoin de connaître l’implémentation actuelle. Bien sûr, ces tests testent de facto la regex, mais d’une manière indépendante de la mise en œuvre.
Ruakh
1
Un reg ex est un programme, bien que dans un langage spécialisé et très concis. En tant que tel, le test est approprié pour les expressions non triviales ... Et le code qui appelle l'expression doit être testé, ce qui peut implicitement tester le réservé.
Keshlam
6
@ruakh Bien dit. L'avantage d'une classe wrapper pour une expression régulière est que vous pouvez la remplacer proprement par du code ordinaire si cela devient nécessaire. Le code avec une entrée / sortie complexe doit toujours avoir des tests unitaires, car il est remarquablement difficile de déboguer sans. Si vous devez vous référer à la documentation pour comprendre les effets du code, des tests unitaires sont nécessaires. Si c'est juste un mappage rapide 1: 1 comme une conversion de type, alors il n'y a pas de problème. Les regexes dépassent ce stade de la nécessité de docs très rapidement.
Aaron3468
4
@Lii: Regexes ne mérite pas de traitement particulier. La regex est l'unité dans ce cas, nous la testons donc un peu.
JacquesB
1
@ruakh j'étais sur le point d'écrire une réponse à cet effet. Je conviens que l'utilisation de regex est un détail d'implémentation. Ce qui compte, c’est que les choses valident quand elles sont supposées le faire et ne le font pas quand elles sont supposées le faire. Testez le FooValidatorpour ses entrées et sorties, alors vous ne vous inquiétez pas de la façon dont cela se fait. ++
RubberDuck
21

Regex peut être un outil puissant, mais ce n’est pas un outil sûr, mais qui fonctionne quand même si vous apportez des modifications même mineures à des regex complexes.

Créez donc de nombreux tests qui documentent les cas qu’il devrait couvrir. Et créez de nombreux tests qui documenteront les cas où il devrait échouer, s’il est utilisé pour la validation.

Chaque fois que vous devez modifier vos expressions rationnelles, vous ajoutez les nouveaux cas en tant que tests, modifiez-les et espérez que tout ira pour le mieux.

Si j'étais dans une organisation qui en général n'utilisait pas de tests unitaires, j'écrirais quand même un programme de test permettant de tester toutes les expressions rationnelles que nous utiliserions. Je le ferais même pendant mon temps libre, mes cheveux n’auraient pas besoin de perdre plus de couleur.

Courbé
la source
3

Les expressions régulières sont du code avec le reste de votre application. Vous devriez vérifier que le code global fait ce que vous attendez de lui. Cela a plusieurs objectifs:

  • Les tests sont des documentations exécutables. Cela montre clairement ce que vous devez faire avec le code. Si c'est testé c'est important.
  • Les futurs responsables de la maintenance peuvent être certains que s’ils le modifient, les tests garantiront que le comportement reste inchangé.

Comme il existe un obstacle supplémentaire à surmonter en ayant un code dans une langue différente intégrée au reste, vous devriez probablement accorder cette attention supplémentaire au bénéfice de la maintenance.

Thorbjørn Ravn Andersen
la source
1

En bref, vous devriez tester votre application, un point c'est tout. Que vous testiez votre regex avec des tests automatisés qui l'exécutent de manière isolée, dans le cadre d'une boîte noire plus grande ou que vous le manipuliez à la main, est secondaire au point où vous devez vous assurer que cela fonctionne.

Le principal avantage des tests unitaires est qu'ils permettent de gagner du temps. Ils vous permettent de tester la chose autant de fois que vous le souhaitez ou à tout moment dans le futur. S'il y a une quelconque raison de croire que votre expression rationnelle sera à tout moment refactorisée, modifiée, si vous obtenez plus de contraintes, etc., alors oui, vous voulez probablement des tests de régression, ou si vous le modifiez, vous devrez aller au cours d’une heure de réflexion sur tous les cas critiques afin que vous n’ayez pas rompu. Ou alors vous apprenez à vivre avec la peur de votre code et ne le changez jamais.

Sara
la source
3
Une règle de base, je viens de réaliser; si j'avais besoin de docs pour écrire et inspecter le code, il me faudrait un test unitaire. Ils m'ont évité beaucoup de maux de tête, attraper des pointeurs nuls, aucun type et une sortie incorrecte. Ils donnent également à l'utilisateur final la possibilité de réparer votre code selon les spécifications, avec un minimum d'effort, lorsqu'il tombe inévitablement.
Aaron3468
-1

Par contre, ils font rarement partie de l'interface d'une unité. Il serait peut-être préférable de ne tester que l'interface et de le faire d'une manière qui teste implicitement les expressions rationnelles.

Je pense qu'avec ça tu y as répondu toi-même. Les regex dans une unité sont très probablement un détail d'implémentation.

Ce qui va pour tester votre SQL va probablement aussi pour les regex. Lorsque vous modifiez un élément SQL, vous devez probablement l'exécuter manuellement sur un client SQL pour voir s'il donne les résultats escomptés. Il en va de même lorsque je modifie une expression rationnelle, j'utilise un outil d'expression régulière avec des exemples d'entrées pour voir s'il fait ce que j'attendais.

Ce que je trouve utile, c’est un commentaire près de la regex avec un échantillon de texte auquel il devrait correspondre.

Christiaan
la source
" Lorsque vous modifiez une partie de SQL, vous la passez probablement à la main dans un client SQL pour voir si elle donne les résultats escomptés. " tester les regex à la main, alors je devrais faire un test unitaire pour cela à la place. C'est justement ce qui rend difficile le choix!
Lii
Ça dépend vraiment. Ce que vous voulez pour vos tests unitaires, c'est la possibilité d'apporter des modifications. À quelle fréquence modifiez-vous une expression régulière spécifique? Si la réponse est souvent donnée, créez-en un test.
Christiaan
8
Toutes choses étant égales par ailleurs, il vaut mieux avoir un test automatisé qu'un "test à la main".
Robert Harvey
1
Pourquoi ne pas tester une regex en utilisant l'automatisation?
Tony Ennis
1
Cela fait partie d'une méthode et tout ce que j'essayais de dire, c'est qu'il n'est pas nécessaire de tester spécifiquement la regex si vous testez déjà cette méthode. Mais si vous le faites, vous feriez probablement mieux d’extraire l’expression rationnelle dans une fonction distincte que vous testez isolément.
Christiaan,
-5

Si vous devez demander, la réponse est oui.

Supposons que FNG pense qu'il peut "améliorer" votre regex. Maintenant, il est un FNG, donc automatiquement un idiot. Exactement le genre de personne qui ne devrait jamais toucher votre précieux code! Mais peut-être qu'il est lié au PHB ou à quelque chose du genre , alors vous ne pouvez rien faire.

Sauf que vous savez que le PHB va vous traîner en arrière et crier vers ce projet pour "peut-être donner au gars des indications sur la façon dont vous avez créé ce gâchis" quand tout va mal. Donc, vous écrivez tous les cas que vous avez soigneusement pris en compte lors de la construction de votre beau chef-d'œuvre d'expression.

Et puisque vous les avez toutes écrites, vous avez deux tiers du temps nécessaire pour avoir un ensemble de tests élémentaires, car, avouons-le, les scénarios de test regex sont extrêmement faciles à exécuter une fois que vous avez construit le cadre.

Alors maintenant, vous avez un ensemble de conditions de bord, d'alternatives et de résultats attendus. Et tout à coup, les cas de test constituent la documentation, comme promis dans tous ces articles de blog trop agiles. Vous venez de faire remarquer à la FNG que si son "amélioration" ne réussissait pas les tests existants, ce n'était pas vraiment une amélioration, n'est-ce pas? Et où sont ses nouveaux cas de test proposés qui démontrent un problème avec le code original, puisque cela fonctionne, il n'a pas besoin d'être modifié, jamais !!!

Austin Hastings
la source
3
qu'est-ce que FNG? Cela ne semble pas être une mauvaise réponse pour moi, mais une définition manquante pour FNG (googlin car elle ne donne que des résultats qui ne sont pas liés, alors peut-être que cette réponse a simplement été votée à cause de FNG?)
GameDeveloper
1
Je suppose que Google vous a emmené au bon endroit. ;-) ( en.wikipedia.org/wiki/FNG_syndrome )
Austin Hastings
Sauf si vous êtes un génie absolu de la programmation, il y aura des programmeurs plus expérimentés tenant compte de ce que vous faites, comme si vous regardiez le nouveau type. Vous voudrez peut-être envisager d'être plus humble.
Thorbjørn Ravn Andersen