package main import "testing" func TestGoModelPlayStoneViaKey(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) m.cursor = GoPos{Row: 4, Col: 4} next, _ := m.Update(key("enter")) m = next.(GoModel) if m.isError { t.Fatalf("неожиданная ошибка: %s", m.message) } if m.game.Board[4][4] != GoBlack { t.Fatalf("камень должен был встать в (4,4) как чёрный") } } func TestGoModelCursorMovement(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) m.cursor = GoPos{Row: 4, Col: 4} next, _ := m.Update(key("up")) m = next.(GoModel) if m.cursor.Row != 3 { t.Errorf("курсор должен был сдвинуться вверх") } next, _ = m.Update(key("right")) m = next.(GoModel) if m.cursor.Col != 5 { t.Errorf("курсор должен был сдвинуться вправо") } } func TestGoModelCursorClampsAtEdges(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) m.cursor = GoPos{Row: 0, Col: 0} next, _ := m.Update(key("up")) m = next.(GoModel) if m.cursor.Row != 0 { t.Errorf("курсор не должен был уйти за верхний край") } next, _ = m.Update(key("left")) m = next.(GoModel) if m.cursor.Col != 0 { t.Errorf("курсор не должен был уйти за левый край") } } func TestGoModelPassViaKey(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) next, _ := m.Update(key("p")) m = next.(GoModel) if m.isError { t.Fatalf("неожиданная ошибка паса: %s", m.message) } } func TestGoModelInvalidMoveShowsError(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) m.cursor = GoPos{Row: 0, Col: 0} m.game.Board[0][0] = GoBlack next, _ := m.Update(key("enter")) m = next.(GoModel) if !m.isError { t.Fatalf("ожидалась ошибка хода на занятую точку") } } func TestGoModelQReturnsToMenu(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) next, _ := m.Update(key("q")) m = next.(GoModel) if !m.backToMenu { t.Fatalf("ожидался флаг backToMenu после 'q'") } if m.quitting { t.Fatalf("'q' не должен закрывать всё приложение") } } func TestGoModelNewGameAfterResult(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) m.game.Result = &GoResult{Winner: GoBlack, BlackScore: 10, WhiteScore: 7.5} next, _ := m.Update(key("n")) m = next.(GoModel) if m.game.Result != nil { t.Errorf("новая партия не должна была начаться с результатом") } if m.game.Size != 9 { t.Errorf("новая партия должна была сохранить размер доски") } } func TestGoModelSupportsAllBoardSizes(t *testing.T) { for _, size := range []int{9, 13, 19} { m := NewGoModel(size, GoDifficultyMedium) if m.game.Size != size { t.Errorf("ожидался размер доски %d, получено %d", size, m.game.Size) } } } // TestGoModelFullAutoPlaythrough прогоняет TUI-модель от начала до // конца на маленькой доске, где "человек" отыгрывает свои ходы // через бота, проверяя, что весь путь через Update не паникует и // партия завершается. func TestGoModelFullAutoPlaythrough(t *testing.T) { m := NewGoModel(9, GoDifficultyEasy) helperBot := GoBot{Difficulty: GoDifficultyEasy} rnd := m.rnd const maxSteps = 3000 for i := 0; i < maxSteps && m.game.Result == nil; i++ { if m.game.Turn != m.human { next, _ := m.Update(botMoveMsg{}) m = next.(GoModel) continue } pos, ok := helperBot.DecideMove(m.game, rnd) if !ok { next, _ := m.Update(key("p")) m = next.(GoModel) continue } m.cursor = pos next, _ := m.Update(key("enter")) m = next.(GoModel) if m.isError { t.Fatalf("неожиданная ошибка хода человеком: %s", m.message) } } if m.game.Result == nil { t.Fatalf("партия через TUI не завершилась за %d шагов", maxSteps) } }