Hallo allerseits!
Auf Habré gibt es ausgezeichnete Artikel über SpecFlow. Ich möchte mich mit diesem Thema befassen und über das parallele Ausführen von Tests, das Übergeben von Daten zwischen Schritten, das Helfen von Helfern, Transformationen, Hooks und die Verwendung von Json als Datenquelle sprechen.
Parallele Ausführung und Datenübertragung zwischen Schritten
In der
Dokumentation zum Übertragen von Daten zwischen Schritten finden Sie das folgende Beispiel:
Dieser Code verwendet Zeichenfolgenschlüssel. Das Auswendiglernen und Schreiben ist ziemlich mühsam.
Dieses Problem kann gelöst werden, indem eine statische Klasse mit den erforderlichen Eigenschaften erstellt wird:
public static class ScenarioData { public static ComplexObject Complex { get => ScenarioContext.Current.Get<ComplexObject>(nameof(Complex)); set => ScenarioContext.Current.Set(value, nameof(Complex)); } }
Die Datenübertragung sieht jetzt so aus:
Leider können wir ScenarioContext.Current
nicht verwenden, wenn wir Tests parallel ausführen, bis wir die erforderliche Injektion vorgenommen haben
So haben wir ein paar Probleme gelöst: Wir haben die String-Schlüssel entfernt und die Möglichkeit bereitgestellt, Tests parallel auszuführen. Für diejenigen, die experimentieren möchten, habe ich ein
kleines Projekt erstellt.Helfer und Transformationen unterstützen
Betrachten Sie den nächsten Schritt
When user starts rendering | SourceType | PageOrientation | PageMediaSizeName | | set-01-valid | Landscape | A4 |
Sehr oft werden Daten aus einer Tabelle so abgezogen
[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"]; ... }
Mit
Assist Helpers sieht das Lesen von Testdaten viel eleganter aus. Wir müssen ein Modell mit den entsprechenden Eigenschaften erstellen:
public class StartRenderingRequest { public string SourceType { get; set; } public string PageMediaSizeName { get; set; } public string PageOrientation { get; set; } }
und verwenden Sie es in CreateInstance
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var request = table.CreateInstance<StartRenderingRequest>(); ... }
Mit
Transformationen kann die Beschreibung des Testschritts noch weiter vereinfacht werden.
Definieren Sie die Transformation:
[Binding] public class Transforms { [StepArgumentTransformation] public StartRenderingRequest StartRenderingRequestTransform(Table table) { return table.CreateInstance<StartRenderingRequest>(); } }
Jetzt können wir den gewünschten Typ als Parameter im Schritt verwenden:
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(StartRenderingRequest request) {
Für diejenigen, die experimentieren wollen -
das gleiche Projekt.Hooks und Verwendung von Json als Quelle für Testdaten
SpecFlow-Tabellen sind mehr als genug für einfache Testdaten. Es gibt jedoch Testszenarien mit einer großen Anzahl von Parametern und / oder einer komplexen Datenstruktur. Um solche Testdaten zu verwenden und gleichzeitig die Lesbarkeit des Skripts zu gewährleisten, benötigen wir
Hooks . Wir werden den Hook [BeforeScenario] verwenden, um die erforderlichen Daten aus der Json-Datei zu lesen. Definieren Sie dazu spezielle
Tags auf Skriptebene
@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
und fügen Sie die Verarbeitungslogik zu den Hooks hinzu:
[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; }
Dieser Code subtrahiert den Inhalt der JSON-Datei (relativer Pfad zur Datei) in eine Zeichenfolgenvariable und speichert ihn in den Skriptdaten (ScenarioData.JsonDataSource). Daher können wir diese Daten bei Bedarf verwenden
[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); }
Da Json viele Daten enthalten kann, kann die Aktualisierung der Testdaten auch über Tags implementiert werden. Interessenten können ein Beispiel im selben
Projekt sehen.Referenzen
1.
Gurke2.
Essiggurke3.
SpecFlow-Dokumentation4.
SpecFlow Wiki5.
Ausführbare Spezifikation: SpecFlow A bis Z.6.
Datengesteuerte Tests & SpecFlow