La réponse rapide
Un très important point à soulever est qu'il y a deux variantes du développement guidé par le comportement. Les deux saveurs sont xBehave y xSpec .
xBehave BDD : SpecFlow
SpecFlow (très similaire à concombre de la pile Ruby) est excellent pour faciliter les tests xBehave BDD en tant que critères d'acceptation. Il ne fournit cependant pas un bon moyen d'écrire des tests comportementaux au niveau de l'unité. Il existe quelques autres cadres de test xBehave, mais SpecFlow a reçu beaucoup d'attention.
xSpec BDD : MSpec
Objectivement parlant. Parmi les cadres de spécifications de contexte disponibles, MSpec est celui qui existe depuis le plus longtemps et qui est le cadre de spécification de contexte le plus largement utilisé dans la communauté .Net.
L'autre cadre xSpec BDD : NSpec
Je recommande personnellement NSpec (inspiré directement par RSpec pour Ruby). Pour tout vous dire, je suis l'un des auteurs de NSpec. Vous pouvez accomplir BDD en utilisant simplement NUnit ou MSTest... mais ils ne sont pas à la hauteur (il est vraiment difficile de construire des contextes de manière incrémentale). MSpec est également une option et constitue le cadre de contexte/spécification le plus mature pour .Net. Mais mais il y a des choses qui sont plus simples dans NSpec.
La longue réponse
Les deux variantes de BDD existent principalement en raison des avantages orthogonaux qu'elles procurent.
Avantages et inconvénients de xBehave (syntaxe GWT)
Pour
- permet de faciliter les conversations avec l'entreprise par le biais d'un dialecte commun appelé (par exemple, Given ...., And Given ...., When ......, And When ..... , Then ...., And Then)
- le dialecte commun peut ensuite être transposé en code exécutable, ce qui prouve à l'entreprise que vous avez réellement terminé ce que vous aviez promis de faire.
- le dialecte est contraignant, l'entreprise doit donc désambiguïser les exigences et les faire entrer dans les phrases.
Cons
- Bien que l'approche xBehave permette de définir des critères d'acceptation de haut niveau, les cycles nécessaires pour faire correspondre l'anglais au code exécutable par le biais d'attributs ne permettent pas de définir un domaine au niveau de l'unité.
- La mise en correspondance du dialecte commun avec les tests est PÉNible (augmentez votre regex). Chaque phrase créée par le métier doit être mappée à une méthode exécutable via des attributs.
- Le dialecte commun doit être étroitement contrôlé afin que la gestion de la cartographie ne devienne pas incontrôlable. Chaque fois que vous modifiez une phrase, vous devez trouver la méthode qui se rapporte directement à cette phrase et corriger la correspondance regex.
Avantages et inconvénients de xSpec (contexte/spécification)
Pour
- Permet au développeur d'établir le contexte de manière incrémentielle. Un contexte peut être mis en place pour un test et certaines assertions peuvent être exécutées contre ce contexte. Vous pouvez ensuite spécifier plus de contexte (en vous appuyant sur le contexte qui existe déjà), puis spécifier plus de tests.
- Pas de langage contraignant. Les développeurs peuvent être plus expressifs sur la façon dont une certaine partie d'un système se comporte.
- Aucune correspondance n'est nécessaire entre l'anglais et un dialecte commun (parce qu'il n'y en a pas).
Cons
- Pas aussi accessible par l'entreprise. Regardons les choses en face, les entreprises n'aiment pas désambiguïser ce qu'elles veulent. Si nous leur donnions une approche contextuelle de la BDD, la phrase se résumerait à "Faites que ça marche".
- Tout est dans le code. La documentation contextuelle est imbriquée dans le code (c'est pourquoi nous n'avons pas à nous soucier de la correspondance entre l'anglais et le code).
- Pas aussi lisible compte tenu d'un verbiage moins restrictif.
Échantillons
Le site Kata du bowling est un très bon exemple.
Exemple de SpecFlow
Voici à quoi ressemblerait la spécification dans SpecFlow (là encore, c'est un excellent test d'acceptation, car il communique directement avec l'entreprise) :
Dossier de présentation
Le fichier de caractéristiques est le dialecte commun pour le test.
Feature: Score Calculation
In order to know my performance
As a player
I want the system to calculate my total score
Scenario: Gutter game
Given a new bowling game
When all of my balls are landing in the gutter
Then my total score should be 0
Scenario: Single Pin
Given a new bowling game
When I've hit exactly 1 pin
Then my total score should be 1
Fichier de définition des étapes
Le fichier de définition d'étape est l'exécution réelle du test, ce fichier inclut les mappings pour SpecFlow.
[Binding]
public class BowlingSteps
{
private Game _game;
[Given(@"a new bowling game")]
public void GivenANewBowlingGame()
{
_game = new Game();
}
[When(@"all of my balls are landing in the gutter")]
public void WhenAllOfMyBallsAreLandingInTheGutter()
{
_game.Frames = "00000000000000000000";
}
[When(@"I've hit exactly 1 pin")]
public void When1PinIsHit()
{
_game.Frames = "10000000000000000000";
}
[Then(@"my total score should be (\d+)")]
public void ThenMyTotalScoreShouldBe(int score)
{
Assert.AreEqual(score, _game.Score);
}
}
MSpec Sample, xSpec, Contexte/Spécification
public class describe_BowlingKata
{
public static Game game;
public class when_all_balls_land_in_the_gutter : describe_BowlingKata
{
Establish ctx = () => game = new Game();
Because of = () => game.Frames = "00000000000000000000";
It should_have_a_score_of_0 = () => game.Score.ShouldBe(0);
}
public class when_a_single_pin_is_hit : describe_BowlingKata
{
Establish ctx = () => game = new Game();
Because of = () => game.Frames = "10000000000000000000";
It should_have_a_score_of_1 = () => game.Score.ShouldBe(1);
}
}
Echantillon NSpec, xSpec, Contexte/Spécification
Voici un NSpec exemple du même kata de bowling :
class describe_BowlingGame : nspec
{
Game game;
void before_each()
{
game = new Game();
}
void when_all_my_balls_land_in_the_gutter()
{
before = () => game.Frames = "00000000000000000000";
it["should have a score of 0"] = () => game.Score.should_be(0);
}
void when_a_single_pin_is_it()
{
before = () => game.Frames = "10000000000000000000";
it["should have a score of 1"] = () => game.Score.should_be(1);
}
}
Au fur et à mesure que vous ferez du BDD, vous constaterez que les versions xBehave et xSpec du BDD sont toutes deux nécessaires. xBehave est plus adapté aux tests d'acceptation, xSpec est plus adapté aux tests unitaires et à la conception axée sur le domaine.
MSpec vs NSpec
Des paramètres objectifs comme l'âge et la stabilité devraient être pris en compte, et j'encourage tout le monde à en tenir compte. Mais s'il vous plaît aussi prendre en considération le fait que les nouveaux cadres peuvent fournir une API plus succincte, une meilleure utilisation des constructions linguistiques et s'appuyer sur les leçons apprises pour les cadres passés . MSpec fournit des constructions de Given, Because, It et Cleanup mais elles ont un coût : initialisation statique pour tous les membres, explosion de la classe, et elle est syntaxiquement rigide en raison de son utilisation unique des délégués. Vous constaterez que les tests MSpec les plus simples sont plus simples dans NSpec. Voici une suite de tests plus complexe écrite à la fois en MSpec et en NSpec.
Une comparaison de xUnit, MSpec et NSpec : https://gist.github.com/amirrajan/6701522
Liens pertinents
rspec vs cucumber (histoires de rspec)
BDD avec Cucumber et rspec - quand est-ce que c'est redondant ?