BDD externe (avec Specflow)

Je suis nouveau sur BDD, mais je l’ai trouvé très intéressant et je souhaite développer mon prochain projet en utilisant BDD. Après avoir googlé et regardé des screencasts, j’ai encore beaucoup de questions sur BDD dans la vraie vie.

1. Scénarios déclaratifs ou impératifs?

La plupart des scénarios donnés-alors-que j’ai vus ont été écrits en termes d’interface utilisateur (impératif).

Scenario: Login Given I am on the Login-page When I enter 'AUser' in the textbox 'UserName' And I enter 'APassword' in the textbox 'Password' And I click the 'Login' button Then I should see the following text 'You are logged in' 

J’ai trouvé ces tests extrêmement fragiles et ils ne disent rien sur la valeur métier de cliquer sur des boutons. Je pense que son cauchemar à maintenir. Pourquoi la plupart des exemples utilisent des scénarios impératifs?

 Scenario: Login (declarative) Given I am not logged in When I log in using valid credentials Then I should be logged in 

Si vous préférez le style déclaratif, comment décrivez-vous des choses comme «page d’accueil» ou «page de produits»?

  • Astuces pour écrire de bonnes spécifications

2. Exercice ou non de l’interface utilisateur?

La plupart des implémentations d’étapes que j’ai vues ont utilisé WatiN, White ou quelque chose du genre pour implémenter des scénarios du sharepoint vue de l’utilisateur. Démarrer le navigateur en cliquant sur les boutons. Je pense que c’est extrêmement lent et fragile. Eh bien, je peux utiliser quelque chose comme object page pour rendre les tests moins fragiles. Mais c’est une autre quantité de travail. Surtout pour les applications de bureau avec interface utilisateur complexe.

Comment implémentez-vous des scénarios dans des projets réels – exercice de l’interface utilisateur ou via des contrôleurs / présentateurs de test?

  • Meilleur moyen d’appliquer BDD

3. Base de données réelle ou non?

Lorsqu’une partie donnée du scénario est mise en œuvre, il faut souvent que certaines données soient dans le système (par exemple, certains produits pour une application en magasin). Comment implémentez-vous cette partie – en ajoutant des données à une firebase database réelle (test complet de bout en bout) ou en fournissant des stubs de référentiel aux contrôleurs?

En attente de réponses expérimentées!

MISE À JOUR: Ajout de liens utiles sur les questions.

    1. Déclarer est la bonne façon, OMI. Si vous parlez de noms de fichiers .aspx, vous le faites mal. Le but de l’histoire est de faciliter la communication entre les développeurs et les non-développeurs. Les non-développeurs ne se soucient pas des produits.aspx, ils se soucient d’une liste de produits. Votre système fait quelque chose que les non-développeurs trouvent utile. C’est ce que vous essayez de capturer.

    2. Les histoires racontent les fonctionnalités de haut niveau que vous devez implémenter. C’est ce que votre système doit faire. La seule façon de vraiment savoir si vous avez fait cela est d’exercer l’interface utilisateur. Les histoires BDD SpecFlow ne remplacent pas les tests unitaires, ce sont plutôt des tests d’intégration. Si vous brisez cela, vous avez brisé la valeur de votre logiciel. Les tests unitaires sont des détails d’implémentation dont vos utilisateurs ne se soucient pas, et ils ne testent chaque élément que de manière isolée. Cela ne peut pas vous dire si A et B travaillent ensemble tout le temps (en théorie, cela devrait, en pratique, faire des choses intéressantes [lire: inattendues] lorsque les deux parties se jouent ensemble). Des tests automatisés de bout en bout peuvent également vous aider avec votre assurance qualité. Si un domaine fonctionnel se brise, vous le savez et ils peuvent passer leur temps dans d’autres domaines de l’application tout en déterminant ce qui a interrompu les tests d’intégration.

    3. C’est un problème délicat. Nous avons adopté une approche hybride. Nous utilisons la firebase database (intègrons les tests après avoir testé le système comme un élément plutôt que les composants individuels), mais plutôt que de réinitialiser les configurations tout le temps, nous utilisons Deleporter pour remplacer nos référentiels lorsque cela est nécessaire. Semble fonctionner correctement, mais il y a certainement des avantages et des inconvénients de toute façon. Je pense que nous sums encore en train de comprendre cela en grande partie.

    Edit : J’ai trouvé cet article en train de décrire le concept de se limiter à ne parler que de domaines spécifiques pour éviter les scénarios fragiles .

    Son principal point est que le nombre minimum de domaines dont vous pouvez parler est le domaine problématique et le domaine de la solution. Si vous parlez de quelque chose en dehors de ces deux domaines, vous impliquez trop de parties prenantes, vous introduisez trop de bruit et vous fragilisez vos scénarios.

    Il mentionne également un modèle absolu «déclaratif» ou «impératif» étant un mythe. Il parle d’un modèle cognitif appelé “chunking”, en disant qu’à n’importe quel niveau de votre abstraction, vous pouvez “chunk up” ou “chunk down”. Cela signifie que vous pouvez obtenir plus explicite (comment?) Ou plus de méta (quoi ou pourquoi?). Vous reprenez un modèle impératif en demandant “qu’est-ce qu’on fait?” Vous dites “Comment allons-nous faire ça?” Je suppose donc que je ne serais pas trop accro à la déclaration par rapport à l’impératif – cela ne vous mènera nulle part ailleurs dans ce problème.

    Ce qui vous mènera quelque part est de déterminer dans quels domaines appartient chaque terme, peut-être en identifiant quel acteur est l’expert du domaine auquel appartient ce terme. Une fois que vous avez identifié tous les domaines, vous pouvez choisir des termes associés. des domaines les plus importants du scénario, ou supprimer complètement les déclarations non adaptées. Si cela ne suffit pas, vous pouvez diviser, préciser davantage ou déplacer le scénario pour qu’il réponde à ces exigences.

    BTW, il utilise également le scénario de connexion sur une interface utilisateur, donc vous avez des conseils concrets 🙂

    Avant la modification : (une partie de ceci s’applique toujours. Les questions “DB ou pas de firebase database” et “Interface utilisateur ou pas d’interface utilisateur” ne sont pas liées)

    1 – Scénarios déclaratifs ou impératifs?

    Déclarez quand vous le pouvez, bien que l’impératif ait une certaine valeur (à certains moments du cycle de vie d’un projet).

    L’impératif est un moyen plus simple de penser aux testeurs et aux analystes commerciaux qui ne sont pas aussi familiarisés avec la théorie et la conception de l’information. Il est également plus facile de réfléchir plus tôt dans un projet avant de définir votre domaine de problème et vos stream de travail. Cela peut être utile pour la reflection exploratoire.

    La déclaration est moins susceptible de changer avec le temps. Comme une interface graphique est la partie d’une application la plus sujette au désabonnement, c’est extrêmement précieux. Il est plus facile de réfléchir une fois que vous avez défini votre domaine de problème et vos stream de travail, et que vous vous concentrez davantage sur les concepts relationnels. C’est un modèle plus stable et plus généralement applicable.

    Si vous écrivez des scénarios de test avec un modèle générique et déclaratif, vous pouvez les implémenter en combinant l’automatisation complète de l’interface utilisateur de l’application, des tests d’intégration ou des tests unitaires.

    Comment décrivez-vous des choses telles que «Page d’accueil» ou «Produits»?

    Je ne suis pas sûr que je le ferais au niveau de base des fonctionnalités et des exigences. Vous pouvez créer des sous-fonctionnalités et des sous-exigences décrivant les détails de l’implémentation, comme des stream de travail d’interface utilisateur spécifiques. Si vous décrivez une partie d’une interface utilisateur, vous devez alors définir une fonctionnalité / exigence d’interface utilisateur.

    2 – Exercice ou non?

    Tous les deux.

    Je pense que c’est extrêmement lent et fragile

    Oui, ça l’est. Effectuez chaque scénario / exigence de haut niveau avec l’interface utilisateur et l’intégration complète de la firebase database, mais n’exercez pas chaque chemin de code avec une automatisation de bout en bout de l’interface utilisateur, et certainement pas des cas limites. Si vous le faites, vous passerez plus de temps à les faire fonctionner, et beaucoup moins de temps à tester votre application.

    Vous pouvez structurer votre application pour pouvoir effectuer des tests d’intégration à moindre coût, y compris des tests basés sur une interface utilisateur. Les tests unitaires sont également précieux.

    Mais moins vous faites de tests d’intégration, plus vous allez manquer de bogues. Il peut être plus facile d’écrire des tests unitaires, et ils seront certainement moins fragiles, mais vous allez tester moins votre application, par définition.

    3 – Base de données réelle ou non?

    Tous les deux.

    Des tests d’intégration de bout en bout de haut niveau doivent être effectués avec le système complet en place. Cela inclut une vraie firebase database, exécutant vos tests avec chaque système sur un serveur différent, etc.

    Plus le niveau est bas, plus je préconise les objects fictifs.

    • Les tests unitaires ne doivent tester que des classes individuelles
    • Les tests d’intégration de niveau intermédiaire doivent éviter les dépendances coûteuses, fragiles et impactantes telles que le système de fichiers, les bases de données, le réseau, etc. Essayez de tester l’implémentation de ces dépendances fragiles et impactantes avec des tests unitaires et des tests de bout en bout.

    Au lieu de mentionner une page par son nom, décrivez ce qu’elle représente, par exemple

     Scenario: Customers logs in successfully When I log in Then I should see an overview of ACME's top selling products 

    Vous pouvez tester directement les API ou les modèles sous-jacents, mais plus vous le faites, plus vous risquez de ne pas rencontrer de problème d’intégration. Une approche consiste à équilibrer les choses avec un petit nombre de tests de stack complète, et un nombre plus important qui teste entre deux couches uniquement.