Het bankkernpakket schrijven
Nu het basisproject samen met ons testbestand wordt uitgevoerd, gaan we beginnen met het schrijven van de code waarmee de functies en vereisten van de vorige les worden geïmplementeerd. Hier gaan we terug naar enkele onderwerpen die we eerder hebben besproken, zoals fouten, structuren en methoden.
Open het $GOPATH/src/bankcore/bank.go
bestand, verwijder de Hello()
functie en laten we beginnen met het schrijven van de kernlogica van ons online banksysteem.
Structuren maken voor klanten en accounts
Laten we beginnen met het maken van een Customer
structuur waarin we de naam, het adres en het telefoonnummer hebben van een persoon die een bankklant wil worden. We hebben ook een structuur nodig voor de Account
gegevens. Omdat een klant meer dan één account kan hebben, gaan we de klantgegevens insluiten in het accountobject. In principe gaan we maken wat we in de TestAccount
test hebben gedefinieerd.
De structuren die we nodig hebben, kunnen eruitzien als in het volgende codevoorbeeld:
package bank
// Customer ...
type Customer struct {
Name string
Address string
Phone string
}
// Account ...
type Account struct {
Customer
Number int32
Balance float64
}
Wanneer u de opdracht nu uitvoert in uw go test -v
terminal, ziet u dat de test wordt doorgegeven:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
PASS
ok github.com/msft/bank 0.094s
Deze test wordt doorgegeven omdat we de structuren voor Customer
en Account
. Nu we de structuren hebben, gaan we de methoden schrijven voor het toevoegen van de functies die we nodig hebben in de eerste versie van onze bank. Deze functies omvatten stortingen, intrekken en geld overmaken.
De stortingsmethode implementeren
We moeten beginnen met een methode om geld toe te voegen aan onze rekening. Maar voordat we dat doen, gaan we de TestDeposit
functie in het bank_test.go
bestand maken:
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")
}
}
Wanneer u uitvoert go test -v
, ziet u een mislukte test in de uitvoer:
# 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]
Om aan de vorige test te voldoen, gaan we een Deposit
methode maken voor onze Account
structuur die een fout retourneert als het ontvangen bedrag gelijk is aan of lager is dan nul. Anders voegt u het bedrag toe dat u hebt ontvangen aan het saldo van de rekening.
Gebruik de volgende code voor de Deposit
methode:
// 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
}
Wanneer u de test uitvoert go test -v
, ziet u dat de test wordt doorgegeven:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
=== RUN TestDeposit
--- PASS: TestDeposit (0.00s)
PASS
ok github.com/msft/bank 0.193s
U kunt ook een test schrijven die bevestigt dat u een foutmelding krijgt wanneer u een negatief bedrag probeert in te storten, zoals deze:
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")
}
}
Wanneer u de go test -v
opdracht uitvoert, ziet u dat de test wordt doorgegeven:
=== 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
Notitie
Vanaf hier schrijven we één testcase voor elke methode. Maar u moet zoveel tests naar uw programma's schrijven als u zich vertrouwd voelt, zodat u zowel verwachte als onverwachte scenario's kunt behandelen. In dit geval wordt bijvoorbeeld de logica voor foutafhandeling getest.
De ingetrokken methode implementeren
Voordat we de Withdraw
functionaliteit schrijven, gaan we de test hiervoor schrijven:
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")
}
}
Wanneer u de go test -v
opdracht uitvoert, ziet u een mislukte test in de uitvoer:
# 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]
We gaan de logica voor de Withdraw
methode implementeren, waarbij we het saldo van het account verminderen met het bedrag dat we als parameter ontvangen. Zoals we eerder hebben gedaan, moeten we valideren dat het getal dat we ontvangen groter is dan nul en dat het saldo in de rekening voldoende is.
Gebruik de volgende code voor de Withdraw
methode:
// 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
}
Wanneer u de go test -v
opdracht uitvoert, ziet u dat de test wordt doorgegeven:
=== 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
De instructiemethode implementeren
Laten we een methode schrijven om de instructie af te drukken die de accountnaam, het nummer en het saldo bevat. Maar eerst gaan we de TestStatement
functie maken:
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")
}
}
Wanneer u uitvoert go test -v
, ziet u een mislukte test in de uitvoer:
# 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]
Laten we de Statement
methode schrijven, die een tekenreeks moet retourneren. (U moet deze methode later overschrijven als een uitdaging.) Gebruik de volgende code:
// Statement ...
func (a *Account) Statement() string {
return fmt.Sprintf("%v - %v - %v", a.Number, a.Name, a.Balance)
}
Wanneer u de test uitvoert go test -v
, ziet u dat de test wordt doorgegeven:
=== 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
We gaan verder met de volgende sectie en schrijven de web-API die de Statement
methode beschikbaar maakt.