Pisanie pakietu podstawowego banku
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 -v
polecenia 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 -v
polecenia 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 -v
polecenia 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 -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)
=== 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
.