199 lines
6.9 KiB
Go
199 lines
6.9 KiB
Go
package main
|
||
|
||
import "testing"
|
||
|
||
func TestBlackjackModelDealsCorrectPlayerCount(t *testing.T) {
|
||
for n := 1; n <= 6; n++ {
|
||
m := NewBlackjackModel(n, 100, 10)
|
||
if len(m.game.Players) != n {
|
||
t.Errorf("ожидалось %d игроков, получено %d", n, len(m.game.Players))
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelClampsPlayerCount(t *testing.T) {
|
||
m := NewBlackjackModel(0, 100, 10)
|
||
if len(m.game.Players) != 1 {
|
||
t.Errorf("ожидалось ограничение снизу до 1 игрока, получено %d", len(m.game.Players))
|
||
}
|
||
m = NewBlackjackModel(10, 100, 10)
|
||
if len(m.game.Players) != 6 {
|
||
t.Errorf("ожидалось ограничение сверху до 6 игроков, получено %d", len(m.game.Players))
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelHitViaKeys(t *testing.T) {
|
||
m := NewBlackjackModel(1, 100, 10)
|
||
resetForManualBout(m.game)
|
||
m.game.Players[0].Hand = []Card{c(King, Clubs), c(Queen, Hearts)}
|
||
m.game.CurrentPlayerIdx = 0
|
||
m.game.Phase = BJPhasePlayerTurn
|
||
m.game.Deck = &Deck{cards: []Card{c(Five, Diamonds)}}
|
||
|
||
next, _ := m.Update(key("h"))
|
||
m = next.(BlackjackModel)
|
||
if m.isError {
|
||
t.Fatalf("неожиданная ошибка: %s", m.message)
|
||
}
|
||
if m.game.Players[0].Status != BJStatusBusted {
|
||
t.Fatalf("ожидался перебор, статус: %v", m.game.Players[0].Status)
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelStandViaKeys(t *testing.T) {
|
||
m := NewBlackjackModel(1, 100, 10)
|
||
resetForManualBout(m.game)
|
||
m.game.CurrentPlayerIdx = 0
|
||
m.game.Phase = BJPhasePlayerTurn
|
||
|
||
next, _ := m.Update(key("s"))
|
||
m = next.(BlackjackModel)
|
||
if m.isError {
|
||
t.Fatalf("неожиданная ошибка: %s", m.message)
|
||
}
|
||
if m.game.Phase != BJPhaseRoundOver {
|
||
t.Fatalf("с одним игроком после stand раунд должен был сразу завершиться")
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelDoubleViaKeys(t *testing.T) {
|
||
m := NewBlackjackModel(1, 100, 10)
|
||
resetForManualBout(m.game)
|
||
m.game.Players[0].Hand = []Card{c(Five, Clubs), c(Six, Hearts)}
|
||
m.game.CurrentPlayerIdx = 0
|
||
m.game.Phase = BJPhasePlayerTurn
|
||
m.game.Deck = &Deck{cards: []Card{c(King, Diamonds)}}
|
||
|
||
next, _ := m.Update(key("d"))
|
||
m = next.(BlackjackModel)
|
||
if m.isError {
|
||
t.Fatalf("неожиданная ошибка: %s", m.message)
|
||
}
|
||
if m.game.Players[0].Bet != 20 {
|
||
t.Fatalf("ставка должна была удвоиться, получено %d", m.game.Players[0].Bet)
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelQReturnsToMenu(t *testing.T) {
|
||
m := NewBlackjackModel(2, 100, 10)
|
||
next, _ := m.Update(key("q"))
|
||
m = next.(BlackjackModel)
|
||
if !m.backToMenu {
|
||
t.Fatalf("ожидался флаг backToMenu после 'q'")
|
||
}
|
||
if m.quitting {
|
||
t.Fatalf("'q' не должен закрывать всё приложение")
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelNewRoundCarriesBalance(t *testing.T) {
|
||
m := NewBlackjackModel(1, 100, 10)
|
||
resetForManualBout(m.game)
|
||
m.game.CurrentPlayerIdx = 0
|
||
m.game.Phase = BJPhasePlayerTurn
|
||
|
||
next, _ := m.Update(key("s"))
|
||
m = next.(BlackjackModel)
|
||
if m.game.Phase != BJPhaseRoundOver {
|
||
t.Fatalf("раунд должен был завершиться")
|
||
}
|
||
balanceAfterRound := m.game.Players[0].Balance
|
||
|
||
next, _ = m.Update(key("n"))
|
||
m = next.(BlackjackModel)
|
||
// с одним игроком новый раунд может мгновенно разрешиться сам,
|
||
// если случайно выпадет блэкджек с раздачи — это ожидаемое
|
||
// поведение, а не баг, поэтому проверяем именно перенесённый
|
||
// капитал (preRoundBalance), а не итоговый Balance
|
||
if m.game.preRoundBalance[0] != balanceAfterRound {
|
||
t.Fatalf("капитал должен был перенестись в новый раунд: ожидалось %d, получено %d",
|
||
balanceAfterRound, m.game.preRoundBalance[0])
|
||
}
|
||
}
|
||
|
||
// TestBlackjackModelFullAutoPlaythrough прогоняет TUI-модель от
|
||
// начала до конца для человека, отыгрывающего по той же логике, что
|
||
// и бот, но через реальные нажатия клавиш — для нескольких
|
||
// вариантов числа игроков и нескольких раундов подряд.
|
||
func TestBlackjackModelFullAutoPlaythrough(t *testing.T) {
|
||
bot := BlackjackBot{}
|
||
for n := 1; n <= 6; n++ {
|
||
m := NewBlackjackModel(n, 1000, 10)
|
||
for round := 0; round < 20; round++ {
|
||
const maxSteps = 200
|
||
steps := 0
|
||
for m.game.Phase != BJPhaseRoundOver && steps < maxSteps {
|
||
steps++
|
||
if m.game.CurrentPlayerIdx != m.humanIdx {
|
||
next, _ := m.Update(botMoveMsg{})
|
||
m = next.(BlackjackModel)
|
||
continue
|
||
}
|
||
action := bot.DecideAction(m.game)
|
||
var k string
|
||
switch action {
|
||
case "double":
|
||
k = "d"
|
||
case "hit":
|
||
k = "h"
|
||
default:
|
||
k = "s"
|
||
}
|
||
next, _ := m.Update(key(k))
|
||
m = next.(BlackjackModel)
|
||
}
|
||
if steps >= maxSteps {
|
||
t.Fatalf("игроков %d, раунд %d: раунд через TUI не завершился за %d шагов", n, round, maxSteps)
|
||
}
|
||
if m.game.Result == nil {
|
||
t.Fatalf("игроков %d, раунд %d: раунд завершился без результата", n, round)
|
||
}
|
||
next, _ := m.Update(key("n"))
|
||
m = next.(BlackjackModel)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelShowsMessageWhenBetReduced(t *testing.T) {
|
||
m := NewBlackjackModel(1, 100, 10)
|
||
for m.game.Phase == BJPhasePlayerTurn {
|
||
if err := m.game.Stand(); err != nil {
|
||
t.Fatalf("неожиданная ошибка: %v", err)
|
||
}
|
||
}
|
||
m.game.Players[m.humanIdx].Balance = 4 // меньше полной ставки 10, но больше нуля
|
||
|
||
next, _ := m.Update(key("n"))
|
||
m = next.(BlackjackModel)
|
||
if !m.game.RoundBetReduced[m.humanIdx] {
|
||
t.Fatalf("ожидался флаг урезанной ставки")
|
||
}
|
||
if m.game.Players[m.humanIdx].Bet != 4 {
|
||
t.Errorf("ставка должна была урезаться до 4, получено %d", m.game.Players[m.humanIdx].Bet)
|
||
}
|
||
if m.message == "" {
|
||
t.Errorf("ожидалось информационное сообщение об урезанной ставке")
|
||
}
|
||
if m.isError {
|
||
t.Errorf("сообщение об урезанной ставке не должно быть ошибкой")
|
||
}
|
||
}
|
||
|
||
func TestBlackjackModelShowsMessageWhenNoFundsLeft(t *testing.T) {
|
||
m := NewBlackjackModel(1, 100, 10)
|
||
for m.game.Phase == BJPhasePlayerTurn {
|
||
if err := m.game.Stand(); err != nil {
|
||
t.Fatalf("неожиданная ошибка: %v", err)
|
||
}
|
||
}
|
||
m.game.Players[m.humanIdx].Balance = 0
|
||
|
||
next, _ := m.Update(key("n"))
|
||
m = next.(BlackjackModel)
|
||
if m.game.Players[m.humanIdx].Bet != 0 {
|
||
t.Errorf("ставка при отсутствии денег должна была стать 0, получено %d", m.game.Players[m.humanIdx].Bet)
|
||
}
|
||
if m.message == "" {
|
||
t.Errorf("ожидалось информационное сообщение об отсутствии денег")
|
||
}
|
||
}
|