Skip to content

Commit 3fe0db3

Browse files
author
Daniel Barclay
committed
ManualTicTacToe: Added initial GameUITest (runGame only; no internal mocking/spying.
1 parent 74cc072 commit 3fe0db3

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

src/main/scala/com/us/dsb/explore/algs/ttt/manual/GameState.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object GameState {
1818

1919
def initial(startingPlayer: Player): GameState =
2020
GameState(Board.initial, None, startingPlayer)
21-
def initial: GameState = initial(Player.O)
21+
def initial: GameState = initial(Player.X)
2222
}
2323

2424
/**
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.us.dsb.explore.algs.ttt.manual
2+
3+
import com.us.dsb.explore.algs.ttt.manual.GameUI.{GameUIResult, UserTextIO}
4+
import org.scalatest.funspec.AnyFunSpec
5+
import org.scalatest.matchers.should.Matchers._
6+
7+
8+
class GameUITest extends AnyFunSpec {
9+
10+
class CrudeManualStubIO(inputs: String*) extends UserTextIO {
11+
12+
private var remainingInputs = inputs.toList
13+
14+
override def readLine(): String = {
15+
val thisInput :: laterInputs = remainingInputs
16+
remainingInputs = laterInputs
17+
Predef.println(s"readLine(): returning; '''${thisInput}'''")
18+
thisInput
19+
}
20+
21+
override def print(lineOrPart: String): Unit = {
22+
Predef.println(s"print(String): not checking; '''${lineOrPart}'''")
23+
}
24+
25+
override def println(fullLine: String): Unit = {
26+
Predef.println(s"println(String): not checking; '''${fullLine}'''")
27+
}
28+
29+
}
30+
31+
private def runStrings(inputs: String*): String =
32+
GameUI.runGame(new CrudeManualStubIO(inputs: _*)).text
33+
private def runChars(inputChars: String): String =
34+
runStrings(inputChars.map("" + _): _*)
35+
36+
37+
describe("runGame:") {
38+
describe("'q' should quit (result in message mentioning \"quit\"):") {
39+
40+
it("'q' as first command") {
41+
runStrings("q") should include regex ("(?i)quit")
42+
}
43+
44+
}
45+
describe("""X win should report X won; text should:""") {
46+
lazy val result = runChars("mdmrmdmrm") // X--/OX-/-OX
47+
it("""mention "win""") {
48+
result should include regex "(?i)W[o]n"
49+
}
50+
it("""mention X""") {
51+
result should include ("X")
52+
}
53+
it("""not mention O (probably)""" ) { // not if "X beat O"
54+
result should not include ("O")
55+
}
56+
it("""be "Player X won" (currently) """) {
57+
result should be ("Player X won")
58+
}
59+
}
60+
describe("""O win should report O won; text should:""") {
61+
lazy val result = runChars("m rm dlm rm rm dlm") // XO-/XOX/--O
62+
it("""mention win, O, and not X (probably)""") {
63+
result should (
64+
include regex ("(?i)W[o]n")
65+
and include ("O")
66+
and not include ("X")
67+
)
68+
}
69+
it("""be "Player O won" (currently) """) {
70+
result should be ("Player O won")
71+
}
72+
}
73+
describe("draw should report draw; text should:") {
74+
/*
75+
(1, 1) - m
76+
(2, 1) - dm
77+
(1, 2) - urm
78+
(2, 2) - dm
79+
(3, 1) - dlm
80+
(1, 3) - uurrm
81+
(2, 3) - dm
82+
(3, 3) - dm
83+
(3, 2) - lm
84+
*/
85+
lazy val actual = runChars("m" + "dm" + "urm" + "dm" + "dlm" + "uurrm" + "dm" + "dm" + "lm")
86+
87+
it("""mention "draw""") {
88+
actual should include regex "(?i)Draw"
89+
}
90+
it("""be "Game ended in draw" (currently)""") {
91+
actual should be ("Game ended in draw")
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)