septembre
2011
Voici un des grands classiques des tests unitaires, la fameuse couche d’accès et la problématique lié à la base de donnée …
Comme pour tout problème non trivial, il existe une multitude de solutions, d’ailleurs il n y a pas longtemps une liste des solutions possibles a été donnée dans un des blogs de developpez :
http://blog.developpez.com/nico-pyright/p8194/c/tests-unitaires-comment-tester-sa-couche/
Pour moi la base de donnée fait partie intégrante du système et pour cette raison je ne conçois pas des test indépendant de la base (en tout cas en ce qui concerne la DAL), quitte à rendre cette partie de mes test moins unitaires.
Et la meilleure façon de tester en évitant les surprises est de tester dans des conditions proches de l’environnement de production. Mais ceci pose un problème majeur, comment peut on garantir le même résultat pour plusieurs exécutions ?
Pour remédier à cela, il existe des Frameworks qui permettent de faire certaines choses (DBunit …), initialiser les données avant de lancer les tests, par exemple.
Mais de toutes les approches, je préfère celle qui manipule directement le contenu de la base sans altérer son contenu, évitant par ailleurs le télescopage entre plusieurs test.
Certains Frameworks permettent l’utilisation de l’attribut Rollback, Nunit permet de le faire mais seulement avec une extension (xtUnit pour qui ça intéresse), l’autre solution serait d’utiliser TransactionScope :
public void InsertCustomer_CheckQuantityClientInsert_CorrectInsertion()
{
Customer customer = new Customer("Nicolas","Paris");
using (TransactionScope transaction = new TransactionScope())
{
int nbInserted = customerDAL.InsertCustomer(customer);
Assert.That(nbInserted, Is.EqualTo(1));
}
}
public void InsertCustomer_CustomerExistsInDatabase_FailureInsertion()
{
Customer customer = new Customer("Nicolas","Paris");
using (TransactionScope transaction = new TransactionScope())
{
int nbInserted = customerDAL.InsertCustomer(customer);
Assert.That(nbInserted, Is.EqualTo(0));
}
}
Pour exécuter un tel test il faut :
– Référencer System.transactions
– Avoir une entité Customer
– Une class d’accès customerDAL ayant une méthode InsertCustomer qui retourne le nombre de lignes affectées.
Autre scénario
public void InsertCustomer_CheckQuantityClientInsert_CorrectInsertion()
{
Customer customer = new Customer(5, "Nicolas","Paris");
using (TransactionScope transaction = new TransactionScope())
{
int nbInserted = customerDAL.InsertCustomer(customer);
Customer customerResult = = customerDAL.GetCustomerById(5);
Assert.That(customerResult.City , Is.EqualTo("Paris"));
customer.City = "London";
int nbUpdated = customerDAL.UpdateCustomer(customer);
customerResult = customerDAL.GetCustomerById(5);
Assert.That(nbUpdated, Is.EqualTo(1));
Assert.That(customerResult.City , Is.EqualTo("London"));
}
}
Voici un scénario pas forcément très unitaire, mais qui permet de tester efficacement une mise à jour, à condition que l’insertion et la sélection soit bien tester également.
La condition de l’utilisation de TransactionScope ici est que la IDBConnection soit partager entre les différentes méthodes appelées de la DAL.
Donc pour conclure ma solution n’est pas forcément un Test Unitaire, mais pour l’instant c’est la seule qui m’est vraiment convaincu
3 Commentaires + Ajouter un commentaire
Commentaires récents
- [Scrum] Générer un Burdown chart de Sprint dans
- [Scrum] Générer un Burdown chart de Sprint dans
- Les stars de l’actualité informatique : Cloud et Agilité … dans
- Les stars de l’actualité informatique : Cloud et Agilité … dans
- Organiser sa journée de travail ? Efficacité et productivité sans stress c’est possible dans
les bases sont réduites au minimum.
Et les tests auto sont joués la nuit.
Globalement les temps sont encore corrects.
Oui c’est claire, j’ai envie d’ailleurs d’essayer à cette occasion Spring.net.
Sinon pour ta solution, elle n’est pas trop lente la solution de la restauration ? A moins qu’elle soit vraiment vierge en données ?
Tu devrais pouvoir assez facilement faire une classe de base pour éviter de mettre le TransactionScope dans chaque test.
De mon coté, j’ai fait un truc similaire, mais avec une restauration de base automatique via SMO