Salut,
Je viens faire un point avec vous, j'ai réussi à créé des tests d'intégration pour Solr après plusieurs dizaines d'heures de galère. Je ne vais pas vous décrire l'épopée de l'écriture des tests mais juste faire le point sur ses fameux tests pour avoir un retour sur le travail fait.
Introduction
Pour l'instant, un seul test a été écrit mais l'architecture est en place, le test est déjà passé sous le joug de Travis. Ce qui constitue la bonne nouvelle.
Je vais m'attarder un peu sur comment sont fait les tests pour bien cibler les problématiques que j'ai rencontré.
Je vois bien qu'on suit pas au fond de la classe, un petit rappel de vocabulaire rapide (pas tout à fait exact mais qui donne l'idée):
-
Solr: Le moteur d'indexation. C'est lui qui est chargé d'indexer le contenu et qui fait la recherche. On l'utilise jamais directement dans le code. La version 5 apporte beaucoups de changements, la migration pourrait se faire dans quelques semaines.
-
Haystack: La librairie python utilisé, pour l'indexation du contenu. C'est ça, qu'on utilise partout dans le code. Haystack est utile car il nous permet de rester indépendant du moteur d'indexation et de la version du moteur. Haystack appel la librairie PySolr (qui appel Solr) pour indexer les contenus et pour faire la recherche. C'est juste une surcouche. En gros, Haystack (utilisé dans le code) => PySolr => Solr.
-
schema.xml: indispensable dans la version 4 (l'actuelle), inutile dans la version 5. C'est un fichier XML qui décrit les champs et les types des valeurs indexés. C'est généré par une commande Django.
-
PySolr: La librairie python utilisé par Haystack pour faire appel à Solr. On ne l'utilise pas directement.
Après cette courte présentation, comment est organisé le code, est la grande question.
Du code, des tests /o/
Pour l'instant, deux classes ont été créés:
C'est une classe que devront hériter tous les tests qui concernent les tests d'indexation. Cette classe fait une 50 lignes. Elle est situé dans le fichier zds/utils/test_testing_tools.py.
Cette classe utilise le principe des 'core' (la seule personne que je connaisse qui utilise cette techno appelle ça des 'cœurs' mais bon) dans Solr. Un 'core', c'est tous simplement un index (c'est à dire des fichiers indexés), des logs, un schema.xml et des fichiers de configuration . Chaque core à son index, ce qui va nous permettre dans nos tests ne de ne pas écraser les index (les fichiers indexés) des développeurs (C'est pas drôle, je sais ^^). À chaque test, on créé un 'core', avec sa configuration et un nom généré aléatoirement. On lance les tests dans celui-ci et on le détruit à la fin (oui, le 'cœur' est détruit :p).
La création des core est réalisé grâce à l'API REST de Solr. Cette API à plusieurs limitations, tout d'abord, on ne peut pas créer de 'core' sans préciser la configuration (du core). C'est pourquoi on doit stocker toute la configuration du 'core'. De plus, l'API impose une autre limitation, la configuration doit-être présente dans le futur dossier du core (dans le dossier d'installation d'installation de solr/example/solr/nom du core). C'est pourquoi on est obligé de remplir un paramètre avec le chemin vers l'installation de Solr pour pouvoir copier les fichiers de configuration dans le bon dossier.
L'API rest de Solr est appelé pour supprimer le core à la fin.
C'est le fichier qui fait réellement le test. Pas grand chose à dire, toute la partie difficile est dans l'autre fichier, un extrait : le but est de créé un post et vérifier qu'il à bien été indexé.
1 2 3 4 5 6 7 8 9 | # Clear index call_command('clear_index', verbosity=0, interactive=False, commit=True) # Create some post PostFactory(topic=self.topic, author=self.user, position=2) # Index them call_command('rebuild_index', verbosity=0, interactive=False, commit=True) self.assertEqual(SearchQuerySet().count(), 2) |
Ce qui est bien, c'est qu'on a pas de dépendance dans les tests autre que Haystack.
Les autres fichiers
Le dossier contenant la config du core par défaut. est ici.
Le script permettant de télécharger et d'installer solr est disponible ici. J'ai aussi modifié le .travis.
Ce qui peut poser des soucis
-
La classe
SolrTestCase
est dépendante de l'api rest de Solr et plus généralement des versions de Solr. Les autres classes de tests ne sont pas dépendante de Solr mais uniquement de Haystack. Sachant que la classeSolrTestCase
devra bouger avec Solr 5. La migration sur Solr 5 pourrait se faire, quand la PR de migration de Solr 5 dans Haystack sera accepté (dans environ quelques semaines). Une question se pose donc: on attend Solr 5 pour les tests ou on fait ça maintenant ? -
On est obligé de sauvegarder la configuration d'un core, ça fait quelques fichiers à stocker: une dizaine qu'il va falloir mettre à jours. Je pense pas qu'il change tous les jours non plus. Pour moi, on ne peut pas faire confiance à la configuration de l'utilisateur de toute manière ^^. Cette limitation disparaît avec Solr 5, on peut dire à Solr de charger les fichiers par-défaut (on me l'a dit à l'oral à vérifier).
-
Obliger de préciser ou est situé le dossier d'installation de Solr.
-
À cause d'une limitation de Solr, on ne peut pas recharger le schema.xml d'un core sans redémarrer Solr. Un bug peut apparaître si par malheur, on ré-utilise le même noeud en changeant le schema.xml. Mais y'a quasiment aucune chance que ça se produise. Si un mathématicien veut faire une loi de Poisson, pour savoir combien de chance, on a. Cette limitation disparaît avec Solr 5.
-
Les temps de build travis sont allongés du au temps de téléchargement de Solr (en moyenne une 40 secondes).
Ce qui est cool
- Les tests unitaires ne sont dépendant que de Haystack (sauf la classe
SolrTestCase
) - Pas de nouvelle dépendance
- Si on a pas Solr, les tests passe quand même.
- Automatisé, juste à remplir une constante, le chemin d'installation de Solr, lancer Solr et les tests peuvent s’exécuter.
Annexe : - La branche - Le build de travis