Nie potrafię napisać testu do jednej funkcji

0

Cześć,

Mój cały kod poniżej i czy mógłbym prosić o pomoc w napisaniu testu (phpunit) do jedenj funkcji a mianowicie do funkcji
public function withdrawCash($amount)

<?php

class BankAccount {
    private $number;
    private $cash;
    static private $nextAccNumber = 1;

    public function __construct() {
        $this->number = self::$nextAccNumber;
        self::$nextAccNumber++;
        $this->cash = 0.0;
        echo "Twój numer konta: $this->number.<br>";
    }

    public function getNumber() {
        return $this->number;
    }

    public function getCash() {
        return $this->cash;
    }

    public function depositCash($amount) {
        if (is_numeric($amount) && $amount > 0) {
            $this->cash += $amount;
        }
        return $this;
    }
    
    public function withdrawCash($amount) {
        if (is_numeric($amount) && $amount > 0) {
            if ($amount > $this->cash) {
                $withdraw = $this->cash;
            }
            else {
                $withdraw = $amount;
            }
            $this->cash -= $withdraw;
            return $withdraw;
        }
    }
    
    public function printInfo() {
        echo $this->cash;
    }
}

Dziekuję

1

ale z czym masz konkretnie problem?

0

no w sumie problem mam taki że kompletnie nie wiem jak to ugryźć. Jak do poprzednich funkcji jakoś te testy napisałem to tej nie mam pojęcia.
Nie wiem jakiego asserta wuykorzystać czy $this->assertGreaterThan jest poprawny. Zakręciłem się nad tym od paru godzin i już szukam pomocy w sieci.

0

Przede wszystkim musisz zrozumiec co dana funkcja robi i co chcesz sprawdzic. W tym przypadku jezeli $amount jest wieksze od zera oraz jest liczba to Twoja funkcja powinna zmniejszyc $this->cash o podana ilosc. Tu juz masz pierwszy test. Pozniej mozesz zrobic kolejny assert ze sprawdzeniem if'a $amount > $this->cash, else tez jestes w stanie rpzetestowac podobnie jak poprzednie pdoajac tylko inne parametry.

0

Chyba dzisiaj na to za głupi jestem. Wracam do tego jutro :)
Dziekuję za pomoc

0

Po pierwsze mały clean up w kodzie, który pozwoli nam usunąć elsy i zagnieżdzenia

public function withdrawCash($amount)
{
    // unikamy zagnieżdzenia dzięki early exception lub early return
    if (!is_numeric($amount) || $amount <= 0) {
        throw new InvalidArgumentException("WTF m8?");
    }
 
    // unikamy elsa dzieki defaultowej wartosci
    $withdraw = $amount;

    if ($withdraw > $this->cash) {
        $withdraw = $this->cash;
    }
    
    $this->cash -= $withdraw;
    
    return $withdraw;
}

Teraz patrzysz na swoją funkcję i zauważasz, że masz 2 ify. Każdy z tych warunków musisz przetestować. Czyli zawsze jak piszesz test:

  • sprawdzasz happy path
  • Sad path (Path of Sorrow, Vale of Tears - jak zwał atk zwał).
  • i każdy jeden warunek jaki jest w twojej metodzie, dlatego im mniej tym lepiej
class BankAccountTest {
    public function testWithdrawCashWorksForAmountLessThanBalance()
    {
        // tutaj sprawdzamy tzw. happy path, czyli podajemy prawidłowe argumentry
        // i sprawdzamy, czy działa
    }

    public function testWithdrawCashWithdrawsAtMostTheCurrentBalance()
    {
        // tutaj sprawdzamy twojego if'a
    }
    
    public function testWithdrawCashThrowsExceptionOnInvalidAmount()
    {
        // tutaj zakładasz, że ktoś chce zrobić cos niedozwolonego
        // przypadkii dla "ASDASDADS" i dla $amount < 0 oczywiście
    }
}
0

@eloszki: odpowiem Ci tutaj, bo pewnie się nie zmieszczę w komentarzu.

Mogłbyś oczywiście wszystkie trzy warunki sprawdzić w jednej metodzie pod tytułem testWithdrawCash i ładnie okomentować

public function testWithdrawCash()
{
    // tutaj sprawdzamy tzw. happy path
    // $account->withDraw...
    // assert...
    
    // tutaj sprawdzamy sad path..
    
    // tutaj sprawdzamy ify...
}

tylko teraz jeżeli test Ci się załamie, to nie wiesz co się zepsuło. W logach zobaczysz, że 1 test failed - testWithdrawCash i wiesz, że metoda withdrawCash nie działa jak powinna, ale nie wiesz co dokładnie nie działa. Jak masz każdy przypadek rozbity na osobną metodę, to wtedy dostajesz coś takiego 1 test failed - testWithdrawCashWithdrawsAtMostTheCurrentBalance i wiesz, ze problem jest w tym, ze ktos chce wypłacić sume większą niż ma na koncie i prawodpodobnie mu sie to udało.

W testach nie trzeba stosować zasady DRY (don't repeat yourself), ale SRP (single responsibility principle) nadal bym zostawił. Czyli każda metoda w teście sprawdza jedną rzecz, nie mniej i nie więcej.

0

Teraz wydaje się to bardzo logiczne nawet. Tak jak z kodem rozbijam go na najmniejsze kawałki zazwyczaj albo raczej na namniejsze problemy tak samo muszę tutaj robić. dzięki raz jeszcze.

1 użytkowników online, w tym zalogowanych: 0, gości: 1