web-dev-qa-db-fra.com

Dans SpecFlow, comment puis-je partager des données entre les étapes/fonctionnalités?

J'ai 2 fonctionnalités qui utilisent une étape "Quand" commune mais qui ont des étapes "Alors" différentes dans différentes classes.

Comment puis-je accéder, par exemple, à ActionResult à partir de l'appel de mon contrôleur MVC dans l'étape When de mes deux étapes Then?

32
Simon Keep

Dans SpecFlow 1.3, il existe trois méthodes:

  1. membres statiques
  2. ScenarioContext
  3. ContextInjection

Commentaires:

  1. les membres statiques sont très pragmatiques et dans ce cas, pas si mal que les développeurs le pensent d'abord (il n'y a pas de thread ou besoin de se moquer/de se remplacer dans les définitions pas à pas)

  2. Voir la réponse de @Si Keep dans ce fil

  3. Si le constructeur d'une classe de définition d'étape a besoin d'arguments, Specflow essaie d'injecter ces arguments. Ceci peut être utilisé pour injecter le même contexte dans plusieurs définitions d'étape.
    Voir un exemple ici: https://github.com/techtalk/SpecFlow/wiki/Context-Injection

33
jbandi

Utilisez la classe ScenarioContext, qui est un dictionnaire commun à toutes les étapes.

ScenarioContext.Current.Add("ActionResult", actionResult);
var actionResult = (ActionResult) ScenarioContext.Current["ActionResult"];
32
Simon Keep

J'ai une classe d'assistance qui me permet d'écrire 

Current<Page>.Value = pageObject;

qui est un wrapper sur le ScenarioContext. Cela fonctionne sur le nom du type, il devrait donc être légèrement étendu si vous devez accéder à deux variables du même type.

 public static class Current<T> where T : class
 {
     internal static T Value 
     {
         get { 
               return ScenarioContext.Current.ContainsKey(typeof(T).FullName)
               ? ScenarioContext.Current[typeof(T).FullName] as T : null;
             }
         set { ScenarioContext.Current[typeof(T).FullName] = value; }
     }
 }

Édition 2019: J'utiliserais la réponse de @ JoeT de nos jours, il semblerait que vous bénéficiez des mêmes avantages sans avoir à définir une extension

15
mcintyre321

Je n'aimais pas utiliser Scenario.Context à cause de la nécessité de jeter chaque entrée du dictionnaire. J'ai trouvé un autre moyen de stocker et de récupérer l'élément sans avoir à le lancer. Cependant, il existe un compromis ici car vous utilisez effectivement le type car la clé permet d'accéder à l'objet à partir du dictionnaire ScenarioContext. Cela signifie qu'un seul article de ce type peut être stocké. 

TestPage testPageIn = new TestPage(_driver);
ScenarioContext.Current.Set<TestPage>(testPageIn);
var testPageOut = ScenarioContext.Current.Get<TestPage>();
8
JoeT

Vous pouvez définir un paramètre dans vos étapes qui est la clé de la valeur que vous stockez. De cette façon, vous pourrez le référencer dans vos étapes ultérieures en utilisant la clé. 

...
Then I remember the ticket number '<MyKey>'
....
When I type my ticket number '<MyKey>' into the search box
Then I should see my ticket number '<MyKey>' in the results 

Vous pouvez stocker la valeur réelle dans un dictionnaire ou un sac de propriétés ou similaire.

0
Daniel Kereama