Hola a todos!
En Habré hay excelentes artículos sobre SpecFlow. Quiero profundizar en este tema y hablar sobre la ejecución de pruebas en paralelo, pasando datos entre pasos, ayudantes de ayuda, transformaciones, enlaces y sobre el uso de Json como fuente de datos.
Ejecución paralela y transferencia de datos entre pasos.
En la
documentación para transferir datos entre pasos, encontramos el siguiente ejemplo:
Este código usa claves de cadena. Memorizarlos y escribirlos es bastante tedioso.
Este problema se puede resolver creando una clase estática con las propiedades necesarias:
public static class ScenarioData { public static ComplexObject Complex { get => ScenarioContext.Current.Get<ComplexObject>(nameof(Complex)); set => ScenarioContext.Current.Set(value, nameof(Complex)); } }
La transferencia de datos ahora se ve así:
Desafortunadamente,
no podremos usar ScenarioContext.Current al ejecutar pruebas en paralelo hasta que realicemos la Inyección necesaria
Por lo tanto, resolvimos un par de problemas: nos deshicimos de las teclas de cadena y proporcionamos la capacidad de ejecutar pruebas en paralelo. Para aquellos que quieran experimentar, creé un
pequeño proyecto.Ayudantes de ayuda y transformaciones
Considera el siguiente paso
When user starts rendering | SourceType | PageOrientation | PageMediaSizeName | | set-01-valid | Landscape | A4 |
Muy a menudo, los datos de una tabla se restan así
[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"]; ... }
Usando
Assist Helpers, leer los datos de las pruebas se ve mucho más elegante. Necesitamos hacer un modelo con las propiedades apropiadas:
public class StartRenderingRequest { public string SourceType { get; set; } public string PageMediaSizeName { get; set; } public string PageOrientation { get; set; } }
y usarlo en CreateInstance
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var request = table.CreateInstance<StartRenderingRequest>(); ... }
Con
Transformaciones , la descripción del paso de prueba se puede simplificar aún más.
Define la transformación:
[Binding] public class Transforms { [StepArgumentTransformation] public StartRenderingRequest StartRenderingRequestTransform(Table table) { return table.CreateInstance<StartRenderingRequest>(); } }
Ahora podemos usar el tipo deseado como parámetro en el paso:
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(StartRenderingRequest request) {
Para aquellos que quieren experimentar,
el mismo proyecto.Ganchos y uso de Json como fuente de datos de prueba
Las tablas SpecFlow son más que suficientes para datos de prueba simples. Sin embargo, hay escenarios de prueba con una gran cantidad de parámetros y / o una estructura de datos compleja. Para utilizar dichos datos de prueba, mientras se mantiene la legibilidad del script, necesitamos
ganchos . Utilizaremos el gancho [BeforeScenario] para leer los datos necesarios del archivo Json. Para hacer esto, defina
etiquetas especiales en el nivel del 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
y agregue la lógica de procesamiento a los ganchos:
[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; }
Este código resta el contenido del archivo json (ruta relativa al archivo) en una variable de cadena y lo guarda en los datos del script (ScenarioData.JsonDataSource). Por lo tanto, podemos usar estos datos cuando sea necesario
[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); }
Como puede haber muchos datos en Json, la actualización de los datos de prueba también se puede implementar a través de etiquetas. Los interesados pueden ver un ejemplo en el mismo
proyecto.Referencias
1.
pepino2.
Pepinillo3.
Documentación de SpecFlow4.
Wiki SpecFlow5.
Especificación ejecutable: SpecFlow A a Z6.
Pruebas basadas en datos y SpecFlow