Różnice między podanym momentem, kiedy to (GWT) a Arrange Act Assert (AAA)?

13

W TDD istnieje składnia 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);
}

W testach BDD pisanie używa podobnej struktury, ale ze składnią 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 */   }

Chociaż często uważa się je za takie same, istnieją różnice. Kilka kluczowych to:

  1. GWT można odwzorować bezpośrednio na specyfikację pliku funkcji w ramach BDD

  2. GWT jest łatwiejszy do zrozumienia dla osób, które nie są programistami, zachęcając do używania zwykłego angielskiego i krótko opisując, co robi każda część

  3. Podane kiedy i kiedy to słowa kluczowe w różnych ramach BDD, takich jak SpecFlow i Cucumber

Moje pytanie: czy są jakieś inne różnice (oprócz nazw) między AAA i GWT? Czy jest jakiś powód poza wymienionymi powyżej, że jeden powinien być preferowany nad drugim?

Chaos poznawczy
źródło
3
Nie widzę różnicy poza „czytaniem bardziej jak językiem naturalnym”. Biorąc pod uwagę ustalenie, kiedy nastąpi akcja, to zapewnij pewne rzeczy o nowym stanie.
Sjoerd Job Postmus
Myślę, że znalazłeś kilka istotnych punktów i raczej nie otrzymasz odpowiedzi z dodatkowymi różnicami. Ze względu na swoją wartość używam wyłącznie AAA do testów jednostkowych, ponieważ format jest całkowicie niezależny od metodologii, ale zachęca do małych, niezależnych testów.
amon

Odpowiedzi:

9

Myślę, że bardzo dobrze wymieniłeś różnice w swoim pytaniu, jednak dodam kilka moich opinii na temat tego, jak postrzegam oba podejścia.

AAA jest dla mnie bardzo przydatny podczas testowania własnego kodu. Jeśli pracuję nad projektem lub biblioteką dla siebie, AAA jest właściwą drogą. Pozwala mi skonfigurować wszystko, co potrzebne do wykonania testu, a następnie po prostu przetestować . Szybko go konfiguruję i szybko sprawdzam, czy mój kod działa zgodnie z oczekiwaniami.

GWT jest przydatny w środowiskach biznesowych, w których praca wykonywana przez programistów musi być odwzorowana na wartość biznesową. Wartość biznesowa jest odwzorowywana według funkcji i, mam nadzieję, funkcji, które nie wprowadzają błędów. Istnieje wiele strategii mapowania funkcji do zadań programistycznych, ale jedną z nich są wymagania. Z mojego doświadczenia wynika, że ​​wymagania wahają się od wymagań na poziomie użytkownika aż po małe zadania do wykonania przez użytkownika. Jest to przydatne, ponieważ menedżerowie mogą łatwo zrozumieć, w jaki sposób praca programisty wpływa na ich klientów / użytkowników, a zatem dlaczego programiści wnoszą wartość dodaną do ich działalności

  • Wymagania na poziomie użytkownika: Biorąc pod uwagę, że magazyn ma co najmniej N pozycji w magazynie, kiedy użytkownik kupuje N pozycji, wówczas magazyn wysyła N pozycji
  • Wymaganie na poziomie systemu 1: Biorąc pod uwagę, że w systemie ekwipunku jest N pozycji (ek) w ekwipunku, kiedy do systemu ekwipunku zostanie wprowadzone żądanie N pozycji (ów), wówczas system ekwipunku zmniejsza liczbę zapasów dla tego rodzaju pozycji
  • Wymaganie na poziomie systemu 2: Biorąc pod uwagę, że system płatności ma N pozycji (ek) w ekwipunku, kiedy do systemu płatności zostanie wprowadzone żądanie N pozycji (ów), wówczas system płatności obciąża użytkownika za N pozycji (y)
  • ...
  • Wymaganie na poziomie programisty 1: Biorąc pod uwagę, że 5 swetrów znajduje się w ekwipunku, gdy 3 swetry zostaną usunięte z ekwipunku, wówczas w ekwipunku pozostaną 2 osoby
  • ...

Ten rodzaj struktury wymagań pozwala na projektowanie drzewiaste, w którym wszystkie wymagania na poziomie programisty mapują drzewo do wymagań na poziomie użytkownika. W ten sposób, gdy nie powiedzie się wymaganie na poziomie programisty, wiadomo, na który wymóg ma wpływ poziom użytkownika.

W przeciwieństwie do tego test AAA może wyglądać tak. To jest dla mnie bardzo ważne dla programistów i nie jest przydatne dla biznesu. Nie oznacza to, że podobna struktura wymagań nie może być stworzona ze strategii testowania AAA, ale nic w języku AAA nie ułatwia tego.

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
źródło
Zawsze interesuje mnie, gdy ludzie pytają, czy komputery (a więc programiści) wnoszą wartość dodaną do ich działalności. Czy to naprawdę może być tylko duży samozbierający się bambus? Myślę, że menedżer biznesu powinien albo nauczyć się wystarczająco dużo o programowaniu, aby zrozumieć, w jaki sposób osiąga swoje cele, albo po prostu zaufać, że to robi i nie martwić się. Może nie do końca rozumiem, jak działa substancja chemiczna wpływająca na początek opóźnionego prądu prostownika w komórkach przedsionkowych, ale zdecydowanie mogę poczuć, jak dobrze jest nie mieć arytmii serca.
Abstrakcja jest ważna poza informatyką. Ludzie będą mieli specjalistyczną wiedzę z różnych dziedzin, a umiejętność przekazywania tej wiedzy innym osobom ma kluczowe znaczenie dla firmy. GWT to abstrakcja, która jest przydatna, aby zachęcić programistów i menedżerów (program | projekt) do komunikacji. Po drugie, jako programista łatwo sobie wyobrazić, że programiści mają potencjał, aby generować niewielką lub żadną wartość dla firmy. Na koniec warto zauważyć, że GWT to nie tylko sposób komunikowania się programistów i menedżerów, ale jedno z wielu narzędzi, które firma może chcieć wypróbować.
Frank Bryce
Chciałbym też, żeby mój lekarz zrozumiał, dlaczego mechanizm korekcji arytmii serca działa, zanim go włożą, a nie tylko, że działa. Testy GWT mają pomóc odpowiedzieć na „dlaczego”. GWT pomaga w komunikacji między programistą a kierownikiem produktu i jest podobny do komunikacji między chemikiem a lekarzem. Kierownik produktu komunikuje się z użytkownikami, jakie funkcje uzyskują, podczas gdy lekarz komunikuje swoim pacjentom, jaką wartość uzyskują dzięki korekcji arytmii serca.
Frank Bryce
4

Myślę, że to zależy od używanego frameworka. Ogólnie, o ile mi wiadomo, AAA jest wspierane przez ramy NUnit, a zatem jest to naturalny wybór w tym względzie. Jeśli chodzi o teoretyczne różnice między TDD i BDD, wydają się one niewielkie. Zobacz ten link, ktoś bardziej wykwalifikowany niż ja, aby dać ci wyjaśnienie.

George Grainger
źródło
2

Nie ma żadnej różnicy.
Trzy stany testu:
Biorąc pod uwagę = Rozmieść,
Kiedy = Działaj,
Następnie = Potwierdź.

Różnice, które podałeś w pytaniu, to różnice między TDD i BDD, a nie GWT i AAA.

W TDD możesz mieć trzy różne metody dla jednego testu

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
źródło