J'ai lu beaucoup de choses avant de poser cette question, y compris de nombreuses questions pertinentes ici sur SE:
Cependant, je ne peux pas m'empêcher de penser que la démangeaison n'a pas encore été rayée après avoir lu pour obtenir de l'aide.
Comment écrire des tests unitaires pour du code hérité que je ne peux pas exécuter, simuler, lire ou comprendre facilement? Quels tests de régression sont utiles à un composant qui fonctionne vraisemblablement comme prévu?
Je suis à nouveau stagiaire d'été alors que je fais la transition vers les études supérieures. Mes tâches impliquent ces exigences:
Après avoir obtenu une copie du code source, j'ai essayé de le construire et de l'exécuter, afin de comprendre ce que fait ce produit et comment il fonctionne. Je ne pouvais pas. J'ai demandé à mes superviseurs comment je fais et j'ai reçu une nouvelle machine autonome capable de la construire, y compris les scripts de construction qui le font réellement. Cela n'a pas fonctionné non plus, car comme ils auraient dû s'y attendre, leur code de production ne fonctionne que sur le système embarqué pour lequel il est conçu. Cependant, ils ont un simulateur à cet effet, ils ont donc obtenu le simulateur et l'ont mis sur cette machine pour moi. Le simulateur n'a pas fonctionné non plus. Au lieu de cela, j'ai finalement reçu une impression d'une interface graphique pour un écran particulier. Ils n'ont pas non plus de commentaires de code dans les 700 000+ Java LOC, ce qui le rend encore plus difficile à saisir. De plus, il y avait des problèmes pour évaluer si leurs projets étaient compatibles ou non avec les nouveaux IDE. En particulier , leur code ne s'est pas chargé correctement dans la très IDE version qu'ils utilisent.
Mon inventaire ressemble à ceci:
J'en ai au moins assez pour écrire théoriquement des tests qui peuvent s'exécuter. J'ai donc essayé un test unitaire de base sur ce composant. Cependant, je n'ai pas pu initialiser les objets qu'il avait en tant que dépendances, qui comprenaient des modèles, des gestionnaires et des connexions de base de données. Je n'ai pas beaucoup d'expérience JUnit au-delà des tests unitaires de base, alors suivez-moi à la section suivante.
setUp
.Et maintenant, une tentative d'articuler l'incertitude que j'ai encore comme question. Essentiellement, je ne comprends pas la partie de la façon d'écrire ces tests. En supposant que je ne reçois pas de conseils supplémentaires de la part de mes superviseurs (probablement), c'est dans mon but non seulement d'apprendre ce que fait ce composant mais de décider quels tests sont réellement utiles comme tests de régression.
En tant que professionnels qui ont travaillé sur des projets comme celui-ci plus longtemps que moi, pouvez-vous fournir des conseils sur la façon d'écrire des tests unitaires dans ce genre de situation?
En première approximation, les parties prenantes d'une suite de tests sont les développeurs/mainteneurs de code. Vous allez avoir besoin de leur temps. Insister là-dessus.
Demandez-leur quels sont les problèmes auxquels ils sont confrontés.
Demandez-leur quels sont les bogues qu'ils ont corrigés récemment (au cours des deux dernières années, en supposant que ce soit un long projet lent).
J'ai l'impression que vous ne vous attendez pas à ce qu'ils soient aimables pour votre travail; peut-être que tu as raison. Mais je ne pense pas que vous puissiez construire quelque chose d'utile sans leur aide.
Ils vont vous tenir la main en écrivant le premier test. Vous les tirerez peut-être, mais vous vous tiendrez par la main de toute façon.
Une fois que vous avez un test, j'espère que ce sera plus clair comment écrire le second. Si vous avez réussi à créer n'importe quel type de rapport, ce sera certainement plus clair.
Je vais supposer qu'à un moment donné, vous pouvez au moins compiler le code. Si vous ne pouvez même pas aller aussi loin, vous êtes en train de faire une folie.
L'absence d'exigences, de spécifications ou de captures d'écran appropriées n'est pas un bloqueur pour l'écriture de tests. Tant que vous pouvez lire le code source, vous pouvez écrire des tests.
Si vous êtes autorisé à refactoriser la base de code pour isoler des éléments tels que les connexions à la base de données derrière leur propre interface, il devient possible d'écrire des tests unitaires de boîte noire - essentiellement des tests pour lancer une entrée sur une méthode et affirmer son comportement ou sa sortie. Obtenez des tests couvrant chaque ligne de code en une seule méthode, puis demandez à l'un des membres les plus expérimentés de l'équipe d'examiner vos tests.
Si vous n'êtes pas autorisé à refactoriser la base de code afin d'écrire des tests unitaires, les tests d'intégration complète ou les tests d'automatisation de l'interface utilisateur sont votre seule option. Même dans ce cas, le test de la boîte noire est votre meilleure stratégie - lancez une entrée dans l'interface utilisateur et voyez comment elle réagit. Faites vos affirmations. Demandez à un membre senior de l'équipe de revoir vos tests.
À un moment donné, vous disposerez de suffisamment de tests automatisés pour pouvoir commencer à refactoriser la base de code en toute confiance pour introduire des tests unitaires. Les tests d'interface utilisateur garantissent le fonctionnement des principaux cas d'utilisation métier, et vous pouvez ensuite moderniser une architecture propice aux tests au niveau des unités ou des composants.
Un autre avantage des tests d'interface utilisateur est que vous pouvez bâtir une réputation auprès de votre équipe grâce à la compréhension de la base de code, ce qui à son tour les rend plus ouverts à l'introduction de modifications, car la preuve se trouve dans le pudding. Et vous aurez fait du pudding en écrivant des tests réussis.
En bref:
Vous seriez surpris de la rapidité avec laquelle vous pouvez apprendre la vue d'ensemble d'une application de 700 000 lignes
Sur la base de la description du problème et de vos commentaires, je pense que le mieux que vous puissiez faire est de commencer avec l'API Java et d'essayer de construire un test unitaire unique autour d'une méthode isolée.
Sans accès au code, je ne peux que vous donner des conseils limités mais je chercherais quelque chose qui a) n'a pas de dépendances b) ne change pas d'état. Par exemple. disons qu'il existe une méthode qui prend une valeur et vérifie qu'elle se situe dans une plage donnée. Si vous ne pouvez pas trouver quelque chose sans dépendances, essayez quelque chose qui récupère une valeur d'une dépendance et essayez de la simuler.
Une fois que vous avez trouvé quelque chose comme ça, vous pouvez commencer à construire des tests. Si la méthode teste une valeur positive, passez-la par un négatif et assurez-vous qu'elle l'attrape, etc. Le problème ici est que vous ne savez pas avec certitude quel est le comportement correct. Vous devrez peut-être demander de l'aide ou fouiller dans la documentation pour cela.
Il est peu probable que vous alliez très loin avec cela. La réalité est que l'écriture de code afin qu'il puisse être testé à l'unité est un art en soi. Le code qui n'a pas été écrit dans cet esprit peut être difficile à impossible à tester unitaire.
Une autre option qui peut être plus facilement implémentée est le test de compatibilité binaire. Autrement dit, vous capturez les entrées et les sorties d'un système, puis pour tester, vous alimentez ces mêmes entrées et comparez les sorties. Cela ne vous dira pas si le code est bon ou mauvais pour commencer, mais cela peut aider à détecter les erreurs de régression là où les choses ont changé involontairement lors d'une autre modification. Vous devrez cependant être en mesure d'exécuter l'intégralité de l'application pour que cela se produise.