Forum Programmation.python tests unitaires

Posté par  . Licence CC By‑SA.
Étiquettes :
1
14
jan.
2022

Bonjour,
J'ai produit du code sur un dépot github (
Et j'ai eu un commentaire sur ce forum que le code n'était pas "testable".
J'ai lu cette dépeche https://linuxfr.org/news/python-partie-9-formateur-de-code-analyse-statique#toc-pytest où il est question de test unitaire.
Je ne comprend pas bien l'interet d'ajouter des fonctions de test à chacune de mes fonctions. En outre je dois prévoir le résultat de la fonction avec un assert pour que le test fonctionne?
Est ce que quelqu'un peut m'expliquer l'interet de faire des tests unitaire? J'ai déja testé au fur et a mesure que j'ai codé chaque fonction "à la main" en fait.

Merci

  • # Commentaire bookmark

    Posté par  . Évalué à 5.

  • # Pourquoi des test unitaires

    Posté par  . Évalué à 7.

    La grande difficulté des tests unitaires c’est de comprendre ce que représente une unité. Il ne faut pas voir l’unité comme forcément une fonction ou une méthode. L’idée est de tester un comportement. Selon les cas, une seule fonction sera suffisante pour le représenter mais bien souvent ça sera sera plusieurs fonctions ou un groupe d’objets.
    La réponse n’est d’ailleurs pas connue d’avance et elle peut varier en fonction des habitudes de programmation ou des choix architecturaux.

    J’ai un peu divagué et mon avis sur l’intérêt des tests unitaires :

    • c’est qu’ils évitent les régressions ;
    • ils documentent le code ;
    • ils permettent de se dire que si ça passe le code fera ce pourquoi il est prévu ;
    • il y a une diminution du stress car ils apportent de la confiance ;
    • ils permettent d’avoir un code plus expressif ;
    • ils évitent d’avoir du code totalement couplé dont la maintenance est un sacerdoce ;
    • ils permettent au développeur de devenir meilleur car il peut expérimenter sans risque de régressions, si ça ne passe pas git reset --hard et on passe à autre chose.

    Plein d’avantages pour ma part et ceux cités ne sont pas dans un ordre particulier. Mais, et c’est un gros mais, il faut une grosse dose d’abnégation pour passer d’écrire les tests après, à écrire les tests en premier puis arriver à faire émerger le design du code en implémentant les tests.

  • # ah les années 90 !

    Posté par  (site web personnel) . Évalué à 5.

    en 1990 : ce serait bien de faire des tests…
    en 2000 : ce serait bien les automatiser (ça fait 10 ans que ça nous gâve), c'est quoi les tests unitaires ?
    en 2010 : eh, les développeurs pourraient ajouter des tests unitaires automatiques.
    en 2015 : tiens, on a des CI/CD quasi opérationnelles, vous penseriez quoi de prendre en compte les tests unitaires ?
    en 2020 : moui, mon bin, spa gagné, les tests unitaires renvoient true à chaque fois (vécu)
    en 2021 : bah, covid, tous foutus
    en 2022 : il serait peut-être temps d'avoir au moins des tests unitaires et des tests d'intégration (pas forcément bout en bout, mais le mini ; j'ai foi en l'humanité pour que quelqu'un comprenne mon commentaire : oui ça demande un peu de recherche, trouver les frameworks de test (yen a plein, cf. depuis 2015 qu'il auraient dû être en place)

    pfff, l'info, depuis tout ce qui fonctionne bien, j'aurais failli y rester, depuis que tout foire, j'ai envie de me casser (non, virer du monde n'est pas une solution, trouver des gens compétents me rassurerait… oui, je suis un des rares à avoir escaladé à mon DSI et DG puis lui à son PDG que nous pouvions résoudre le souci, 3 semaines de crise tout de même…)

    on est tous foutu /o\

    donc : spa gagné, bref


    P.S. : spa faute d'avoir prévenu, d'une part ; d'autre part, les tests unitaires ne suffisent pas, ni les tests d'intégration, une vraie équipe de UAT (user acceptance test) est plus légitime (pour autant, c'est moi en tant que développeur qui intervenait en prod' grâce à leurs informations et disponibilité ; c'est grave et ça n'a pas changé depuis 1990 :/)

    • [^] # Re: ah les années 90 !

      Posté par  (site web personnel) . Évalué à 5.

      pour aller plus loin (non pas là…), tu peux regarder du côté de Test-driven_development moui en anglais :/

      • [^] # Re: ah les années 90 !

        Posté par  (site web personnel) . Évalué à 2. Dernière modification le 16 janvier 2022 à 01:11.

        Ou sinon commencer par l'extreme-programming, le peer-review, les méthodes soit-disantes agiles (non, ça ne veut pas dire pas de doc', c'est plutôt plus de doc' : sur un sprint standard de 6 semaines, passer 2-3 jours à clarifier ce qui doit être fait semblerait le minimum standard, ce n'est pas ce que je constate :/ et les commits journaliers ne le reflètent que rarement).

        Bref : tu mettrais en prod' du code non testé qui est censé tomber en marche auto-magiquement ? (prendre en compte tous les cas d'usage non identifiés en amont…).
        Si tu as la réponse, bah ya de quoi écrire un bouquin :-)
        Voire promouvoir une méthodologie efficace depuis ces 20 dernières années (j'en connais pas, tant pis : reste du boulot demain :p ah si : le respect de l'utilisateur, ça ce serait déjà bien).

  • # merci

    Posté par  . Évalué à 1.

    merci de vos commentaires, je m'acculture au fur et a mesure.

    Mais il y a des cas où je ne sais pas trop comment faire les tests. Par exemple si la fonction lance un programme ou requette sur une base de données ou fait des trucs réseaux.

    Par exemple j'ai une fonction qui lance openvpn avec la commande os.system:

    os.system(
    "openvpn --config /Users/macbook/Downloads/ovpn/ovpn_tcp/"
    + vpn
    + " --auth-user-pass /Users/macbook/Downloads/login.conf --verb 0"
    )

    Comment je suis censé tester ma fonction?

    • [^] # Re: merci

      Posté par  (site web personnel, Mastodon) . Évalué à 4.

      Ceymal… Regarde https://pypi.org/project/openvpn-api/ et https://pypi.org/project/openpyn/ si tu trouves ton bonheur : ce devrait être plus simple à gérer que les appels os.system()

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: merci

      Posté par  . Évalué à 2.

      Pour tester ce genre de chose c’est tout de suite plus compliqué. Il va te falloir créer un niveau d’abstraction, avec une interface ou une classe non-finale, pour ne pas appeler directement ta dépendance.

      Lors de tes tests, tu pourras contrôler ton abstraction et lui faire dire ce qui t’arrange dans ton cas métier.

      Le grand classique, c’est une interface du genre UserRepository avec une méthode get(idUser). Tu veux tester le cas ou l’utilisateur n’existe pas et renvoyer une erreur. Tu peux utiliser un système mock qui au moment de get(monIdFoireux) retourne quelque chose qui représente l’absence. Pour ne pas dépendre d’une bibliothèque de mock, tu crées une classe FakeUserRepository qui implémente l’interface UserRepository et qui pour get(monIdFoireux) retourne un truc vide. Tu injecteras cette classe lors de l’exécution du test.

  • # et pour les fonctions dans des classes?

    Posté par  . Évalué à 1.

    Ok, l'utilisation de mock me parait tres abstraite sans exemple…
    Sinon là je met des fonctions test_fonctionx dans une classe qui contient pleins de fonctions mais pytest ne les détecte pas, est-ce que c'est bien normal?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.