step argument transformations specflow tables
Tutorial Step Argument Transformations & Specflow Tables:
Nosso tutorial anterior do Specflow nos informou sobre Vinculações compartilhadas e com escopo, ganchos e reutilização de etapas em detalhe. Aqui neste tutorial, vamos explorar mais sobre Transformações de Argumento de Etapa em Specflow.
Sinta-se à vontade para ler nosso Guia completo de treinamento Specflow para iniciantes para uma compreensão clara do conceito. O recurso Step Argument Transformation do Specflow permite que um usuário forneça uma transformação personalizada para os parâmetros fornecidos nas etapas.
Ele permite que uma lógica personalizada seja adicionada para converter parâmetros de entrada em um parâmetro específico. Por exemplo, você pode criar diretamente um objeto de classe a partir dos parâmetros e retornar o objeto construído da função de transformação.
Outro recurso do Specflow que veremos são as tabelas Specflow, que permitem a passagem de dados de entrada em formato tabular com uma única etapa e os auxiliares de tabela podem mapear diretamente para uma instância de objeto conforme desejado.
Assista o vídeo:
Aqui está um tutorial em vídeo sobre as tabelas Step Argument Transformations & Specflow:
O que você aprenderá:
Step Argument Transformations
Para entender as transformações do Argumento de uma maneira melhor, vamos primeiro tentar descobrir como exatamente Specflow corresponde aos parâmetros. Como vimos em nossos artigos anteriores, para o exemplo de pesquisa do YouTube, estávamos passando o termo de pesquisa como um parâmetro para que o cenário fosse executado.
A correspondência de parâmetro geralmente ocorre por meio de uma expressão regular e a regex correspondente resulta na definição do parâmetro do método para o termo de pesquisa fornecido na etapa.
Vamos primeiro tentar entender quais são as conversões padrão com suporte no Specflow e quando as transformações de argumento podem ser úteis.
Conversões Suportadas
O Specflow oferece suporte a muitas conversões prontas para o uso, observando o próprio tipo de dados após a correspondência de regex. Ele pode cuidar automaticamente de conversões como - String, inteiro, GUID, Enums, etc.
Vejamos um exemplo para alguns deles abaixo:
Scenario: Get Transactions in my account Given I have entered customer name as Test Customer And I have entered customer account id as 0f8fad5b-d9cb-469f-a165-70867728950e And I select sorting order as DESCENDING And I select number of transactions to be displayed as 25 Then I should see my account transactions
No exemplo de código acima, destacamos diferentes tipos de entrada que estamos passando nas etapas e, nas implementações das etapas, eles estão sendo convertidos para os respectivos tipos de dados.
Vamos ver as implementações de etapas para eles abaixo (para simplificar, acabamos de fazer um console para cada uma das etapas para ilustrar que o argumento fornecido é automaticamente convertido para o tipo esperado):
(Given(@'I have entered customer name as (.*)')) public void GivenIHaveEnteredCustomerNameAsTestCustomer(String customerName) { Console.Out.WriteLine(customerName); } (Given(@'I have entered customer account id as (.*)')) public void GivenIHaveEnteredCustomerAccountIdAs(Guid accountId) { Console.Out.WriteLine(accountId.ToString()); } (Given(@'I select sorting order as (.*)')) public void GivenISelectSortingOrderAsAscending(SortOrder sortOrder) { Console.Out.WriteLine(sortOrder.ToString()); } (Then(@'I should see my account transactions')) public void ThenIShouldSeeMyAccountTransactions() { Console.Out.WriteLine('success!'); } (Given(@'I select number of transactions to be displayed as (.*)')) public void GivenISelectNumberOfTransactionsToBeDisplayedAs(int p0) { Console.Out.WriteLine(p0.ToString());
Ao executar o cenário acima, a saída imprime todos os valores com sucesso, indicando que a conversão automática de argumentos para os tipos de dados esperados foi bem-sucedida.
Esta é a aparência da saída:
Given I have entered customer name as Test Customer Test Customer -> done: SupportedSpecflowConversions.GivenIHaveEnteredCustomerNameAsTestCustomer('Test Customer') (0.0s) And I have entered customer account id as 0f8fad5b-d9cb-469f-a165-70867728950e 0f8fad5b-d9cb-469f-a165-70867728950e -> done: SupportedSpecflowConversions.GivenIHaveEnteredCustomerAccountIdAs(0f8fad5b-d9cb-469...) (0.0s) And I select sorting order as DESCENDING DESCENDING -> done: SupportedSpecflowConversions.GivenISelectSortingOrderAsAscending(DESCENDING) (0.0s) And I select number of transactions to be displayed as 25 25 -> done: SupportedSpecflowConversions.GivenISelectNumberOfTransactionsToBeDisplayedAs(25) (0.0s) Then I should see my account transactions success! -> done: SupportedSpecflowConversions.ThenIShouldSeeMyAccountTransactions() (0.0s)
Transformações de Argumento
Vamos ver um exemplo em ação para entender isso. Suporte, você tem um aplicativo que converte o tempo determinado e o converte em minutos. Exemplo: Se a entrada do usuário for 1 dia - a saída é - 1440, se a entrada do usuário for 1 dia 2 horas 2 minutos, então a saída deve ser 1562.
Agora, pode-se ver que para suportar diferentes tipos de entradas, será necessário escrever diferentes implementações de ligação, dependendo do tipo de entradas. Por exemplo: Para entradas tendo apenas a parte do dia, haverá uma implementação de etapa separada, para entradas tendo uma parte do dia, mês - haverá implementação de etapas separadas, etc.
Vamos ver como isso pode ser implementado por meio de uma implementação de etapa única por meio da transformação de Argumento de Etapa e a entrada fornecida é simplesmente convertida em objeto de carimbo de data / hora e retornada à etapa original que é chamada de transformação de etapa.
Pense nisso como uma varredura regex de primeiro nível para sua entrada, que retorna o valor parcialmente transformado para a etapa de chamada.
Observe o arquivo de feições com 3 variantes de entrada diferentes, com uma única transformação, convertendo-o em um objeto de intervalo de tempo completo e retornando de volta.
Scenario: Convert timestamp to minutes - variant 1 Given I have entered 50 days into the timestamp to minute converter When I press calculate Then the result should be 72000.00 on the screen Scenario: Convert timestamp to minutes - variant 2 Given I have entered 1 day, 2 hours, 3 minutes into the timestamp to minute converter When I press calculate Then the result should be 1563.00 on the screen Scenario: Convert timestamp to minutes - variant 3 Given I have entered 1 day, 1 hour, 1 minute, 30 seconds into the timestamp to minute converter When I press calculate Then the result should be 1501.50 on the screen
Observe os valores destacados no exemplo de código acima. Tudo isso será feito exatamente na mesma transformação e o resultado final será um valor de entrada TimeSpan transformado que é enviado de volta para a etapa de chamada de Specflow.
Vejamos a implementação da Transformação abaixo:
(StepArgumentTransformation(@'(?:(d*) day(?:s)?(?:, )?)?(?:(d*) hour(?:s)?(?:, )?)?(?:(d*) minute(?:s)?(?:, )?)?(?:(d*) second(?:s)?(?:, )?)?')) public TimeSpan convertToTimeSpan(String days, String hours, String minutes, String seconds) { int daysValue; int hoursValue; int minutesValue; int secondsValue; int.TryParse(days, out daysValue); int.TryParse(hours, out hoursValue); int.TryParse(minutes, out minutesValue); int.TryParse(seconds, out secondsValue); return new TimeSpan(daysValue, hoursValue, minutesValue, secondsValue); }
Para que a estrutura saiba que é uma ligação de transformação, o Atributo StepArgumentTransformation precisa ser adicionado ao método que implementa a conversão de Argumento.
Os outros pontos importantes a serem observados em relação às conversões de argumento são:
# 1) As transformações do argumento da etapa são executadas para cada etapa de correspondência, ou seja, independentemente do tipo de etapa, ou seja, se é dado, quando ou então, a transformação acontecerá para cada regex correspondente.
#dois) Dependendo do tipo de retorno da saída transformada, se a etapa de chamada real não tiver o tipo de retorno correspondente para o parâmetro de entrada, a transformação não ocorrerá.
O que isso significa é, suponha que a etapa de chamada requer uma entrada transformada, mas tem o carimbo de data / hora de entrada mencionado como algo que não corresponde ao tipo de retorno do método transformado, então a correspondência de regex será substituída e a conversão não ocorrerá.
Vejamos a implementação de chamar a etapa “Dado”:
private TimeSpan ts; (Given(@'I have entered (.*) into the timestamp to minute converter')) public void GivenIHaveEnteredDaysIntoTheTimestampToMinuteConverter(TimeSpan tsTransformed) { ts = tsTransformed; }
Observe o tipo de parâmetro de entrada aqui, ou seja, seu TimeSpan, que corresponde ao tipo retornado da etapa de transformação se for alterado para algum outro tipo. Por exemplo, String, a conversão do argumento não acontecerá e a correspondência de regex será substituída pela implementação Step original.
Dica profissional: Um ponto importante a ser observado aqui é que todo o texto que precisa ser transformado deve ser alimentado / combinado por meio da transformação do argumento da etapa. Conseqüentemente, a etapa fornecida envolverá agora todos os formatos de entrada possíveis em uma única string e a expressão regular de transformação irá convertê-la em um objeto TimeSpan e retornar de volta.Tabelas Specflow
As tabelas Specflow são uma forma de passar uma lista dos valores para a função de implementação da etapa. Em nossos artigos anteriores, examinamos a maneira de implementar testes orientados a dados usando esboço do cenário e exemplos. Mas isso era principalmente para executar o cenário com entradas diferentes.
Aqui, nas tabelas, trata-se de passar todos os dados de uma vez em forma tabular para a implementação da etapa que está fornecendo os dados.
Por exemplo, considere um exemplo em que você está testando um Sistema de Gestão de Alunos e, para criar um novo objeto de Aluno, é necessário preencher muitos detalhes como nome, sobrenome, idade, ano de nascimento, etc.
Uma maneira é passar cada uma dessas informações como uma etapa separada que será essencialmente uma grande quantidade de código clichê e em cada etapa, você acabará atualizando o mesmo objeto que precisa ser testado. Outra maneira pode ser construir um regex complexo e tentar passar todos os dados na mesma etapa, mas é bastante sujeito a erros e instável.
As mesas vêm em nosso socorro aqui. Todos os dados de entrada relacionados ao aluno podem ser enviados para a implementação da mesma etapa de uma forma tabular agradável por meio do recurso de tabela do specflow.
Vejamos um exemplo de código abaixo para implementação de recursos e etapas:
Scenario: Pass data through Specflow tables for StudentInfo object Given I have entered following info for Student | FirstName | LastName | Age | YearOfBirth | | test | student | 20 | 1995 | When I press add Then i student should get added to database and entered info should be displayed on the screen
Os dados da tabela são destacados na Etapa do Cenário acima.
melhor editor python mac os x
Specflow fornece muitos TableHelpers, que permitem recursos úteis diretamente, como a criação de uma instância de objeto a partir dos dados de entrada fornecidos pelo usuário, em vez de analisar cada campo sozinho.
Vejamos a etapa de implementação abaixo:
private StudentInfo studInfo; (Given(@'I have entered following info for Student')) public void GivenIHaveEnteredFollowingInfoForStudent(Table table) { // converting supplied input data directly to instance of StudentInfo object studInfo = table.CreateInstance(); }
Observe a seção destacada acima. Aqui está apenas uma pequena linha de código, todo o objeto StudentInfo (que é um POCO contendo os campos de dados do aluno, ou seja, nome, sobrenome, idade, ano de nascimento, etc)
Alguns outros recursos / conceitos relacionados às tabelas Specflow são mostrados abaixo:
# 1) As tabelas podem ser horizontais ou verticais. As tabelas verticais são mais parecidas com pares de valores-chave e, no cenário acima, mais parecidos com mapeamentos de nome-valor, enquanto as tabelas horizontais contêm todos os dados de um objeto em uma única linha (como vimos em nosso exemplo).
#dois) As tabelas verticais podem ser mapeadas para apenas um único objeto .NET, enquanto as tabelas horizontais também podem ser mapeadas para um Conjunto ou Coleção de Objetos.
# 3) Cada valor de campo na tabela deve ser atômico, pois será mapeado para um único campo correspondente no objeto analisado.
Um ponto importante a notar aqui é que mesmo se você auto-gerar vinculações de etapas com os dados tabulares, o gerador de vinculação Specflow contabilizará automaticamente esses tipos de entrada e os reconhecerá como dados tabulares válidos.
Conclusão
Neste artigo, tentamos explicar 2 conceitos importantes e úteis no Specflow.
O primeiro passo é o Transformações Step Argument que permitem conversões de tipo personalizadas para argumentos Specflow para evitar código clichê (e permite que o script de teste pareça mais modularizado e lógico) e o segundo recurso que vimos é Tabelas Specflow que são úteis quando você precisa passar muitos campos / dados em uma única etapa em um formato tabular amigável.
Em nosso próximo tutorial, aprenderemos mais sobre como você pode gerar automaticamente uma bela documentação usando Specflow em diferentes formatos usando ferramentas de código aberto como Pickles, que podem servir como uma referência fácil para todos os interessados no projeto.
PREV Tutorial | PRÓXIMO Tutorial
Leitura recomendada
- Implantação no MongoDB: tutorial passo a passo
- Instalação e configuração passo a passo do Appium Studio
- Exemplo de ponta a ponta do Specflow e Selenium Webdriver
- Um guia passo a passo para integrar o QTP ao ALM / QC
- As 15 perguntas mais populares da entrevista do Specflow
- Advanced Specflow Shared e Scoped Bindings, Hooks e Step Reuse
- Instale o MongoDB no Windows: um guia passo a passo
- Como Integrar JIRA com qTest: Um Guia Passo a Passo