Qui n'a jamais entendu cette question dans l'espace ouvert "oui, mais elle fait quelle taille ton unité ?" Et l'autre de répondre : "petite, comme... heu", et là, patatras, pas de point de comparaison. Pourtant, l'autre utilise JUnit, ou PHPUnit, ou un autre. Oui, JUnit, le cadriciel créé par Kent Beck et Erich Gamma (du GoF), LE Kent Beck du Test-Driven Development, le fameux TDA, pardon, TDD. Ne nous emportons pas, l'autre est peut-être adepte du Behavior-Driven Development, la fameuse méthodologie où ce sont les analystes métiers qui rédigent directement les cas de tests, grâce aux harnais fournis par les développeurs, et pas un dévoiement de la méthodologie où le développeur code dans un langage de concombres (même pas masqués) ? Ou simplement en écrivant des noms de méthodes de 500 caractères de long en faisant des phrases dans un anglais plus qu'approximatif ?
Soyons raisonnables : restons sur Beck et le TDD. On connaît les différents types de test : unitaire, intégration, fonctionnel, bout-en-bout (e2e). On peut dire que c'est bio, comme ces concombres, ou plutôt que c'est naturel : tout le monde est d'accord sur ce vocabulaire. Voyons donc comment Kent qualifie les tests unitaires dans "Test-Driven Development By Example" publié en 2003 (je jaunis) :
Le problème à conduire les développements avec des tests à petite échelle (je les appelle “tests unitaires”, mais ça ne correspond pas très bien à la définition acceptée des tests unitaires) est que vous courrez le risque d'implémenter ce que vous pensez être la volonté de l'utilisateur, mais qui s'avère ne pas être ce qu'ils veulent du tout.1
Ha. Beck nous donne deux informations : d'un, une définition de "test unitaire" existe bien dans le monde professionnel et de deux, il n'en a strictement rien à faire. Le nom JUnit est donc tamponné du fameux "vu et s'en cogne".
Va-t-il falloir fouiller tel un archéologue de l'ACM pour trouver ces fameuses définitions ? Lire des dizaines d'auteurs rendant compte de manière en apparence contradictoire ? Non, il suffit de Beizer.
Je parle évidemment de Boris Beizer, un des onze distingués de l'International Software Testing Qualification Board, et auteur de deux livres de référence sur la qualité logicielle : Software Testing Techniques (1983) et Software System Testing and Quality Assurance (1984). Voyons ce qu'il écrivait à ce sujet dans la seconde édition de 1990 du premier livre ; c'est un peu long, mais vous serez récompensés de cette lecture par un eurêka de fort bon aloi.
Nous testons selon trois types distincts un système logiciel typique : test unitaire/de composant, test d'intégration, et test de système. Les objectifs de chaque classe sont différents et en conséquence, on peut s'attendre à une utilisation d'un mélange de méthodes de test. Elles sont :
Unité, Test unitaire — Une unité est le plus petit élément d'un logiciel qu'on puisse tester, c'est-à-dire qu'il peut être compilé ou assemblé, lié, chargé et mis sous le contrôle d'un banc d'essai ou d'un pilote. Une unité résulte habituellement du travail d'un programmeur et consiste en quelques centaines (ou moins) de lignes de code source. L'activité de test unitaire est effectuée pour montrer que l'unité ne satisfait pas à ses spécifications fonctionnelles et/ou que sa structure d'implémentation ne correspond pas à la conception technique. Quand nos tests mettent en évidence de telles fautes, on parle de bug unitaire.
Composant, Test de composant — Un composant est un agrégat intégré d'une ou plusieurs unités. Une unité est un composent, un composant et les sous-routines qu'il appelle est un composant, etc. Par cette définition (récursive), un composant peut-être n'importe quoi d'une unité à un système entier. L'activité de test de composant est effectuée pour montrer que le composant ne satisfait pas à ses spécifications fonctionnelles et ou que sa structure d'implémentation ne correspond pas à la conception technique. Quand nos tests mettent en évidence de telles fautes, on parle de bug de composant.
Intégration, Test d'intégration — Une intégration est un processus par lesquels les composants sont intégrés pour créer de plus grands composants. L'activité de test d'intégration est effectuée pour montrer que, en dépit du fait que les composants sont individuellement satisfaisants, comme démontré par la validation par les tests de composant, la combinaison des composants est incorrecte ou incompatible. [...]Je suis redevable à l'un de mes étudiants de séminaire pour l'illustration élégante suivante de la problématique de tests de composants et d'intégration. Soit une sous-routine A, qui s'appelle elle-même de manière récursive. Le test de composant n'inclut pas l'appel des sous-composants ; en conséquence, la récurrence de l'appel de A à A n'est pas testé. Le test d'intégration est celui de l'appel de A et de son retour. Ce nouveau composant, intégré, est clairement différent car il implique le support des appels récursifs (par exemple avec une pile), qui n'était pas testé auparavant ; en conséquence, en tant que "nouveau" composant, il requiert une activité de test supplémentaire.
Système, Test de système — Un système est un gros composant. L'activité de test de système vise à mettre en évidence des anomalies qui ne peuvent pas être attribuées à des composants en tant que tels, comme des incompatibilités entre composants, ou des interactions prévues de composants et d'autres objets. Les tests système concernent les problèmes et les comportements qui ne peuvent être mis en évidence qu'en testant l'ensemble du système intégré ou une partie majeure de celui-ci. L'activité de test de système inclue la mise à l'épreuve des performances, de la sécurité, de la sensibilité à la configuration, du démarrage et de la récupération.2
Si pour certains tester c'est douter, avec Beizer le doute ne m'habite plus : c'est clair comme de l'eau de roche. Quelque part, ça n'est pas étonnant : après une première carrière d'ingénieur, ces livres sont le fruit de quinze ans de pratique professionnelles dans l'assurance qualité logicielle, parmi laquelle le test prend une part éminemment importante. Alors pourquoi Beizer ne fait pas partie de nos enseignements, malgré son statut ?
S'il est une référence, c'est pour la communauté des testeurs, en particulier pour la génération qui s'est professionnalisée dans les années 80 et 90. Malheureusement, en termes de nombre, cette commu' n'a pas explosé comme celle des codeurs-doux heurt-mais cœur. Et par ce simple effet de masse, sur la métrique du rayonnement, on peut dire que Beizer n'est pas un bon coup. Pour faire du travail de programmation de qualité, on a pourtant tout à gagner à lire Beizer encore et encore, jusqu'au bout de la nuit.
Citations en langue d'origine
-
The problem with driving development with small-scale tests (I call them “unit tests,” but they don’t match the accepted definition of unit tests very well) is that you run the risk of implementing what you think users want, but having it turn out not to be what they wanted at all. ↩
-
We do three distinct kinds of testing on a typical software system: unit/component testing, integration testing, and system testing. The objectives of each class is different and therefore, we can expect the mix of test methods used to differ. They are:
Unit, Unit Testing — A unit is the smallest testable piece of software, by which I mean that it can be compiled or assembled, linked, loaded, and put under the control of a test harness or driver. A unit is usually the work of one programmer and it consists of several hundred or fewer, lines of source code. Unit testing is the testing we do to show that the unit does not satisfy its functional specification and/or that its implemented structure does not match the intended design structure. When our tests reveal such faults, we say that there is a unit bug.
Component, Component Testing — A component is an integrated aggregate of one or more units. A unit is a component, a component with subroutines it calls is a component, etc. By this (recursive) definition, a component can be anything from a unit to an entire system. Component testing is the testing we do to show that the component does not satisfy its functional specification and/or that its implemented structure does not match the intended design structure. When our tests reveal such problems, we say that there is a component bug.
Integration, Integration Testing — Integration is a process by which components are aggregated to create larger components. Integration testing is testing done to show that even though the components were individually satisfactory, as demonstrated by successful passage of component tests, the combination of components are incorrect or inconsistent. [...] ↩I’m indebted to one of my seminar students for the following elegant illustration of component and integration testing issues. Consider a subroutine A, which calls itself recursively. Initial component testing does not include the called subcomponents; therefore the recursive call of A by A is not tested. Integration testing is the test of the A call and return. The new, integrated component is clearly a different kind of component because it invokes the recursive call support mechanisms (e.g., the stack), which were not tested before; therefore, as a “new” component, it needs additional testing.
System, System Testing — A system is a big component. System testing is aimed at revealing bugs that cannot be attributed to components as such, to the inconsistencies between components, or to the planned interactions of components and other objects. System testing concerns issues and behaviors that can only be exposed by testing the entire integrated system or a major part of it. System testing includes testing for performance, security, accountability, configuration sensitivity, start-up, and recovery.
Top comments (0)