Comment écrire un script pour créer des fixtures?

Bonjour,

J’aimerais créer des fixtures pour une centaine d’utilisateurs.
Comment est-ce que je suis censé le faire ?
à la main fixture par fixture dans le fichier yml (j’espère pas !)
dans un script mis dans une rake task (si oui cela ressemble à
quoi ?)
dans un script copier/coller dans la ligne de commande
aprèsunscript/console test
dans une migration
dans un test (integration, mock, unit ?)

Voilà, j’aimerais connaître la bonne pratique “officielle” pour
exécuter du code qui crée des données de test. Merci de votre aide

H

Tu peux mettre du ruby dans tes fixtures exactement comme tu peux en
mettre
dans tes vues.

Exemple :

<% (1…100).each do |user_id| %>
user_<%= user_id %>:
name: user_<%= user_id %>
password: password_<%= user_id %>
<% end %>

C’est un exemple très très simple, parce que, si, par exemple, tu veux
que
tes fixtures soient plus “sexy” et ne se ressemblent pas à un numéro
près,
rien ne t’empêche de faire (par exemple) des tableaux de données que tu
peux
attribuer aléatoirement, etc.

Je fais fréquemment ça pour avoir des données “sexy” pour montrer à mes
clients / utilisateurs finaux comment se comporte l’appli dans des
situations crédibles.

En espérant que ça te sors d’embaras…


Michel B.

Merci. Effectivement, je ne savais pas que je pouvais mettre du ruby
dans les fixtures.
Ceci dit, je préfèrerais un simple script ruby du style :
(1…100).each do |user_id|
User.new(:id => user_id, :name => “user”+user_id)
end
Aujourd’hui je peux mettre ça dans du code de test mais cela ne parait
pas bien propre vu que cela devrait être relancé pour chaque test
alors que les fixtures ne sont chargées qu’une fois au lancement de la
batterie de tests (si je ne m’abuse).

Je préfère du code seul parce que cela me parait plus simple à
debugger, et parce que je peux l’exécuter directement à la console si
je veux tester une syntaxe.
J’ai une chance d’y arriver en exécutant un script où je dois passer
par le yml ? (Rq je px toujours faire un script ruby qui génère le
yml, grâce à la méthode to_yaml, mais bon ça me parait un peu tiré par
les cheveux)

H

On Aug 21, 8:54 pm, “Michel B.” [email protected]

Si c’est un problème d’exécuter à la console, je ne vois pas vraiment la
différence entre un rake db:fixtures:load en ligne de commande et un
chargement console.

Perso je ne vois pas tellement ce qu’il y aurait à débugger dans une
fixture, mais si il faut débugger rake prend une option --trace qui te
permet d’obtenir la trace ruby complète de l’erreur.

Par contre, si tu veux que tes fixtures passent par ton objet métier,
effectivement les fixtures ne sont pas ce qu’il te faut, puisque les
fixtures sont mappées directement sans passer par les objet métier.

Dans ce dernier cas, je suggère effectivement un script ruby, peut-être
une
tâche rake spécifique, que tu pourrais mettre dans un plugin, et qui
mapperais sur des fichiers en ruby pur comme tu préfère, et qui
prendrais
sensiblement les mêmes options que db:fixtures:load.

Ceci dit, essaye peut-être d’abord d’utiliser les fixtures yml, ne
serait-ce
que pour voir si tu ne risque pas de développer quelque chose qui existe
déjà comme tu en as besoin mais que tu n’en a pas encore consience.

Si tu choisis la dernière solution, donne des nouvelles ici, et publie
peut-être le plugin, ça peut intéresser d’autres que toi qui aimeraient
la
même chose…

Cordialement.


Michel B.

Harry S. a écrit, le 08/21/2008 09:30 PM :

C’est un peu plus compliqué que ça. Si tu utilises
self.use_transactional_fixtures = true
avec une base de données qui supporte les transactions, pour chaque
catégorie de test (techniquement chaque instance de la classe
implémentant les tests d’un model ou d’un contrôleur par exemple) les
fixtures ne sont effectivement chargées qu’une fois à la création de
l’instance, une transaction est ensuite utilisée pour chaque test et un
ROLLBACK effectué à la fin du test.
Si ce n’est pas le cas, les fixtures sont chargées au début de chaque
test.

Lionel

@Michel,
Oui j’aimerais utiliser le code métier. A priori cela me semble éviter
de la redondance. En y réfléchissant, ce que j’imagine est assez
proche d’une migration où on entre des données initiales. Les fixtures
seraient alors des migrations utilisées seulement par l’environnement
de test (via la commande
rake db:migrate RAILS_ENV=test par exemple). Le fonctionnement est
alors très proche du plugin que tu décris.
Mais comme tu dis avant de coder ce genre de chose je vais déjà
utiliser ce qui existe et notamment ta première proposition.

@Lionel
Dans test_helper j’ai bien self.use_transactional_fixtures = true
(paramètre par défaut, j’y ai jamais touché.). J’utilise MySQL.
Supporte-t-elle les transactions ? Auquel cas je suis bien dans le cas
que tu cites. Merci pour l’info.

@Tous
Et vous comment faites-vous pour générer et charger 100+ fixtures ?

H

On Aug 21, 9:48 pm, Lionel B. [email protected]

2008/8/21 Harry S. [email protected]:

@Tous
Et vous comment faites-vous pour générer et charger 100+ fixtures ?

L’utilisation de fixture fait presque débat. En effet, pour permettre
d’avoir des test rapide, il est actuellement conseillé d’utilisé des
Mock pour les test fonctoinnels. En conséquence, les fixtures ne
servent presque que pour les test unitaires. Dans ce cas il est
rarement nécessaire d’avoir autant de fixtures. Personnelement, je les
crée au fur et à mesure en fonction de mes besoins durant les tests.


Cyril M.

L’utilisation de fixture fait presque débat. En effet, pour permettre
d’avoir des test rapide, il est actuellement conseillé d’utilisé des
Mock pour les test fonctoinnels. En conséquence, les fixtures ne
servent presque que pour les test unitaires. Dans ce cas il est
rarement nécessaire d’avoir autant de fixtures. Personnelement, je les
crée au fur et à mesure en fonction de mes besoins durant les tests.

Utiliser les mock, c’est bien pour tester les contrôleurs, mais pour les
tests unitaires ce serait un peu con de mocker la classe que l’on veut
valider, et ne serait-ce que pour tester les validates_presence_of ou
assimilés les fixtures sont utiles.

Ensuite, leur utilité pour pré-remplir la base me semble avérée, surtout
quand on travail à des refontes de systèmes existants où on a des
données
bien réelles d’une base de données de production à intégrer, ce serait
dommage de s’en priver.

@Tous
Et vous comment faites-vous pour générer et charger 100+ fixtures ?

Personnellement je passe par des datasets (dump de la base de
données). A chaque test il se passe les choses suivantes :

  • drop database
  • create database
  • load dataset
  • reindex solr

Je vois les inconvénients suivants :

  • ca ralentit mes tests : 47s pour “75 examples, 0 failures”.
  • je teste moins précisemment la dépendance de mes objets aux
    données.

J’ai tout de même choisi cette solution car :

  • Certaines de mes tables et models sont créés à la volée et ne
    peuvent donc pas utiliser les fixtures.
  • Ca m’évite d’écrire et de maintenir un jeu de données pour chaque
    test: c’est presque le même pour tout le monde !
  • J’utilise solr. Si j’utilisais les fixtures je devrais faire des
    stub ou mock.
  • Probablement aussi car je suis débutant dans le TDD.

Mais je vais progressivement passer aux ‘factories’. C’est un peu de
travail pour définir les données dont chaque test a besoin, mais
çapaliera les inconvenients cités.
Peut-être qu’ensuite je passerai aux mock !

Enfin, pour info il existe au moins un plugin qui crée automatiquement
les fixtures à partir de la base de données.
Tout cela ne fait finalement que reporter le problème posé au
chargement de données dans la base. Mais en général tout de même c’est
plus pratique.

@harry
J’ai rempli ma base avec un script custom qui prend les données dans
des fichiers existants.
Puis je crée mon dataset avec :
rake db:dataset:dump DATASET=datasetname RAILS_ENV=test
Pour executer les commandes (drop database create database load
dataset,
etc.) dans mes tests, j’ai copié le code des tâches rake
correspondantes pour en faire de simples méthodes. Ces méthodes
prennent en argument le dump que je veux utiliser.

@sounka: OK Merci pour ces infos !

OK va falloir que je regarde plus précisément les pattern de test vu que
mes connaissances s’arrêtent sur le AWDWR. Pour moi les mocks c’est
juste pour simuler du code non exécutable en test (par exemple les
transactions financières)…
Philosophiquement je ne sais pas si je suis en train de faire un test
unitaire ou fonctionnel? A priori c’est plutôt un test unitaire. Je veux
tester des calculs comme une évolution temporelle de nombre de
commentaires pour un billet de blog donné. Pour tester ça, j’aimerais
avoir dans ma db 100 utilisateurs qui ont laissé 1 commentaire sur 1
post sur une période de 6 mois. Ici le test porte sur le calcul pas sur
le reste.

@Sounka Ta méthode m’a l’air pratique. J’ai quelques questions :
Avant de faire un dump de la DB comment l’as tu créée ? (A partir de la
db de prod,dev test ?) Tu l’as créée à partir de 0 avec du code métier ?
Les différentes commandes (drop database create database load dataset,
etc.) sont exécutées comment (tâche rake ?) Comment dire à Rails de
charger un dump particulier avant un test particulier ?

sounka wrote:

@Tous
Et vous comment faites-vous pour g�n�rer et charger 100+ fixtures ?

Personnellement je passe par des datasets (dump de la base de
donn�es). A chaque test il se passe les choses suivantes :

  • drop database
  • create database
  • load dataset
  • reindex solr

Je vois les inconv�nients suivants :

  • ca ralentit mes tests : 47s pour “75 examples, 0 failures”.
  • je teste moins pr�cisemment la d�pendance de mes objets aux
    donn�es.

J’ai tout de m�me choisi cette solution car :

  • Certaines de mes tables et models sont cr��s � la vol�e et ne
    peuvent donc pas utiliser les fixtures.
  • Ca m’�vite d’�crire et de maintenir un jeu de donn�es pour chaque
    test: c’est presque le m�me pour tout le monde !
  • J’utilise solr. Si j’utilisais les fixtures je devrais faire des
    stub ou mock.
  • Probablement aussi car je suis d�butant dans le TDD.

Mais je vais progressivement passer aux ‘factories’. C’est un peu de
travail pour d�finir les donn�es dont chaque test a besoin, mais
�apaliera les inconvenients cit�s.
Peut-�tre qu’ensuite je passerai aux mock !

Enfin, pour info il existe au moins un plugin qui cr�e automatiquement
les fixtures � partir de la base de donn�es.
Tout cela ne fait finalement que reporter le probl�me pos� au
chargement de donn�es dans la base. Mais en g�n�ral tout de m�me c’est
plus pratique.

@Sounka, tu parlais des factories. Comme je viens d’en réentendre parler
sur
http://www.rubyinside.com/whats-hot-on-github-august-2008-1091.html
via factory_girl, je peux te demander plus d’infos dessus ? Tu pensais Ã
ce plugin factory_girl ou il y a d’autres plugins ?

@Tous, Avez-vous des retours sur les factories et en particulier
factory_girl ?

H