Olá pessoal!
Em Habré, existem excelentes artigos sobre o SpecFlow. Desejo aprofundar-me neste tópico e falar sobre a execução de testes em paralelo, passando dados entre etapas, ajudando auxiliares, transformações, ganchos e sobre o uso do Json como fonte de dados.
Execução paralela e transferência de dados entre etapas
Na
documentação para transferir dados entre as etapas, encontramos o seguinte exemplo:
Este código usa chaves de seqüência de caracteres. Memorizar e digitá-los é bastante entediante.
Esse problema pode ser resolvido criando uma classe estática com as propriedades necessárias:
public static class ScenarioData { public static ComplexObject Complex { get => ScenarioContext.Current.Get<ComplexObject>(nameof(Complex)); set => ScenarioContext.Current.Set(value, nameof(Complex)); } }
A transferência de dados agora se parece com isso:
Infelizmente,
não poderemos usar o ScenarioContext.Current ao executar testes em paralelo até que façamos a injeção necessária
Assim, resolvemos alguns problemas: nos livramos das chaves de string e fornecemos a capacidade de executar testes em paralelo. Para quem quer experimentar, criei um
pequeno projeto.Auxiliar ajudantes e transformações
Considere o próximo passo
When user starts rendering | SourceType | PageOrientation | PageMediaSizeName | | set-01-valid | Landscape | A4 |
Frequentemente, os dados de uma tabela são subtraídos dessa maneira
[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 os
Assistentes de assistência, a leitura dos dados de teste parece muito mais elegante. Precisamos criar um modelo com as propriedades apropriadas:
public class StartRenderingRequest { public string SourceType { get; set; } public string PageMediaSizeName { get; set; } public string PageOrientation { get; set; } }
e use-o em CreateInstance
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var request = table.CreateInstance<StartRenderingRequest>(); ... }
Com
Transformações , a descrição da etapa do teste pode ser simplificada ainda mais.
Defina a transformação:
[Binding] public class Transforms { [StepArgumentTransformation] public StartRenderingRequest StartRenderingRequestTransform(Table table) { return table.CreateInstance<StartRenderingRequest>(); } }
Agora podemos usar o tipo desejado como parâmetro na etapa:
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(StartRenderingRequest request) {
Para quem quer experimentar -
o mesmo projeto.Hooks e usando Json como fonte de dados de teste
As tabelas SpecFlow são mais que suficientes para dados de teste simples. No entanto, existem cenários de teste com um grande número de parâmetros e / ou uma estrutura de dados complexa. Para usar esses dados de teste, mantendo a legibilidade do script, precisamos de
Hooks . Usaremos o gancho [BeforeScenario] para ler os dados necessários no arquivo Json. Para fazer isso, defina
tags especiais no nível do 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
e adicione a lógica de processamento aos 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; }
Esse código subtrai o conteúdo do arquivo json (caminho relativo para o arquivo) em uma variável de seqüência de caracteres e o salva nos dados do script (ScenarioData.JsonDataSource). Assim, podemos usar esses dados quando necessário
[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 pode haver muitos dados no Json, a atualização dos dados de teste também pode ser implementada por meio de tags. Os interessados podem ver um exemplo no mesmo
projeto.Referências
1.
Pepino2.
Maxixe3.
Documentação SpecFlow4.
Wiki do SpecFlow5.
Especificação executável: SpecFlow A a Z6.
Testes orientados a dados e SpecFlow