Tests unitaires et/ou fonctionnels

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Tests unitaires et/ou fonctionnels

par pascaltje » 25 oct. 2008, 18:19

ne pas être affecté par des effets de bord :
il faut cerner les cas particuliers, comme :
- il y a zero, une ou N catégories, comment réagit la classe qui gère ça ?
- la méthode compare 2 trucs : que se passe-t-tl s'ils sont égaux, complétement différents, si le premier ou le second est vide ?
- les bornes aussi, sous toutes leurs formes donc : des nombres ou des quantités d'enregistrements en DB

tout code qui n'est pas testé va planter ( à coup sûr ) :
c'est pour moi en particulier, mon code plantait lamentablement, même sur des trucs simples ( inattention )

www.onpk.net :
c'est le blog de perrick, qui a traduit la doc de SimpleTest et oeuvré à son développement. La doc est en lien en bas à gauche du menu. Il a aussi des articles sur les tests unitaires, plongés au coeur de son blog... il faut fouiller un peu. c'est un état d'esprit qui apparait dans le blog via des cas concrêts.

Maintenant : pourquoi posais-tu la question ? Il y a un besoin particulier ? Un vieux fantasme de programmeur ?

en fait c'est un reproche fait à symfony : créer son propre système de tests alors que des systèmes existants font ça très bien. symfony a réutilisé de très bons concepts et des classes dans la plupart des cas, sauf pour les tests.
ça sous-entend :
- de l'énergie pour créer, débugguer un système de tests
- une logique similaire mais une syntaxe différente/nouvelle à apprendre pour l'utiliser
un peu dommage dans le fond ...

sujet vaste et intéressant :)

A+,

Pascal

par Hywan » 25 oct. 2008, 17:10

Hmmm :-k.

C'est intéressant ce que tu dis. Le fait d'ordonner le raisonnement met en avant des priorités, c'est intéressant. Je n'ai juste pas compris : « _ ne pas être affecté par des effets de bord », tout sous-entend que le test ne doit pas échouer sur des effets de bord, donc il faut testé les valeurs aux limites c'est ça ? Autrement dit, si on a n qui appartient à l'intervalle [1; 10], il faut tester 1 et 10 (je vulgarise).
Aussi, tu dis : « _ être relativement simple à étendre », dans quel sens/cas ?

Ta définition d'unitaire est intéressante aussi. On ne travaille que sur des cas simples. Et si un cas est compliqué, il sera alors compliqué à tester et les résultats ne seront pas fiables à 100% (si je prolonge le raisonnement). C'est bien vu.

En gros, plus un code est atomisé, et plus on pourra être sûr des résultats. D'une part parce que les tests seront plus faciles à mettre en place et parce qu'ils seront plus complets.

Tes remarques sur les tests unitaires sont intéressantes aussi. Je comprends d'une manière générale que les tests obligent le développeur à écrire plus que de code que le code à tester ; d'où l'idée de génération automatique de tests.
En revanche, je ne suis pas d'accord quand tu dis : « * tout code qui n'est pas testé va planter ( à coup sûr ) », c'est pas toujours vrai. On peut prévoir ou anticiper les tests. Sans en faire, on peut quand même penser à gérer des cas. Bien sûr, il est fort probable que ce soit incomplet …

Tu soulèves aussi une idée très très intéressante : « le code de test est un excellent exemple d'utilisation de la classe; il permet un gain de temps énorme pour l'écriture de scripts utilisant cette classe; il constitue une sorte de documentation du code ». Et c'est ce que fait JML et ACSL, les tests sont fait en documentation, c'est à dire qu'ils ont mis au point un langage formel capable de décrire une suite de test, et c'est au moment de la compilation (ou écriture du byte-code) que sont écrit les tests (si j'ai bien tout compris).

Je n'ai pas compris en quoi onpk.net était intéressant :?.

Et pour conclure, on (un ami et moi) a en projet de créer un générateur automatique de tests unitaires réalistes sur les types pour PHP 5. C'est encore au stade de réflexion. En fait, le typage peut être vu comme un cas particulier d'assertion que l'on peut vérifier statiquement ou pas inférence. Donc la première étape du projet serait d'établir une description d'un langage formel/d'annotation afin d'implémenter une procédure de vérification statique du bon typage. La seconde étape serait d'utiliser les types pour guider la génération automatique des tests aléatoires (et uniforme je pense). Et la troisième (et dernière) étape est la plus intéressante : on se servirait des assertions pour affiner le typage et ainsi mieux guider la génération de tests. C'est là que la notion de données réalistes intervient.
En licence 3, on a un projet à faire et au lieu de prendre les projets que les enseignants proposent, avec mon pote, on a décidé de proposer des sujets. Le sujet de base était un générateur automatique de tests, mais le prof vers qui on est allé trouvait ça un peu trop facile à son goût. Donc comme c'est une tronche dans ce domaine (types, contraintes, vérification et validation symbolique etc.), il a voulu faire rejoindre notre projet avec ses recherches. D'où la fin du projet vraiment intéressante avec la notion de données réalistes.

Donc voilà, je me documente tout doucement, et j'étudie les outils déjà existants (à travers vos réponses et remarques :)) pour voir comment tout ça fonctionne, voir les limites, et tenter de les dépasser. Aussi observer les meilleurs solutions, les plus simples, les plus efficaces et comprendre pourquoi. Enfin bref, une phase de documentation classique :).

Maintenant : pourquoi posais-tu la question ? Il y a un besoin particulier ? Un vieux fantasme de programmeur ?

par pascaltje » 25 oct. 2008, 15:49

quelques trucs écrits lors de mon utilisation intensives de tests unitaires :

dans quelle mesure un test valide-t-il réellement ou suffisamment fortement le code?

un bon test ( ou un bon scenario de tests ) doit ( dans l'ordre ):
_ valider les erreurs triviales
_ valider le cas général qui fonctionne
_ valdier les cas particuliers connus
_ ne pas être affecté par des effets de bord
_ être relativement simple à étendre
_ de manière générale, tester entièrement la regle de gestion que le code doit respecter, regle de gestion au moment du codage, qui pourra évoluer par la suite ( qui évoluera par la suite )

qui dit test unitaire dit fonction unitaire: on ne peut tester, dans un premier temps, que ce qui est simple. ceci amène naturellement à simplifier son code ( code unitaire ) et éviter le code couteau suisse :
_ une fonction / méthode ( unitaire ) ne fait qu'une seule action, simple
_ ses valeurs de retours sont normées, définies par le programmeur: booléen, tableau, chaine de caractère ...

toutes les fonctions ne sont pas simples, mais en procédant de cette manière le programmeur écrit des fonctions plus complexes basées sur des fonctions simples ( qui fonctionnent ) . les bugs possibles du code ne sont plus situés au niveau le plus bas, d'où un gain de temps lors de leur traque.

petite liste de remarques sur les tests unitaires:

* tout code qui n'est pas testé va planter ( à coup sûr )
* le code de test est plus long que la classe à tester
* le code de test est plus long que le script utilisant la classe testée
* le code de test est un excellent exemple d'utilisation de la classe; il permet un gain de temps énorme pour l'écriture de scripts utilisant cette classe; il constitue une sorte de documentation du code
* si une classe est difficile à concevoir ( rôles des méthodes, interaction entre classes... ) elle sera difficile à tester
* un code simple = un test simple = une mise en production rapide

à lire aussi, sur les tests unitaires et SimpleTest :
http://www.onpk.net/

as-tu prévu d'intégrer un système de tests existant ou d'en créer un nouveau ?

A+

Pascal

par Hywan » 25 oct. 2008, 13:14

Bien pour les datasets j'ai compris la notion, c'est ce à quoi je pensais.

Je vois aussi le principe de DbUnit. Et c'est bien galère, j'imagine, pour les types UDT (User Domain Type), c'est à dire les types utilisateurs, donc difficilement compréhensible et « anticipable ».

DbUnit s'intéresse aux tests relationnels, je m'orienterais plus vers des tests objets. Et c'est là que Mock Objects seraient intéressants. Je n'ai pas encore saisi toutes les subtilités et surtout le fonctionnement de la chose, mais ça m'a l'air d'être une bonne solution. C'est une façon d'agréger (d'exporter, de délocaliser) les assertions. Même si PHP a un système d'assertion bien pensé (si elles sont désactivées, l'exécution n'est pas ralentie donc on peut les laisser dans le code), il n'est pas toujours top, on est un peu limité, il constitue une base en bref.
Je vais me pencher là-dessus.

Enfin, je pense qu'il y a deux sortes de tests utiles : les tests de conformité et de non-conformité. Lesquels pratiqués vous le plus et pourquoi :) ?

Merci déjà pour ces réponses.

par ouckileou » 25 oct. 2008, 02:07

Par dataset j'entends les données qui vont être utilisées par les tests, pour simuler les différents cas d'utilisation (dans mon cas dbUnit) en lien avec la base. C'est vrai que si tu testes une méthode qui prend en entrée des nombres, et effectue un calcul dessus, tu n'as pas ce problème. Mais parfois tu testes des services qui traiteront des données métiers plus complexes, ou qui tapera dans la base.

Exemple : je fais un service rechercherContratsClientValides(Integer numeroClient)
qui comme son nom le laisse entendre va renvoyer les contrats clients valides pour une date donnée.

Dans mon dataset, pour bien tester tous les cas, je devrais donc avoir des contrats pour ce client, des valides et des non valides, et des contrats pour d'autres clients, du style :

Code : Tout sélectionner

<CONTRAT_CLIENT ID_CONTRAT="1" ID_CLIENT="1" STATUT="valide" /> <CONTRAT_CLIENT ID_CONTRAT="2" ID_CLIENT="1" STATUT="annule" /> <CONTRAT_CLIENT ID_CONTRAT="3" ID_CLIENT="2" STATUT="annule" />
Dans mon test, si je recherche les contrats du client numéro 1, je vérifierai que seul le contrat numéro 1 est renvoyé.

Voici ce que j'entendais par "dataset", un jeu de données de test, utilisées pour tester tous les (ou un maximumde ) cas différents.

Mais ici on est en présence d'un cas simple. Parfois, il est difficile de savoir quels ensembles, quelles associations de données seront possibles dans la réalité ou pas. Par exemple, si sur un objet j'ai plusieurs booléens, il est parfois possible que 2 ne puissent être à "false" en même temps. Ou il y a tellement de propriétés que vous ne savez quoi mettre dedans, alors vous remplissez comme ça vous arrange et vous zappez des cas.

Donc à la question "comment vous faites", je réponds dans l'idéal : tu as des données créées et expliquées par des responsables fonctionnels, qui peuvent t'expliquer aussi ce qui sera possible ou pas, ce qu'il faut tester particulièrement. Histoire de naviguer un peu moins à l'aveuglette.

Mais ça, c'est pas toujours possible :(

Et sinon, je n'ai jamais essayé JMLUnit. Pour finir sur le dataset DBUnit, on peut aussi voir qu'avec les contraintes de bases (dbUnit parse le fichier XML et fait des INSERT, puis rollback à la fin du test, et est donc dépendant des contraintes d'intégrité), on aura peut-être besoin d'un client associé, et un client aura besoin de 5 autres relations avec 5 autres tables, elles-mêmes avec 2 etc.
Vous vouliez juste tester votre petite recherche, et vous passez des heures à créer des données (vaguement) cohérentes, qui rentreront dans votre base sans que le SGBD hurle. Belle perte de temps, alors que si vous aviez un jeu de données tout prêt...

Ah oui et si tu t'intéresses aux tests, tu as regardé les Mock Objects ? http://en.wikipedia.org/wiki/Mock_object

par Hywan » 24 oct. 2008, 19:55

Bien, mes premières réactions.

SimpleTest me paraît très léger, mais tout comme PHPUnit. Ils sont léger, mais si ça se trouve, c'est amplement suffisant non ? Ces deux outils servent essentiellement à faire du test unitaire manuel. Est-ce que vous avez déjà une expérience dans les générateurs de tests (unitaires) ? Ça nécessite des assertions normalement. C'est ce que propose JML pour Java ou ACSL pour C.

Pour les tests de navigation (notion équivalente aux tests fonctionnelles ?), je ne me tourne pas faire ce sujet pour l'instant. Je vais finalement rester concentrer sur les tests unitaires.

JUnit, je vais regarder. As-tu déjà essayé JMLUnit ?

Tu parles de la limite des ensembles de données (ou intervalles de données, dataset, intervalles me paraît plus juste qu'ensemble). On travaille sur les types et chaque type a un ensemble de valeur à tester c'est ça ? Je demande pour savoir si on parle de la même chose :). Je n'avais pas penser aux ensembles de données traités par les bases de données … c'est vrai que c'est bien embêtant :-k.

Tu as aussi touché très juste en disant :
Mais surtout c'est parfois difficile de savoir quelles données seront cohérentes dans la réalité ou pas.
Comment savoir si une donnée est réaliste ou pas d'après vous ? Comment faites-vous concrètement ?

par ouckileou » 24 oct. 2008, 18:44

Tests unitaires en Java : JUnit via Eclipse

Sur le projet en cours, le gain est très appréciable en cas de refactoring. Genre tu veux modifier ton code pour mieux l'organiser, ou pour l'optimiser, tu vérifies que tes tests passent bien ensuite.

La principale limite à mon avis est lorsque le développeur doit lui-même créer les données (dataset) utilisées pour les tests : outre le fait que c'est une énorme perte de temps parfois (on veut tester un objet soit une table, mais il faut se taper touuuutes les contraintes d'intégrité, c'est une vraie pelote de laine) il y a le risque qu'il s'arrange un peu pour ne tester que certains cas.

Mais surtout c'est parfois difficile de savoir quelles données seront cohérentes dans la réalité ou pas. Genre savoir que si on a tel flag à true, telle autre donnée ne peut pas être nulle. Si le développeur ne le sait pas, ce n'est pas testé, et ça pète ensuite. Idéalement les cas de tests et les données qui vont avec devraient être réalisés par (ou avec) un fonctionnel.

Sinon la base simple de la prog par contre c'est vrai que c'est pratique, un assertNotNull en entrée de méthode, avec un petit message custom ("nomMethode:variable can not be null"), et on sait tout de suite où est le problème lors des tests.

Toujours entendu que Selenium était très bien aussi, de ce que j'en ai vu, mais jamais utilisé personnellement.

par pascaltje » 24 oct. 2008, 16:36

j'ai utilisé SimpleTest, ça marche bien, avec un résultat visuel incontestable :
les test passent, c'est vert
ça foire, c'est rouge

pour les tests de navigation, j'ai un peu utilisé selenium.

je n'ai pas utilisé le FW de test dans symfony, qu'un nouvel outil de test soit développé me semble étrange, il y en a qui existent déjà...

A+

Pascal

Tests unitaires et/ou fonctionnels

par Hywan » 24 oct. 2008, 16:18

Hey :),

Je m'intéresse aux tests unitaires et fonctionnels et j'aurais aimé connaître vos habitudes, vos outils, vos documentations etc. En gros, si vous utilisez les tests, j'aimerais connaître ce que cela vous a apportez concrètement, avec quels outils travaillez-vous, quels sont leurs limites, quelles seraient les améliorations possibles et/ou souhaitées … ?

On peut parler aussi de programmation par contrat (assertion), donc de JML, ACSL etc., pour ceux qui ne le font pas forcément en PHP.

En gros : je veux tout savoir ;-).

Merci :).