Bonjour à tous!
Sur Habré, il y a d'excellents articles sur SpecFlow. Je veux approfondir ce sujet et parler de l'exécution de tests en parallèle, de la transmission de données entre les étapes, des assistants, des transformations, des hooks et de l'utilisation de Json comme source de données.
Exécution parallèle et transfert de données entre les étapes
Dans la
documentation pour le transfert de données entre les étapes, nous trouvons l'exemple suivant:
Ce code utilise des clés de chaîne. Les mémoriser et les taper est assez fastidieux.
Ce problème peut être résolu en créant une classe statique avec les propriétés nécessaires:
public static class ScenarioData { public static ComplexObject Complex { get => ScenarioContext.Current.Get<ComplexObject>(nameof(Complex)); set => ScenarioContext.Current.Set(value, nameof(Complex)); } }
Le transfert de données ressemble maintenant à ceci:
Malheureusement, nous
ne pourrons
pas utiliser ScenarioContext.Current lors de l'exécution de tests en parallèle tant que nous n'aurons pas effectué l'injection nécessaire.
Ainsi, nous avons résolu quelques problèmes: nous nous sommes débarrassés des clés de chaîne et avons fourni la possibilité d'exécuter des tests en parallèle. Pour ceux qui veulent expérimenter, j'ai créé un
petit projet.Aider les assistants et les transformations
Considérez la prochaine étape
When user starts rendering | SourceType | PageOrientation | PageMediaSizeName | | set-01-valid | Landscape | A4 |
Assez souvent, les données d'une table sont soustraites comme ceci
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var sourceType = table.Rows.First()["SourceType"]; var pageOrientation = table.Rows.First()["PageOrientation"]; var pageMediaSizeName = table.Rows.First()["PageMediaSizeName"]; ... }
À l'aide des
assistants, la lecture des données de test semble beaucoup plus élégante. Nous devons faire un modèle avec les propriétés appropriées:
public class StartRenderingRequest { public string SourceType { get; set; } public string PageMediaSizeName { get; set; } public string PageOrientation { get; set; } }
et l'utiliser dans CreateInstance
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var request = table.CreateInstance<StartRenderingRequest>(); ... }
Avec
Transformations , la description de l'étape de test peut être encore simplifiée.
Définissez la transformation:
[Binding] public class Transforms { [StepArgumentTransformation] public StartRenderingRequest StartRenderingRequestTransform(Table table) { return table.CreateInstance<StartRenderingRequest>(); } }
Maintenant, nous pouvons utiliser le type souhaité comme paramètre dans l'étape:
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(StartRenderingRequest request) {
Pour ceux qui veulent expérimenter -
le même projet.Crochets et utilisation de Json comme source de données de test
Les tables SpecFlow sont plus que suffisantes pour des données de test simples. Cependant, il existe des scénarios de test avec un grand nombre de paramètres et / ou une structure de données complexe. Afin d'utiliser ces données de test, tout en maintenant la lisibilité du script, nous avons besoin de
Hooks . Nous utiliserons le hook [BeforeScenario] pour lire les données nécessaires du fichier Json. Pour ce faire, définissez des
balises spéciales au niveau du script
@jsonDataSource @jsonDataSourcePath:DataSource\FooResponse.json Scenario: Validate Foo functionality Given user has access to the Application Service When user invokes Foo functionality | FooRequestValue | | input | Then Foo functionality should complete successfully
et ajoutez la logique de traitement aux crochets:
[BeforeScenario("jsonDataSource")] public void BeforeScenario() { var tags = ScenarioContext.ScenarioInfo.Tags; var jsonDataSourcePathTag = tags.Single(i => i.StartsWith(TagJsonDataSourcePath)); var jsonDataSourceRelativePath = jsonDataSourcePathTag.Split(':')[1]; var jsonDataSourcePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, jsonDataSourceRelativePath); var jsonRaw = File.ReadAllText(jsonDataSourcePath); ScenarioData.JsonDataSource = jsonRaw; }
Ce code soustrait le contenu du fichier json (chemin d'accès relatif au fichier) dans une variable de chaîne et l'enregistre dans les données de script (ScenarioData.JsonDataSource). Ainsi, nous pouvons utiliser ces données si nécessaire
[Then(@"Foo functionality should complete successfully")] public void ThenFooFunctionalityShouldCompleteSuccessfully() { var actual = ScenarioData.FooResponse; var expected = JsonConvert.DeserializeObject<FooResponse>(ScenarioData.JsonDataSource); actual.FooResponseValue.Should().Be(expected.FooResponseValue); }
Comme il peut y avoir beaucoup de données dans Json, la mise à jour des données de test peut également être implémentée via des balises. Les personnes intéressées peuvent voir un exemple dans le même
projet.Les références
1.
Concombre2.
Cornichon3.
Documentation SpecFlow4.
Wiki SpecFlow5.
Spécification exécutable: SpecFlow A à Z6.
Tests basés sur les données et SpecFlow