database - une - stratégie de communication application mobile




Quelle est la meilleure stratégie pour tester des applications pilotées par des bases de données? (4)

Je travaille avec beaucoup d'applications web qui sont pilotées par des bases de données de complexité variable sur le backend. Généralement, il existe une couche ORM distincte de la logique métier et de présentation. Cela rend la mise à l'essai de la logique métier assez simple; les choses peuvent être mises en œuvre dans des modules discrets et toutes les données nécessaires pour le test peuvent être truquées par le biais de l'objet moqueur.

Mais tester l'ORM et la base de données elle-même a toujours été source de problèmes et de compromis.

Au fil des années, j'ai essayé quelques stratégies, dont aucune ne m'a complètement satisfait.

  • Charger une base de données de test avec des données connues. Exécutez des tests sur l'ORM et confirmez que les bonnes données reviennent. L'inconvénient est que votre base de données de test doit suivre les modifications de schéma dans la base de données de l'application et peut être désynchronisée. Il s'appuie également sur des données artificielles, et ne peut pas exposer les bogues qui se produisent en raison de la saisie stupide de l'utilisateur. Enfin, si la base de données de test est petite, elle ne révélera pas d'inefficacité comme un index manquant. (OK, ce dernier n'est pas vraiment ce que les tests unitaires devraient être utilisés, mais ça ne fait pas de mal.)

  • Chargez une copie de la base de données de production et testez-la. Le problème ici est que vous n'avez aucune idée de ce qui se trouve dans la base de données de production à un moment donné; vos tests devront peut-être être réécrits si les données changent au fil du temps.

Certaines personnes ont fait remarquer que ces deux stratégies reposent sur des données spécifiques et qu'un test unitaire ne devrait tester que les fonctionnalités. À cette fin, j'ai vu suggéré:

  • Utilisez un serveur de base de données simulé et vérifiez uniquement que l'ORM envoie les requêtes correctes en réponse à un appel de méthode donné.

Quelles stratégies avez-vous utilisées pour tester les applications pilotées par base de données, le cas échéant? Qu'est-ce qui a fonctionné le mieux pour vous?


J'ai effectivement utilisé votre première approche avec un certain succès, mais d'une manière légèrement différente qui, je pense, résoudrait certains de vos problèmes:

  1. Conservez le schéma entier et les scripts pour le créer dans le contrôle de source afin que tout le monde puisse créer le schéma de base de données en cours après une extraction. En outre, conservez des exemples de données dans les fichiers de données chargés par une partie du processus de génération. Lorsque vous découvrez des données qui provoquent des erreurs, ajoutez-les à vos exemples de données pour vérifier que les erreurs ne réapparaissent pas.

  2. Utilisez un serveur d'intégration continue pour créer le schéma de base de données, charger les exemples de données et exécuter des tests. C'est ainsi que nous maintenons la synchronisation de notre base de données de test (en la reconstruisant à chaque test). Bien que cela nécessite que le serveur CI ait accès à sa propre instance de base de données, je dis que le fait que notre schéma db soit construit 3 fois par jour a considérablement aidé à trouver des erreurs qui n'auraient probablement pas été trouvées avant la livraison. ). Je ne peux pas dire que je reconstruis le schéma avant chaque commit. Est-ce que quelqu'un? Avec cette approche vous ne devrez pas (bien peut-être que nous devrions, mais ce n'est pas un gros problème si quelqu'un oublie).

  3. Pour mon groupe, l'entrée de l'utilisateur est effectuée au niveau de l'application (pas à la base de données), donc cela est testé via des tests unitaires standard.

Chargement de la copie de la base de production:
C'est l'approche qui a été utilisée lors de mon dernier emploi. Ce fut une cause de douleur énorme de quelques problèmes:

  1. La copie sortirait de la version de production
  2. Des modifications seront apportées au schéma de la copie et ne seront pas propagées aux systèmes de production. À ce stade, nous aurions des schémas divergents. Pas drôle.

Serveur de base de données moqueur:
Nous faisons aussi cela à mon travail actuel. Après chaque validation, nous exécutons des tests unitaires sur le code de l'application qui a injecté des accesseurs mock db. Puis, trois fois par jour, nous exécutons la construction db complète décrite ci-dessus. Je recommande définitivement les deux approches.


J'exécute toujours des tests sur un DB en mémoire (HSQLDB ou Derby) pour les raisons suivantes:

  • Cela vous fait penser aux données à conserver dans votre base de données de test et pourquoi. Transporter simplement votre DB de production dans un système de test se traduit par "Je n'ai aucune idée de ce que je fais ou pourquoi et si quelque chose casse, ce n'était pas moi !!" ;)
  • Il s'assure que la base de données peut être recréée avec peu d'effort dans un nouvel endroit (par exemple quand nous avons besoin de répliquer un bug depuis la production)
  • Cela aide énormément avec la qualité des fichiers DDL.

Le DB en mémoire est chargé avec de nouvelles données une fois les tests démarrés et après la plupart des tests, j'appelle ROLLBACK pour le garder stable. TOUJOURS garder les données dans la base de données de test stable! Si les données changent tout le temps, vous ne pouvez pas tester.

Les données sont chargées depuis SQL, un template DB ou un dump / backup. Je préfère les dumps s'ils sont dans un format lisible parce que je peux les mettre dans VCS. Si cela ne fonctionne pas, j'utilise un fichier CSV ou XML. Si je dois charger d'énormes quantités de données ... je ne le fais pas. Vous n'avez jamais à charger d'énormes quantités de données :) Pas pour les tests unitaires. Les tests de performance sont un autre problème et des règles différentes s'appliquent.


Je pose cette question depuis longtemps, mais je pense qu'il n'y a pas de solution miracle pour cela.

Ce que je fais actuellement, c'est se moquer des objets DAO et garder une représentation en mémoire d'une bonne collection d'objets qui représentent des cas intéressants de données qui pourraient vivre sur la base de données.

Le problème principal que je vois avec cette approche est que vous ne couvrez que le code qui interagit avec votre couche DAO, mais jamais le DAO lui-même, et dans mon expérience je vois que beaucoup d'erreurs se produisent aussi sur cette couche. Je garde également quelques tests unitaires qui s'exécutent sur la base de données (pour utiliser localement TDD ou quick testing), mais ces tests ne sont jamais exécutés sur mon serveur d'intégration continue, car nous ne conservons pas de base de données dans ce but. pense que les tests qui s'exécutent sur le serveur CI doivent être autonomes.

Une autre approche que je trouve très intéressante, mais qui ne vaut pas toujours puisque c'est un peu long, est de créer le même schéma que vous utilisez pour la production sur une base de données intégrée qui fonctionne uniquement dans le test unitaire.

Même s'il ne fait aucun doute que cette approche améliore votre couverture, il y a quelques inconvénients, car vous devez être aussi proche que possible d'ANSI SQL pour le faire fonctionner à la fois avec votre SGBD actuel et le remplacement intégré.

Peu importe ce que vous pensez être le plus pertinent pour votre code, il existe quelques projets qui peuvent le rendre plus facile, comme DbUnit .


Pour un projet basé sur JDBC (directement ou indirectement, par exemple JPA, EJB, ...), vous pouvez créer une maquette non de la base de données complète (dans ce cas, il serait préférable d'utiliser un DB de test sur un SGBD réel). .

L'avantage est l'abstraction qui vient avec, puisque les données JDBC (ensemble de résultats, compte de mise à jour, avertissement, ...) sont les mêmes quel que soit le backend: votre db de production, un db de test ou juste quelques données de maquette fournies pour chaque test Cas.

Avec la connexion JDBC simulée pour chaque cas, il n'est pas nécessaire de gérer le test db (nettoyage, un seul test à la fois, rechargement des appareils, ...). Chaque connexion de maquette est isolée et il n'est pas nécessaire de nettoyer. Dans chaque cas de test, seules les configurations minimales requises sont fournies pour simuler l'échange JDBC, ce qui permet d'éviter la complexité de la gestion d'un db de test complet.

Cadre Acolyte comprend un pilote JDBC et utilitaire pour ce genre de maquette: http://acolyte.eu.org .







mocking