Pisanie pakietu podstawowego banku

Ukończone

Teraz, gdy mamy już uruchomiony projekt podstawowy wraz z naszym plikiem testowym, zacznijmy pisać kod implementujący funkcje i wymagania poprzedniej lekcji. W tym miejscu omówiliśmy kilka zagadnień, takich jak błędy, struktury i metody.

$GOPATH/src/bankcore/bank.go Otwórz plik, usuń Hello() funkcję i zacznijmy pisać podstawową logikę naszego systemu bankowego online.

Tworzenie struktur dla klientów i kont

Zacznijmy od utworzenia Customer struktury, w której mamy nazwę, adres i numer telefonu od osoby, która chce zostać klientem bankowym. Ponadto potrzebujemy struktury danych Account . Ponieważ klient może mieć więcej niż jedno konto, osadźmy informacje o kliencie w obiekcie konta. Zasadniczo utwórzmy to, co zdefiniowaliśmy w TestAccount teście.

Potrzebne struktury mogą wyglądać podobnie do następującego przykładu kodu:

package bank

// Customer ...
type Customer struct {
    Name    string
    Address string
    Phone   string
}

// Account ...
type Account struct {
    Customer
    Number  int32
    Balance float64
}

Po uruchomieniu polecenia w terminalu go test -v powinien zostać wyświetlony komunikat, że test przechodzi:

=== RUN   TestAccount
--- PASS: TestAccount (0.00s)
PASS
ok      github.com/msft/bank    0.094s

Ten test przechodzi, ponieważ zaimplementowaliśmy struktury dla i Customer Account. Teraz, gdy mamy struktury, napiszmy metody dodawania funkcji potrzebnych w początkowej wersji naszego banku. Funkcje te obejmują depozyt, wypłatę i przelew pieniędzy.

Implementowanie metody depozytu

Musimy zacząć od metody, aby umożliwić dodawanie pieniędzy na nasze konto. Jednak zanim to zrobimy, utwórzmy TestDeposit funkcję w bank_test.go pliku:

func TestDeposit(t *testing.T) {
    account := Account{
        Customer: Customer{
            Name:    "John",
            Address: "Los Angeles, California",
            Phone:   "(213) 555 0147",
        },
        Number:  1001,
        Balance: 0,
    }

    account.Deposit(10)

    if account.Balance != 10 {
        t.Error("balance is not being updated after a deposit")
    }
}

Po uruchomieniu go test -vpolecenia powinien zostać wyświetlony test kończący się niepowodzeniem w danych wyjściowych:

# github.com/msft/bank [github.com/msft/bank.test]
./bank_test.go:32:9: account.Deposit undefined (type Account has no field or method Deposit)
FAIL    github.com/msft/bank [build failed]

Aby spełnić poprzedni test, utwórzmy metodę Deposit dla naszej Account struktury, która zwraca błąd, jeśli odebrana kwota jest równa lub niższa niż zero. W przeciwnym razie po prostu dodaj kwotę otrzymaną do salda konta.

Użyj następującego kodu dla Deposit metody :

// Deposit ...
func (a *Account) Deposit(amount float64) error {
    if amount <= 0 {
        return errors.New("the amount to deposit should be greater than zero")
    }

    a.Balance += amount
    return nil
}

Po uruchomieniu go test -vpolecenia powinien zostać wyświetlony komunikat, że test przechodzi:

=== RUN   TestAccount
--- PASS: TestAccount (0.00s)
=== RUN   TestDeposit
--- PASS: TestDeposit (0.00s)
PASS
ok      github.com/msft/bank    0.193s

Możesz również napisać test, który potwierdza, że występuje błąd podczas próby wpłaty ujemnej kwoty, w następujący sposób:

func TestDepositInvalid(t *testing.T) {
    account := Account{
        Customer: Customer{
            Name:    "John",
            Address: "Los Angeles, California",
            Phone:   "(213) 555 0147",
        },
        Number:  1001,
        Balance: 0,
    }

    if err := account.Deposit(-10); err == nil {
        t.Error("only positive numbers should be allowed to deposit")
    }
}

Po uruchomieniu go test -v polecenia powinien zostać wyświetlony komunikat, że test przechodzi:

=== RUN   TestAccount
--- PASS: TestAccount (0.00s)
=== RUN   TestDeposit
--- PASS: TestDeposit (0.00s)
=== RUN   TestDepositInvalid
--- PASS: TestDepositInvalid (0.00s)
PASS
ok      github.com/msft/bank    0.197s

Uwaga

W tym miejscu napiszemy jeden przypadek testowy dla każdej metody. Ale należy napisać tyle testów do swoich programów, jak czujesz się komfortowo, więc możesz obejmować zarówno oczekiwane, jak i nieoczekiwane scenariusze. Na przykład w tym przypadku logika obsługi błędów jest testowana.

Implementowanie metody wycofywania

Zanim napiszemy Withdraw funkcjonalność, napiszmy dla niej test:

func TestWithdraw(t *testing.T) {
    account := Account{
        Customer: Customer{
            Name:    "John",
            Address: "Los Angeles, California",
            Phone:   "(213) 555 0147",
        },
        Number:  1001,
        Balance: 0,
    }

    account.Deposit(10)
    account.Withdraw(10)

    if account.Balance != 0 {
        t.Error("balance is not being updated after withdraw")
    }
}

Po uruchomieniu go test -v polecenia w danych wyjściowych powinien zostać wyświetlony test kończący się niepowodzeniem:

# github.com/msft/bank [github.com/msft/bank.test]
./bank_test.go:67:9: account.Withdraw undefined (type Account has no field or method Withdraw)
FAIL    github.com/msft/bank [build failed]

Zaimplementujmy logikę dla Withdraw metody, w której zmniejszamy saldo konta o kwotę otrzymaną jako parametr. Podobnie jak wcześniej, musimy sprawdzić, czy otrzymana liczba jest większa niż zero i że saldo na koncie jest wystarczające.

Użyj następującego kodu dla Withdraw metody :

// Withdraw ...
func (a *Account) Withdraw(amount float64) error {
    if amount <= 0 {
        return errors.New("the amount to withdraw should be greater than zero")
    }

    if a.Balance < amount {
        return errors.New("the amount to withdraw should be less than the account's balance")
    }

    a.Balance -= amount
    return nil
}

Po uruchomieniu go test -v polecenia powinien zostać wyświetlony komunikat, że test przechodzi:

=== RUN   TestAccount
--- PASS: TestAccount (0.00s)
=== RUN   TestDeposit
--- PASS: TestDeposit (0.00s)
=== RUN   TestDepositInvalid
--- PASS: TestDepositInvalid (0.00s)
=== RUN   TestWithdraw
--- PASS: TestWithdraw (0.00s)
PASS
ok      github.com/msft/bank    0.250s

Implementowanie metody instrukcji

Napiszmy metodę, aby wydrukować instrukcję zawierającą nazwę konta, liczbę i saldo. Najpierw utwórzmy TestStatement jednak funkcję:

func TestStatement(t *testing.T) {
    account := Account{
        Customer: Customer{
            Name:    "John",
            Address: "Los Angeles, California",
            Phone:   "(213) 555 0147",
        },
        Number:  1001,
        Balance: 0,
    }

    account.Deposit(100)
    statement := account.Statement()
    if statement != "1001 - John - 100" {
        t.Error("statement doesn't have the proper format")
    }
}

Po uruchomieniu go test -vpolecenia powinien zostać wyświetlony test kończący się niepowodzeniem w danych wyjściowych:

# github.com/msft/bank [github.com/msft/bank.test]
./bank_test.go:86:22: account.Statement undefined (type Account has no field or method Statement)
FAIL    github.com/msft/bank [build failed]

Napiszmy metodę Statement , która powinna zwrócić ciąg. (Musisz zastąpić tę metodę później jako wyzwanie). Użyj następującego kodu:

// Statement ...
func (a *Account) Statement() string {
    return fmt.Sprintf("%v - %v - %v", a.Number, a.Name, a.Balance)
}

Po uruchomieniu go test -vpolecenia powinien zostać wyświetlony komunikat, że test przechodzi:

=== RUN   TestAccount
--- PASS: TestAccount (0.00s)
=== RUN   TestDeposit
--- PASS: TestDeposit (0.00s)
=== RUN   TestDepositInvalid
--- PASS: TestDepositInvalid (0.00s)
=== RUN   TestWithdraw
--- PASS: TestWithdraw (0.00s)
=== RUN   TestStatement
--- PASS: TestStatement (0.00s)
PASS
ok      github.com/msft/bank    0.328s

Przejdźmy do następnej sekcji i napiszmy internetowy interfejs API, który uwidacznia metodę Statement .