Test des repository

8 views
Skip to first unread message

Julien Lavigne du Cadet

unread,
Nov 13, 2008, 3:53:08 AM11/13/08
to paris.alt.net

Bonjour à tous,

J'aimerai savoir comment vous testez vos repository dans vos projets,
et quels sont les + et les - de vos solutions.

Je sais qu'il y a plusieurs solutions :
1) Tester le repository avec une bdd de dev "classique"
2) Tester le repository avec une base sqlite chargée en mémoire
3) Ajouter une couche d'abstraction supplémentaire entre le repository
et la persistance, puis remplacer la couche persistance lors des tests
par une implémentation Fake à base de hastable ou autre.

La solution 1) n'est pas une option à cause de la vitesse d'execution
des tests.

La solution 2) est très intéressante mais un peu galère à mettre en
place (car il faut recréer le schéma systématiquement, sachant qu'un
schéma pour sql server n'est pas compatible avec sqlite sans
modifications manuelles). Je voulais utiliser migrator.net pour gérer
le problème mais c'est un peu buggé.

La solution 3) me parait la plus simple, mais elle ajoute un niveau
d'abstraction supplémentaire qui n'a à priori raison d'être que pour
les tests

Quel est votre expérience? Que pensez vous de chaque solution? quelles
sont vos best-practices?

Thanks!

Julien

P.S : Je me permets de prendre un petit peu d'avance sur les
discussions à venir lors de la prochaine réunion :-)

DUVAL Olivier

unread,
Nov 13, 2008, 4:36:07 AM11/13/08
to paris...@googlegroups.com
Bonjour tout seul,

 Pour ma part, je suis en train de "tester" la solution 2, avec SQLite, avec une utilisation en mémoire de cette dernière. Le schéma est généré à chaque test (SchemaExport).
 Cela fonctionne pas mal, mais j'ai dû passer à NHibernate 2 pour cela, la 1.2 n'offrait a priori pas un dialect suffisamment bon pour SQLite.
 
  J'en profite d'ailleurs, dans l'assemblée, qui a basculé sur la version 2 de NH ? pas de soucis particulier ?
  Car sur le site http://www.hibernate.org/343.html il ne propose que la v1.2, aussi, je me pose des questions.

  Olivier
--
Olivier DUVAL
http://olivier-duval.info

Frédéric Fadel

unread,
Nov 13, 2008, 7:23:35 AM11/13/08
to paris...@googlegroups.com
Bonjour,
 
Chez nous (Aspectize) on aime beaucoup le DataSet... et pour moi le DataSet ressemble à ta solution 2, certes il faut bosser un peu pour créer son schéma dynamiquement, mais une fois que c'est fait les échanges avec une base ou avec du XML deviennent magiques.
 
Fredy

2008/11/13 Julien Lavigne du Cadet <julien....@gmail.com>

Gauthier Segay

unread,
Nov 13, 2008, 3:08:20 PM11/13/08
to paris.alt.net
Olivier, de mon côté, j'utilise NHibernate2 par l'entremise
d'ActiveRecord sur 3 projets (2 pro, 1 perso, tous en prod) sans
problèmes particuliers (j'utilisais la v1.2 quand ActiveRecord en
dépendait).

Il est vrai que la communauté NH ne met pas forcément à jour la partie
downloads du site, mais si tu consulte la liste (nh-users) tu
trouveras beaucoup d'utilisateurs.

Pour revenir à la question de Julien, (petit disclaimer: je ne
pretends aucunement être expérimenté en DDD)

j'utilise principalement la première solution (oui c'est long) mais
voici quelques raisons:

- dans mon cas, je ne teste pas si NHibernate fonctione (je pars du
principe que oui) mais que la manière dont je l'utilise dans
l'application est ok (si mon application utilise sqlserver, je veux
que mes tests passent dessus)
- mes repositories se limitent à des opérations atomiques simples:
dans ma conception ils sont quasiment l' équivalent de la couche
d'accès aux données du modèle standard
- je limite la quantité de tests à ce niveau ou les choses sont
sensées fonctionner assez simplement après tout, en en renforçant à
l'issue de retours/bugs si nécéssaire.

d'autres tests se situent:
- au niveau de la couche services (ou l'on trouve un comportements
plus "domaine") auquel cas je mock la couche repository,
- au niveau de la couche mapping auquel cas j'utilise effectivement
sqlite en mémoire

pour le point 3, il n'a que peu d'intérêt dans mon cas, car au besoin
c'est le repository que je mock.

Enfin pour le PS, de mon côté je ne fais pas de lien entre repository
et DDD, les entités du mapping (utilisées par le repository) sont
toujours "anémiques" et proches du modèle relationel, ce n'est que si
j'ai besoin d'un domaine pour orchestrer/abstraire la persistence de
manière utile que je vais développer une couche dédiée qui ne
communiqueras pas directement avec les repository.

J'ai hâte d'en savoir plus sur vos modèles de conception concernant
repository et le reste :)

On Nov 13, 10:36 am, "DUVAL Olivier" <zork...@gmail.com> wrote:
> Bonjour tout seul,
>
>  Pour ma part, je suis en train de "tester" la solution 2, avec SQLite, avec
> une utilisation en mémoire de cette dernière. Le schéma est généré à chaque
> test (SchemaExport).
>  Cela fonctionne pas mal, mais j'ai dû passer à NHibernate 2 pour cela, la
> 1.2 n'offrait a priori pas un dialect suffisamment bon pour SQLite.
>
>   J'en profite d'ailleurs, dans l'assemblée, qui a basculé sur la version 2
> de NH ? pas de soucis particulier ?
>   Car sur le sitehttp://www.hibernate.org/343.htmlil ne propose que la
> v1.2, aussi, je me pose des questions.
>
>   Olivier
>
> Le 13 novembre 2008 09:53, Julien Lavigne du Cadet <julien.lavi...@gmail.com

Mathias Kluba

unread,
Nov 13, 2008, 5:22:29 PM11/13/08
to paris...@googlegroups.com
Salut!

Je n'ai pas encore testé la 2.0, car pour l'instant ça ne m'apporte rien
(j'ai vu des fonctionnalités intéressante, mais mon utilisation basique
suffit à ne pas les exploiter).
Et c'est vrai que c'est galère à trouver... pendant 2sec je me suis dit
"mais, ce n'est pas encore une beta??".... et va pour trouver l'info sur
Google (j'ai du passer par InfoQ qui m'a donner le lien sur le blog de
Ayende Rahien).

Moi aussi je mock mes DAO pour tester la couche métier.
Je n'ai pas pensé à l'utilisation de SQLLite, mais ça me semble une
bonne idée.
Ce qu'il manque en .Net, c'est l'équivalent du Java DBUnit...
Comme tu le dis, le but n'est pas de tester NHibernate ou même SQLite,
mais la requête de la DAO.
Dans DBUnit, on part du principe de DBUnit marche sans bug, et on créer
une "moke connexion" à laquelle on ajoute des données comme dans un
DataSet (addRow, etc.). Pour plus de lisibilité, on peut aussi
externaliser les données dans des CSV (connexion.AddData("nom_de_table",
monFichierCSV);). Partant de ce prédicat, tu peux tester ta DAO.

NHibernate utilise d'ailleurs un niveau d'abstraction au dessus de toute
connexion (pour ne pas dépendre de SQLLite ou autre) : IDbProvider. Ce
qui veut dire qu'il serait possible de "mocker" ce provider :
MockDbProvider.
Ceci dit, ça peut aussi devenir fastidieux, car il faudrait mocker aussi
IDbCommand, IDbConnection, IDbDataAdapter, etc.
De plus, cela requiert une bonne connaissance de NHibernate.

Ensuite, je suis fan de l'agile et du "on ne fait que ce qui est
nécessaire" (ok, c'est un peu fainéant comme philosophie).
Ce qui veut dire que si mes services ne font que relayer une méthode de
la DAO, pas besoin de test unitaire pour ça. Heureusement je n'ai pas de
NCover pour me gronder :)

Par contre, je ne comprend pas trop un truc : c'est une couche
supplémentaire les "Repositories" ?
Pour ma part, je suis plus orienté Domain Driven Design, et non Data. En
gros, si mon application n'a pas pour but final de manipuler des données
(contrairement à une appli de migration), si je me sert de la couche de
persistance SEULEMENT pour persister, je privilégie le modèle objet.
Donc les tables ressemblent au modèle, et non l'inverse.

En fait, je commence vraiment à être allergique à ceux qui résonnent
d'abord relationnel avant de faire le modèle objet... le relationnel
n'étant pas un but, mais un moyen de persister. Si on avait des bases de
données objets comme DB4O, on ne se poserait même pas la question.

Il est vrai par contre qu'on a des DTO pour des raisons techniques
(performance) et je comprend dans ce cas l'intérêt d'une couche
intermédiaire, et la nécessiter de faire du mapping Objet-Objet comme
Romain a eu besoin de faire...

(Désolé, je dérive souvent, et je viens de me rendre compte que je parle
plus de test unitaires :))

A+

Gauthier Segay a écrit :

Julien Lavigne du Cadet

unread,
Nov 19, 2008, 4:53:56 AM11/19/08
to paris.alt.net
Pour faire suite à la discussion, voila ce que j'ai finalement décidé
de faire :
http://www.thedotnetfrog.fr/2008/11/19/le-pattern-repository-testing-et-domain-driven-design/

Feedbacks are welcomed :-)

Julien.
> >>   Car sur le sitehttp://www.hibernate.org/343.htmlilne propose que la

DUVAL Olivier

unread,
Nov 19, 2008, 5:07:41 AM11/19/08
to paris...@googlegroups.com
Intéressant, article que je lirai à tête reposée.
En revanche, en attendant, tu utilises quelle technique pour avoir l'interface fluent pour les tests ? tellement plus lisible à lire ;)

 results.Count.ShouldEqual(2);
 results[0].Name.ShouldEqual("Product1");
 results[0].IsTopProduct.ShouldBeTrue();

OD-

Julien Lavigne du Cadet

unread,
Nov 19, 2008, 6:13:30 AM11/19/08
to paris.alt.net
J'utilise une version modifiée de Specunit-net, développé par Scott
Bellware: http://code.google.com/p/specunit-net/
Enfin Je ne suis pas encore passé au "Full BDD" donc en l'occurence
j'utilise uniquement cette classe à laquelle j'ai rajouté quelques
extensions : http://code.google.com/p/specunit-net/source/browse/trunk/src/SpecUnit/SpecificationExtensions.cs

Julien

On 19 nov, 11:07, "DUVAL Olivier" <zork...@gmail.com> wrote:
> Intéressant, article que je lirai à tête reposée.
> En revanche, en attendant, tu utilises quelle technique pour avoir
> l'interface fluent pour les tests ? tellement plus lisible à lire ;)
>
>  results.Count.ShouldEqual(2);
>  results[0].Name.ShouldEqual("Product1");
>  results[0].IsTopProduct.ShouldBeTrue();
>
> OD-
>
> Le 19 novembre 2008 10:53, Julien Lavigne du Cadet <julien.lavi...@gmail.com
>
>
>
> > a écrit :
>
> > Pour faire suite à la discussion, voila ce que j'ai finalement décidé
> > de faire :
>
> >http://www.thedotnetfrog.fr/2008/11/19/le-pattern-repository-testing-...
> > > >>   Car sur le sitehttp://www.hibernate.org/343.htmlilnepropose que la

Gauthier Segay

unread,
Nov 19, 2008, 4:48:13 PM11/19/08
to paris.alt.net
Le problème est très bien posé.

Sur le point suivant:
"Hors cela peut être problématique du point de vue du domaine si l'on
veut par exemple interdire de supprimer une entité!"

c'est à cause de cela que je ne veux pas exposer les repository à des
classes trop "hautes" (proches du usecase) dans l'architecture
applicative, dans mon cas je parle alors de services applicatifs/
domaines (IProductListingService) car le ProductRepository va vite
avoir beaucoup de responsabilités de par son nom trop "générique".

Mais ce n'est qu'une histoire de termes entre nos deux conceptions: le
product repository dans ton exemple est un service particulier dans
mon cas.

Dans ma conception, le repository est perçu comme le "réducteur de
code" de la couche DAL et moyen d'abstraire l'ORM éventuellement
utilisé, il reste quand même bien pratique d'avoir le polymorphisme à
dispo avec une implémentation générique pour certains points "cross-
concerns" (GetByKey)

La question étant alors: le terme repository n'est-il pas galvaudé?

On Nov 19, 10:53 am, Julien Lavigne du Cadet
<julien.lavi...@gmail.com> wrote:
> Pour faire suite à la discussion, voila ce que j'ai finalement décidé
> de faire :http://www.thedotnetfrog.fr/2008/11/19/le-pattern-repository-testing-...
> > >>   Car sur le sitehttp://www.hibernate.org/343.htmlilnepropose que la
Reply all
Reply to author
Forward
0 new messages