> Tech > Trop de rouages

Trop de rouages

Tech - Par Renaud ROSSET - Publié le 30 novembre 2010
email

Lorsque vous écrivez des tests unitaires, l’implémentation la plus simple consiste à faire en sorte qu’ils effectuent des lectures et écritures sur la base de données dans le cadre de leur exécution. Tout cela semble à première vue sensé ! Vos tests visent à mettre à l’épreuve le niveau

Trop de rouages

métier (modèle de domaine, couche de services, façade), la couche de présentation (MVC [Model-View-Controller], MVP [Model-View-Presenter]) et les objets d’accès aux données.

A l’évidence, ce test est pertinent et complet, mais vous allez rencontrer des problèmes subtils. Par exemple, supposons que vous travailliez sur une méthode de votre niveau métier qui vérifie l’existence d’un utilisateur avec un nom d’utilisateur. Si l’utilisateur existe, la méthode de niveau métier doit retourner vrai (true) et, dans le cas contraire, elle doit retourner faux (false). Votre test unitaire ressemblera à ce qui suit.

La méthode UserFacade aura l’aspect suivant :

public bool UsernameExists(string username)
{
UserDataAccess da = new
UserDataAccess();
User user = da.GetByUserName(username);
if (user!= null)
{
return true;
}
else
{
return false;
}
}

Il s’agit d’un bon test, lequel vérifie la fonctionnalité pour les cas « existe » et « n’existe pas », mais c’est là que les choses se compliquent un peu. Pour que ce test soit fiable, vous devez, avant de l’exécuter, placer la base de données dans un état connu, où le nom d’utilisateur « benday » existe et « benday2 » n’existe pas. C’est suffisamment simple à réaliser si vous pouvez créer et supprimer rapidement des utilisateurs. Mais qu’en est-il si ce n’est pas le cas ? Que se passe-t-il si la table UserLogin a une contrainte de clé étrangère qui vous impose de créer un enregistrement Person avant de créer l’enregistrement UserLogin ?

Dans ce cas, vous devez créer un enregistrement Person afin de créer l’enregistrement UserLogin, puis vous devez supprimer l’enregistrement Person avant de supprimer l’enregistrement UserLogin. Ce n’est pas des plus compliqués, mais cela représente du travail supplémentaire pour configurer le test, et cette tâche n’est pas vraiment en rapport avec ce que vous essayez de tester. Ensuite, vous avez le problème consistant à vérifier que votre code de niveau métier et de niveau accès aux données est synchronisé avec le schéma de base de données.

Encore une fois, ce n’est pas la mer à boire, mais cela vient vous distraire un peu plus dans votre tâche d’écriture de votre test unitaire et de votre code applicatif. Il est trop simple de faire fonctionner tout cela avec une base de données.

Introduisons plus de complexité dans votre architecture. Supposons que vous écriviez une application orientée services au moyen de WCF. Pour effectuer le contrôle UserName Exists(), l’objet UserFacade doit appeler un service Web. Maintenant, vous devez être certain que votre service Web est déployé et opérationnel, et qu’il pense que le nom d’utilisateur « benday » existe alors que « benday2 » n’existe pas. Certes, ce n’est pas insurmontable, mais cela ajoute encore plus de rouages à votre test. Qu’en est-il si vous partagez une instance du service Web avec d’autres développeurs ? Si vous commencez à ajouter et à supprimer des utilisateurs, cela va-t-il perturber les tests de quelqu’un d’autre ? Existe-t-il une possibilité que deux personnes exécutent les tests à peu près en même temps et que cela aboutisse à de fausses réussites ou de faux échecs dans vos tests unitaires ? Par ailleurs, si le service Web tombe en panne, vous et les autres développeurs serez bloqués.
A mesure que votre application devient plus complexe, vous allez probablement ajouter toujours plus de tests unitaires avec les exigences de configuration et, après un temps relativement court, il deviendra clair que vous effectuez beaucoup trop de travail pour garantir le bon fonctionnement de vos tests. Vous avez conçu vos tests et votre application de manière fortement couplée et vous arrivez maintenant au problème d’intégration de bout en bout.

Si vous pouvez supprimer la dépendance directe au niveau de la classe UserDataAccess, vous pouvez éliminer le besoin de la base de données. Le code pour la méthode UsernameExists() de l’objet User Facade est constitué de deux parties : l’accès aux données et la logique statuant sur l’existence de l’utilisateur.
Pour les besoins de votre test unitaire, vous vous intéressez uniquement à la logique et il est inutile de tester le code d’accès aux données.

Téléchargez cette ressource

Comment sécuriser une PME avec l’approche par les risques ?

Comment sécuriser une PME avec l’approche par les risques ?

Disposant de moyens financiers et humains contraints, les PME éprouvent des difficultés à mettre en place une véritable stratégie de cybersécurité. Opérateur de services et d’infrastructures, Naitways leur propose une approche pragmatique de sécurité « by design » en priorisant les risques auxquelles elles sont confrontées.

Tech - Par Renaud ROSSET - Publié le 30 novembre 2010