Intentional practice is something that is strongly advocated at the company I work for. What we do as intentional practice changes from time to time, but over the last few months we have spent a fair bit of time solving and resolving various kata's.
Here is what I eventually ended up with after numerous runs of the Tennis Kata.
Firstly, the code:
public class Game
{
private readonly Point _servicePoint = new Point();
private readonly Point _receiverPoint = new Point();
public string Score
{
get
{
if (_servicePoint.ToString().Equals(Point.FORTY)
&& (_receiverPoint.ToString().Equals(Point.FORTY)))
{
return "DEUCE";
}
return string.Format("{0}-{1}", _servicePoint, _receiverPoint);
}
}
public void ScoreToService()
{
_servicePoint.Score(_receiverPoint);
}
public void ScoreToReceiver()
{
_receiverPoint.Score(_servicePoint);
}
}
public class Point
{
public const string LOVE = "0";
public const string FIFTEEN = "15";
public const string THIRTY = "30";
public const string FORTY = "40";
public const string GAME = "GAME";
public const string ADVANTAGE = "ADV";
private string _score = LOVE;
private Dictionary> _pointMap;
public Point()
{
BuildPointMap();
}
public override string ToString()
{
return _score;
}
public void Score(Point opponentPoint)
{
_pointMap[_score].Invoke(opponentPoint);
}
private void BuildPointMap()
{
_pointMap = new Dictionary>
{
{Point.LOVE, o => { _score = Point.FIFTEEN; }},
{Point.FIFTEEN, o => { _score = Point.THIRTY; }},
{Point.THIRTY, o => { _score = Point.FORTY; }},
{
Point.FORTY, o =>
{
if (o.ToString().Equals(Point.FORTY))
{
_score = ADVANTAGE;
}
else
{
_score = o.ToString().Equals(Point.ADVANTAGE)
? FORTY
: GAME;
}
}
},
{Point.ADVANTAGE, o => { _score = GAME; }},
{Point.GAME, o =>
{
throw new ApplicationException("Game already completed!");
}
}
};
}
}
And the tests:
[TestFixture]
public class TestGame
{
[Test]
public void NewGame_ShouldSetScore_0_0()
{
//---------------Set up test pack-------------------
//---------------Assert Precondition----------------
//---------------Execute Test ----------------------
var game = new Game();
//---------------Test Result -----------------------
Assert.IsNotNull(game);
Assert.AreEqual("0-0", game.Score);
}
[Test]
public void ScoreToService_When_0_0_ShouldSetScore_15_0()
{
//---------------Set up test pack-------------------
var game = new Game();
//---------------Assert Precondition----------------
Assert.AreEqual("0-0", game.Score);
//---------------Execute Test ----------------------
game.ScoreToService();
//---------------Test Result -----------------------
Assert.AreEqual("15-0", game.Score);
}
[Test]
public void ScoreToReceiver_When_0_0_ShouldSetScore_0_15()
{
//---------------Set up test pack-------------------
var game = new Game();
//---------------Assert Precondition----------------
Assert.AreEqual("0-0", game.Score);
//---------------Execute Test ----------------------
game.ScoreToReceiver();
//---------------Test Result -----------------------
Assert.AreEqual("0-15", game.Score);
}
[Test]
public void ScoreToReceiver_When_15_15_ShouldSetScore_15_30()
{
//---------------Set up test pack-------------------
var game = new Game();
game.ScoreToService();
game.ScoreToReceiver();
//---------------Assert Precondition----------------
Assert.AreEqual("15-15", game.Score);
//---------------Execute Test ----------------------
game.ScoreToReceiver();
//---------------Test Result -----------------------
Assert.AreEqual("15-30", game.Score);
}
[Test]
public void ScoreToService_When_40_15_ShouldSetScore_GAME_15()
{
//---------------Set up test pack-------------------
var game = new Game();
game.ScoreToService();
game.ScoreToService();
game.ScoreToService();
game.ScoreToReceiver();
//---------------Assert Precondition----------------
Assert.AreEqual("40-15", game.Score);
//---------------Execute Test ----------------------
game.ScoreToService();
//---------------Test Result -----------------------
Assert.AreEqual("GAME-15", game.Score);
}
[Test]
public void ScoreToService_When_30_40_ShouldSetScore_DEUCE()
{
//---------------Set up test pack-------------------
var game = new Game();
game.ScoreToService();
game.ScoreToService();
game.ScoreToReceiver();
game.ScoreToReceiver();
game.ScoreToReceiver();
//---------------Assert Precondition----------------
Assert.AreEqual("30-40", game.Score);
//---------------Execute Test ----------------------
game.ScoreToService();
//---------------Test Result -----------------------
Assert.AreEqual("DEUCE", game.Score);
}
[Test]
public void ScoreToService_When_DEUCE_ShouldSetScore_ADV_40()
{
//---------------Set up test pack-------------------
var game = new Game();
game.ScoreToService();
game.ScoreToService();
game.ScoreToService();
game.ScoreToReceiver();
game.ScoreToReceiver();
game.ScoreToReceiver();
//---------------Assert Precondition----------------
Assert.AreEqual("DEUCE", game.Score);
//---------------Execute Test ----------------------
game.ScoreToService();
//---------------Test Result -----------------------
Assert.AreEqual("ADV-40", game.Score);
}
[Test]
public void ScoreToReceiver_When_40_ADV_ShouldSetScore_40_GAME()
{
//---------------Set up test pack-------------------
var game = new Game();
game.ScoreToService();
game.ScoreToService();
game.ScoreToService();
game.ScoreToReceiver();
game.ScoreToReceiver();
game.ScoreToReceiver();
game.ScoreToReceiver();
//---------------Assert Precondition----------------
Assert.AreEqual("40-ADV", game.Score);
//---------------Execute Test ----------------------
game.ScoreToReceiver();
//---------------Test Result -----------------------
Assert.AreEqual("40-GAME", game.Score);
}
[Test]
public void ScoreToReceiver_When_DEUCE_ShouldSetScore_40_ADV()
{
//---------------Set up test pack-------------------
var game = new Game();
game.ScoreToService();
game.ScoreToService();
game.ScoreToService();
game.ScoreToReceiver();
game.ScoreToReceiver();
game.ScoreToReceiver();
//---------------Assert Precondition----------------
Assert.AreEqual("DEUCE", game.Score);
//---------------Execute Test ----------------------
game.ScoreToReceiver();
//---------------Test Result -----------------------
Assert.AreEqual("40-ADV", game.Score);
}
}
[TestFixture]
public class TestPoint
{
// ReSharper disable InconsistentNaming
[Test]
public void NewPoint_ShouldSetToString_0()
{
//---------------Set up test pack-------------------
//---------------Assert Precondition----------------
//---------------Execute Test ----------------------
var point = new Point();
//---------------Test Result -----------------------
Assert.IsNotNull(point);
Assert.AreEqual(Point.LOVE, point.ToString());
}
[Test]
public void Score_When_0_ShouldSetToString_15()
{
//---------------Set up test pack-------------------
var point = new Point();
//---------------Assert Precondition----------------
Assert.AreEqual(Point.LOVE, point.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(new Point());
//---------------Test Result -----------------------
Assert.AreEqual(Point.FIFTEEN, point.ToString());
}
[Test]
public void Score_When_15_ShouldSetToString_30()
{
//---------------Set up test pack-------------------
var point = new Point();
point.Score(new Point());
//---------------Assert Precondition----------------
Assert.AreEqual(Point.FIFTEEN, point.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(new Point());
//---------------Test Result -----------------------
Assert.AreEqual(Point.THIRTY, point.ToString());
}
[Test]
public void Score_When_30_ShouldSetToString_40()
{
//---------------Set up test pack-------------------
var point = new Point();
point.Score(new Point());
point.Score(new Point());
//---------------Assert Precondition----------------
Assert.AreEqual(Point.THIRTY, point.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(new Point());
//---------------Test Result -----------------------
Assert.AreEqual(Point.FORTY, point.ToString());
}
[Test]
public void Score_When_40_ShouldSetToString_GAME()
{
//---------------Set up test pack-------------------
var point = new Point();
point.Score(new Point());
point.Score(new Point());
point.Score(new Point());
//---------------Assert Precondition----------------
Assert.AreEqual(Point.FORTY, point.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(new Point());
//---------------Test Result -----------------------
Assert.AreEqual(Point.GAME, point.ToString());
}
[Test]
public void Score_When_40_40_ShouldSetToString_ADV()
{
//---------------Set up test pack-------------------
var point = new Point();
var opponentPoint = new Point();
point.Score(opponentPoint);
point.Score(opponentPoint);
point.Score(opponentPoint);
opponentPoint.Score(point);
opponentPoint.Score(point);
opponentPoint.Score(point);
//---------------Assert Precondition----------------
Assert.AreEqual(Point.FORTY, point.ToString(), "PRE CONDITION");
Assert.AreEqual(Point.FORTY, opponentPoint.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(opponentPoint);
//---------------Test Result -----------------------
Assert.AreEqual(Point.ADVANTAGE, point.ToString());
}
[Test]
public void Score_When_40_ADV_ShouldSetToString_40()
{
//---------------Set up test pack-------------------
var point = new Point();
var opponentPoint = new Point();
point.Score(opponentPoint);
point.Score(opponentPoint);
point.Score(opponentPoint);
opponentPoint.Score(point);
opponentPoint.Score(point);
opponentPoint.Score(point);
opponentPoint.Score(point);
//---------------Assert Precondition----------------
Assert.AreEqual(Point.FORTY, point.ToString(), "PRE CONDITION");
Assert.AreEqual(Point.ADVANTAGE, opponentPoint.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(opponentPoint);
//---------------Test Result -----------------------
Assert.AreEqual(Point.FORTY, point.ToString());
}
[Test]
public void Score_When_ADV_40_ShouldSetToString_GAME()
{
//---------------Set up test pack-------------------
var point = new Point();
var opponentPoint = new Point();
point.Score(opponentPoint);
point.Score(opponentPoint);
point.Score(opponentPoint);
opponentPoint.Score(point);
opponentPoint.Score(point);
opponentPoint.Score(point);
point.Score(opponentPoint);
//---------------Assert Precondition----------------
Assert.AreEqual(Point.ADVANTAGE, point.ToString(), "PRE CONDITION");
Assert.AreEqual(Point.FORTY, opponentPoint.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
point.Score(opponentPoint);
//---------------Test Result -----------------------
Assert.AreEqual(Point.GAME, point.ToString());
}
[Test]
public void Score_When_GAME_0_ShouldError()
{
//---------------Set up test pack-------------------
var point = new Point();
var opponentPoint = new Point();
point.Score(opponentPoint);
point.Score(opponentPoint);
point.Score(opponentPoint);
point.Score(opponentPoint);
//---------------Assert Precondition----------------
Assert.AreEqual(Point.GAME, point.ToString(), "PRE CONDITION");
//---------------Execute Test ----------------------
var ex = Assert.Throws(() => point.Score(opponentPoint));
//---------------Test Result -----------------------
StringAssert.Contains("Game already completed!", ex.Message);
}
}