Mi sto facendo strada verso la scala TDD e sono arrivato a un punto in cui mi piacerebbe ricevere consigli sulla "prossima mossa". Mi rendo conto che potrebbe non esserci una sola risposta qui, quindi qualsiasi suggerimento logico sarebbe fantastico.
La cosa su cui penso di essere bloccata è sapere che tempo dovrei forzare la duplicazione o procedere con la funzionalità primaria implementata dal codice minimo (e temporaneo dovuto a non essere generale).
Sto provando ad andare in un rigoroso ciclo verde / rosso / ri-fattore. Inoltre, questo esempio è così semplice che non richiede alcun oggetto mocked, ma penso che sia ancora un esempio valido (correggimi se ho torto o sono entrato in una sorta di caso banale che non vale la pena lavorare con) .
UPDATE : ho continuato con questo quasi alla conclusione, quindi suppongo che lascerò perdere e vedere se qualcuno ha dei commenti e se no lo cancellerò ..
Test:
using NSpec;
namespace TicTacToe
{
public class new_game : nspec
{
protected TicTacToeGame game;
private void before_each()
{
game = new TicTacToeGame();
}
private void when_game_starts()
{
it["board should be clear"] = () => game.BoardState.should_be("---,---,---");
it["it's x's turn"] = () => game.PlayerUp.should_be('x');
it["no winner yet"] = () => game.Winner.should_be('-');
}
}
public class specify_game : new_game
{
private void first_move()
{
context["is x in the center"] = () =>
{
act = () => game.Move('x', 2, 2);
it["board should have x in the center"] = () => game.BoardState.should_be("---,-x-,---");
it["it's y's turn"] = () => game.PlayerUp.should_be('y');
context["then y in the center"] =
() =>
{
it["should throw OtherPlayerOccupiesSpaceException"] =
expect<OtherPlayerOccupiesSpaceException>(() => game.Move('y', 2, 2));
it["no winner yet"] = () => game.Winner.should_be('-');
};
context["then y in the upper left"] = () =>
{
act = () => game.Move('y', 1, 1);
const string expectedBoardState = "y--,-x-,---";
it["correct board state is " + expectedBoardState] = () => game.BoardState.should_be(expectedBoardState);
it["it's x's turn"] = () => game.PlayerUp.should_be('x');
it["no winner yet"] = () => game.Winner.should_be('-');
context["then x in the middle top"] = () =>
{
act = () => game.Move('x', 1, 2);
const string expectedBoardState2 = "yx-,-x-,---";
it["correct board state is " + expectedBoardState2] = () => game.BoardState.should_be(expectedBoardState2);
it["no winner yet"] = () => game.Winner.should_be('-');
context["then y in the right top"] = () =>
{
act = () => game.Move('y', 1, 3);
const string expectedBoardState3 = "yxy,-x-,---";
it["correct board state is " + expectedBoardState3] = () => game.BoardState.should_be(expectedBoardState3);
it["no winner yet"] = () => game.Winner.should_be('-');
context["then x in the middle bottom"] = () =>
{
act = () => game.Move('x', 3, 2);
const string expectedBoardState4 = "yxy,-x-,-x-";
it["correct board state is " + expectedBoardState4] = () => game.BoardState.should_be(expectedBoardState4);
it["x wins"] = () => game.Winner.should_be('x');
};
};
};
};
};
context["is y int the center"] =
() =>
{
it["should throw NotYourTurnException"] =
expect<NotYourTurnException>(() => game.Move('y', 2, 2));
};
}
}
}
Implementazione:
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace TicTacToe
{
public class TicTacToeGame
{
private readonly char[,] grid = new char[3,3];
private bool xsTurn = true;
public TicTacToeGame()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
grid[i, j] = '-';
}
}
}
public string BoardState
{
get
{
var sb = new StringBuilder();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
sb.Append(grid[i, j]);
}
if (i < 2)
sb.Append(',');
}
return sb.ToString();
}
}
public char PlayerUp
{
get { return xsTurn ? 'x' : 'y'; }
}
public void Move(char player, int down, int over)
{
over -= 1;
down -= 1;
if (player != PlayerUp)
throw new NotYourTurnException();
if (grid[down, over] != '-')
throw new OtherPlayerOccupiesSpaceException();
this.grid[down, over] = player;
xsTurn = !xsTurn;
}
public char Winner
{
get
{
string boardState = BoardState;
var xWins = new[]
{
"xxx,...,...",
"...,xxx,...",
"...,...,xxx",
"x..,x..,x..",
".x.,.x.,.x.",
"x..,x..,x..",
"..x,..x,..x",
"x..,.x.,..x",
"..x,.x.,x..",
};
var yWins = new[]
{
"yyy,...,...",
"...,yyy,...",
"...,...,yyy",
"y..,y..,y..",
".y.,.y.,.y.",
"y..,y..,y..",
"..y,..y,..y",
"y..,.y.,..y",
"..y,.y.,y..",
};
if (xWins.Any(win => Regex.IsMatch(boardState, win)))
return 'x';
if (yWins.Any(win => Regex.IsMatch(boardState, win)))
return 'y';
return '-';
}
}
}
}
Output:
PM> NSpecRunner.exe .\TicTacToe\bin\Debug\TicTacToe.dll
new game
when game starts
board should be clear
it's x's turn
no winner yet
specify game
first move
is x in the center
board should have x in the center
it's y's turn
then y in the center
should throw OtherPlayerOccupiesSpaceException
no winner yet
then y in the upper left
correct board state is y--,-x-,---
it's x's turn
no winner yet
then x in the middle top
correct board state is yx-,-x-,---
no winner yet
then y in the right top
correct board state is yxy,-x-,---
no winner yet
then x in the middle bottom
correct board state is yxy,-x-,-x-
x wins
is y int the center
should throw NotYourTurnException
17 Examples, 0 Failed, 0 Pending