¿Diferencias entre Given When Then (GWT) y Arrange Act Assert (AAA)?

13

En TDD hay una sintaxis de Arrange Act Assert (AAA):

[Test]
public void Test_ReturnItemForRefund_ReturnsStockOfBlackSweatersAsTwo_WhenOneInStockAndOneIsReturned()
{
    //Arrange
    ShopStock shopStock = new ShopStock();
    Item blackSweater = new Item("ID: 25");
    shopStock.AddStock(blackSweater);
    int expectedResult = 2;
    Item blackSweaterToReturn = new Item("ID: 25");

    //Act
    shopStock.ReturnItemForRefund(blackSweaterToReturn);
    int actualResult = shopStock.GetStock("ID: 25");

    //Assert
    Assert.AreEqual(expectedResult, actualResult);
}

En BDD, las pruebas de escritura usan una estructura similar pero con la sintaxis Given When Then (GWT):

    [Given(@"a customer previously bought a black sweater from me")]
    public void GivenACustomerPreviouslyBoughtABlackSweaterFromMe()
    { /* Code goes here */   }

    [Given(@"I currently have three black sweaters left in stock")]
    public void GivenICurrentlyHaveThreeBlackSweatersLeftInStock()
    { /* Code goes here */   }

    [When(@"he returns the sweater for a refund")]
    public void WhenHeReturnsTheSweaterForARefund()
    { /* Code goes here */   }

    [Then(@"I should have four black sweaters in stock")]
    public void ThenIShouldHaveFourBlackSweatersInStock()
    { /* Code goes here */   }

Aunque a menudo se consideran iguales, hay diferencias. Algunas claves son:

  1. GWT se puede asignar directamente a la especificación de un archivo de características en marcos BDD

  2. GWT es más fácil de entender para los no desarrolladores al fomentar el uso del inglés simple y al tener una breve descripción de lo que está haciendo cada parte

  3. Dado cuándo y luego son palabras clave en varios marcos de BDD como SpecFlow y Cucumber

Mi pregunta es ¿hay alguna otra diferencia (además de los nombres) entre AAA y GWT? ¿Y hay alguna razón, además de las especificadas anteriormente, de que una debería preferirse sobre la otra?

Caos cognitivo
fuente
3
No veo una diferencia, excepto por "lee más como un lenguaje natural". Dado un acuerdo, cuando ocurre una acción, luego afirmar cosas sobre el nuevo estado.
Sjoerd Job Postmus
Creo que ha encontrado un par de puntos relevantes y es poco probable que reciba una respuesta con diferencias adicionales. Para lo que vale, uso exclusivamente AAA para pruebas unitarias, ya que el formato es completamente independiente de la metodología, pero alienta a las pruebas pequeñas e independientes.
amon

Respuestas:

9

Creo que enumeró muy bien las diferencias en su pregunta, sin embargo, agregaré algunas de mis opiniones sobre cómo veo los dos enfoques.

AAA es muy útil para mí cuando estoy probando mi propio código. Si estoy trabajando en un proyecto o una biblioteca para mí, AAA es el camino a seguir. Me permite configurar lo que necesito para ejecutar mi prueba y luego simplemente probarlo . Es rápido de configurar y rápido para verificar que mi código esté funcionando como esperaba.

GWT es útil en entornos empresariales, donde el trabajo que realizan los programadores debe asignarse al valor empresarial. El valor comercial está mapeado por características, y con suerte características que no introducen errores. Existen muchas estrategias para asignar características a las tareas de programación, pero una de ellas es a través de los requisitos. En mi experiencia, los requisitos van desde requisitos a nivel de usuario hasta pequeñas tareas para que el usuario las ejecute. Esto es útil porque es fácil para los gerentes entender cómo el trabajo que está haciendo el programador está impactando a sus clientes / usuarios y, por lo tanto, por qué los programadores están agregando valor a su negocio

  • Requisito de nivel de usuario: dado que el almacén tiene al menos N artículo (s) en inventario, cuando un usuario compra N artículo (s), el almacén envía N artículo (s) al usuario
  • Requisito de nivel de sistema 1: dado que el sistema de inventario tiene N artículo (s) en el inventario, cuando se ingresa una solicitud de N artículo (s) en el sistema de inventario, el sistema de inventario disminuye el recuento de inventario para ese tipo de artículo
  • Requisito 2 a nivel del sistema: dado que el sistema de pago tiene N artículo (s) en el inventario, cuando se ingresa una solicitud de N artículo (s) en el sistema de pago, el sistema de pago cobra al usuario por N artículo (s)
  • ...
  • Requisito de nivel de programador 1: dado que 5 suéteres están en inventario, cuando se quitan 3 suéteres del inventario, quedan 2 plazas en el inventario
  • ...

Este tipo de estructura de requisitos permite un diseño similar a un árbol donde todos los requisitos de nivel de programador asignan el árbol a los requisitos de nivel de usuario. De esta manera, cuando falla un Requisito de Nivel de Programador, entonces sabe qué Requisito de Nivel de Usuario se ve afectado.

En contraste, una prueba AAA podría verse así. Esto para mí es muy programador y no es útil para el negocio. Eso no quiere decir que no se pueda hacer una estructura de árbol similar de requisitos a partir de una estrategia de prueba AAA, pero nada en el lenguaje de AAA lo hace más fácil.

public void Test_CaseWhereThereAreEnoughSweatersLeft() {
    // Arrange
    // setup Sweater Inventory mock (DB mocks, etc)
    // count = 5
    // when The number of sweaters remaining is request, return count
    // when Inventory is requested to remove N items, then count = count - N

    // Act
    // call the Unit Under Test to remove 3 items from inventory

    // Assert
    // the number of sweaters in the inventory is 2
    // the removal should return indicating a successful removal of items from the inventory
}

public void Test_CaseWhereThereAreNotEnoughSweatersLeft() {
    // Arrange
    // setup Sweater Inventory mock (DB mocks, etc)
    // count = 2
    // when The number of sweaters remaining is request, return count
    // when Inventory is requested to remove N items, then count = count - N

    // Act
    // call the Unit Under Test to remove 3 items from inventory

    // Assert
    // the number of sweaters remaining is still 2
    // the removal should return an error indicating not enough items in the inventory
}
Frank Bryce
fuente
Siempre me parece interesante cuando las personas se preguntan si las computadoras (y, por lo tanto, los programadores) están agregando valor a su negocio. ¿ Realmente podría ser solo un gran bambú de autoservicio? Creo que un gerente de negocios debería aprender lo suficiente sobre programación para comprender cómo está logrando sus objetivos, o simplemente confiar en que lo hace y no preocuparse. Puede que realmente no entienda cómo funciona un químico que influye en la aparición de la corriente rectificadora retardada en las células auriculares, pero definitivamente puedo sentir lo bueno que es no tener más arritmia cardíaca.
La abstracción es importante fuera de la informática. Las personas tendrán experiencia en diferentes campos, y poder comunicar esa experiencia con otros es crucial para un negocio. GWT es una abstracción que es útil para que los programadores y los gerentes de (proyecto | proyecto) se comuniquen. En segundo lugar, como programador es fácil imaginar que los programadores tienen el potencial de producir poco o ningún valor para un negocio. Por último, vale la pena señalar que GWT no es la única forma de comunicar a los programadores y gerentes, sino una de las muchas herramientas que una empresa puede intentar.
Frank Bryce
Además, me gustaría que mi médico entienda por qué funciona mi mecanismo de corrección de arritmia cardíaca antes de que lo coloquen, no solo eso. Se supone que las pruebas de GWT ayudan a responder el "por qué". GWT que ayuda a la comunicación entre el programador y el gerente de producto es análogo a la comunicación entre el químico y el médico. Un gerente de producto comunica a los usuarios qué características obtienen mientras que un médico les comunica a sus pacientes qué valor obtienen con una corrección de la arritmia cardíaca.
Frank Bryce
4

Supongo que depende del marco que estés usando. En general, hasta donde yo entiendo, AAA es compatible con el marco de NUnit, y por lo tanto es la opción natural en ese sentido. En cuanto a las diferencias teóricas entre TDD y BDD, parecen ser leves. Vea este enlace, alguien más calificado que yo para darle una explicación.

George Grainger
fuente
2

No hay diferencia en absoluto.
Tres estados de prueba:
Dado = Organizar,
Cuando = Actuar,
Entonces = Afirmar.

Las diferencias que proporcionó en la pregunta son las diferencias entre TDD y BDD y no entre GWT y AAA.

En TDD puede tener tres métodos diferentes para una prueba

public class TestsOfFormatMethod
{        
    public void Arrange() { // set dependencies }
    public string Act() { // return formattted result }
    public string AssertThatFormatIsEmpty()
    {
        Arrange();
        var actual = Act();
        Assert.IsEmpty(actual);
    }
}
Fabio
fuente