c# - En Specflow, ¿puedo ejecutar una prueba como paso de otra?
unit-testing automated-tests (4)
TL; DR; ¿Cómo puedo crear una prueba de flujo de datos que llame a otra prueba como primer paso?
Given I already have one specflow test
And I want to run another test that goes deeper than the first test
Then I create a second test that runs the first test as its first step
And I add additional steps to test the deeper functionality
Lo siento, un poco de humor specflow allí.
Por ejemplo, tengo una prueba que ya crea una venta:
Given I want to create a sales order
And I open the sales order page
And I click the add new order button
Then a new sales order is created
Y quiero tener otra prueba que pruebe agregar una línea de ventas
Y otra prueba que prueba completar la venta
Y otra prueba que cancela la venta
Y así
Todas esas pruebas comenzarían con los mismos primeros cuatro pasos que la prueba simple, que rompe el principio DRY. Entonces, ¿cómo puedo hacerlo para que el primer paso de la segunda prueba solo ejecute la primera prueba? por ejemplo, algo como:
Given I have run the create sales order test // right here it just runs the first test
And I add a sales order line
Then the order total is updated
Si cada prueba comienza con las mismas primeras cuatro líneas, y más tarde me doy cuenta de que tengo que cambiar la prueba simple de crear una oferta, entonces también tendré que ir a buscar y arreglar todo el resto que repita esas cuatro líneas.
EDITAR: tenga en cuenta que esto también debería poder funcionar a través de las características. Por ejemplo, la prueba simple anterior se define en la función de ventas. Pero también tendría una función de crédito, y eso requeriría crear una venta cada vez para poder acreditarla:
Given I want to credit a sale
And I run the create sales order test
And I complete the the sale
And I click the credit button
Then the sale is credited
Como ya se señaló, puede usar un fondo para esto (y esa es probablemente la mejor opción en la mayoría de las situaciones), pero también puede crear un paso que llame a los otros pasos.
[Binding]
public class MySteps: Steps //Inheriting this base class is vital or the methods used below won''t be available
{
[Given("I have created an order")]
public void CreateOrder()
{
Given("I want to create a sales order");
Given("I open the sales order page");
Given("I click the add new order button");
Then("a new sales order is created");
}
}
que puedes usar en tu escenario:
Scenario: I add another sale
Given I have created an order
When I add a sales order line
Then the order total is updated
Esto tiene la ventaja de que este paso compuesto puede usarse en cualquier parte del escenario y no solo como punto de partida. Este paso puede ser reutilizado en múltiples funciones si necesita
Usa un fondo:
Background:
Given I want to create a sales order
And I open the sales order page
And I click the add new order button
Then a new sales order is created
Scenario: I add another sale
When I add a sales order line
Then the order total is updated
Scenario: I add cancel a sale
When I cancel a sale
Then the order total is updated to 0
etc.
No necesita ejecutar pasos reales para crear un pedido de cliente. Simplemente implemente una definición de paso que lo haga por usted como una línea.
Primero, la clase ficticia SalesOrder
:
public class SalesOrder
{
public double Amount { get; set; }
public string Description { get; set; }
}
Luego, las definiciones de paso
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;
[Binding]
public class SalesOrderSteps
{
[Given("I have already created a Sales Order")]
public void GivenIHaveAlreadyCreatedASalesOrder()
{
var order = new SalesOrder()
{
// .. set default properties
};
// Save to scenario context so subsequent steps can access it
ScenarioContext.Current.Set<SalesOrder>(order);
using (var db = new DatabaseContext())
{
db.SalesOrders.Add(order);
db.SaveChanges();
}
}
[Given("I have already created a Sales Order with the following attributes:")]
public void GivenIHaveAlreadyCreatedASalesOrderWithTheFollowingAttributes(Table table)
{
var order = table.CreateInstance<SalesOrder>();
// Save to scenario context so subsequent steps can access it
ScenarioContext.Current.Set<SalesOrder>(order);
using (var db = new DatabaseContext())
{
db.SalesOrders.Add(order);
db.SaveChanges();
}
}
}
Ahora puede crear pedidos de venta como un solo trazo y opcionalmente incluir algunos atributos personalizados:
Scenario: Something
Given I have already created a Sales Order
Scenario: Something else
Given I have already created a Sales Order with the following attributes:
| Field | Value |
| Amount | 25.99 |
| Description | Just a test order |
Si necesita acceder a ese objeto SalesOrder
en otras definiciones de pasos sin consultarlo en la base de datos, use ScenarioContext.Current.Get<SalesOrder>()
para recuperar ese objeto del contexto del escenario.
Si entiendo la pregunta correctamente, quiere llamar a otros escenarios en diferentes archivos de características.
- Puede manejar esto creando un paso que llamaría los pasos en el escenario (básicamente pasos anidados como la respuesta aceptada arriba).
- Agregue el paso creado al fondo
o
- Crea una función que llamaría los pasos en el escenario.
- Agregue una etiqueta @create_sale_order a los escenarios que necesitan una orden de venta como condición previa.
- Implemente un enlace de escenario anterior para la etiqueta @create_sale_order y llame a la función creada en el paso 1.