Let’s see. I didn’t write a .NET post for a long time, and I am posting a fun project which is a Robot Cleaner that I had implemented in C#.NET.
Although this is a trivial project, it requires a simple understanding of TDD and at that time, my TDD experience in .NET was limited.
Now, let’s check how one can create a test project in .NET:
Simple, eh? Note that above is a simple test project creation and below is showing where you can find your test cases.
You can simply right click on a case and run it and see what happens as follows. Note that the running will yield, a pass or fail according to the test conditions.
Now, let’s check for the domain and the needs of this domain:
Robot Cleaner
Background
When you have a lot of people working in an office it can get dirty quite quickly if you’re not careful. However, cleaning staff are expensive. To save money on cleaning staff the best solution was deemed to be the creation of an automatic cleaning robot that cleans the office at night.
Assignment
Your assignment is to build a prototype of this robot. The assignment is designed to be as simple as possible. The robot will, once given some instructions (shown below as input), run on its own without any human interference. In the morning we can ask the robot to report how many unique places in the office it has cleaned.
Input and Output Criteria
- All input will be given on standard in.
- All output is expected on standard out.
- First input line: a single integer that represents the number of commands the robot should expect to execute before it knows it is done. The number will be in the range n (0 : n : 10, 000).
- Second input line: consists of two integer numbers that represents the starting coordinates x y of the robot. The value of each coordinate will be in the range x (-100, 000 : x : 100, 000) and y (-100, 000 : y : 100, 000).
- The third, and any subsequent line, will consist of two pieces of data. The first will be a single uppercase character C E {E, W,5, N}, that represents the direction on the compass the robot should head. The second will be an integer representing the number of steps s (0 <s < 100,000) that the robot should take in said direction.
Special Notes
- The robot will never be sent outside the bounds of the plane.
- All input should be considered well formed and syntactically correct. There is no need, therefore, to implement elaborate input parsing.
- Do not output any error messages. See previous point. The only output should be the number of unique places that the robot cleaned. See below.
- There will no leading or trailing white space on any line of input.
- There should be no leading or trailing whitespace on any line of output.
- Any multi-valued line of input will have a single white space character between each value.
- You can assume, for the sake of simplicity, that the office can be viewed as a grid where the robot moves only on the vertices.
- The robot cleans at every vertex it touches not just where it stops.
The Output
The output of your program should be a number u, which represents the number of unique places in the office that were cleaned. The output of the number u should be prefixed by 1=> Cleaned: 1, (excluding the quotes).
Example input:
10 22 E2 N1
Example output:
=> Cleaned: 4
Now, let’s check for the trivial implemetation but first, couple of word regarding TDD:
TDD designates Test Driven Development in a such way that you code for testing reasons. This effectively means you are designing your algorithm in a test driven approach. You can read lots of papers about it, but this post will give you a faster recognition of what I am doing.
There are lots of testing approaches and I may mention those later on another post. Now, let’s focus on the coding style. Note that, the code may seem overcommented. I did the commenting since I don’t want to populate a confusion here in the post.
This project is implemented in VS2010-Ultimate. You can run this project also in VS2012 without a glitch, but to run this in VS2008 or VS2005, you cannot simply run it because while loading the project in those environments, it will pop up error, but there is a simple way to fix this, all you need is to change the version of the VS in Foo.sln where Foo is the solution name. In the following sln file, all you need to change is the first line version, Microsoft Visual Studio Solution File, Format Version 11.00 to 10.00 or 9.00.
Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobotCleaner.Application", "RobotCleaner.Application\RobotCleaner.Application.csproj", "{96BF0E94-A85E-4AEC-AA44-0777D742DF00}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "com.cint.RobotCleaner", "com.cint.RobotCleaner", "{C1D1EA87-A74F-491B-8C42-35562D33A8B6}" ProjectSection(SolutionItems) = preProject ..\..\..\..\..\Instructions .pdf = ..\..\..\..\..\Instructions .pdf EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobotCleaner.Test", "RobotCleaner.Test\RobotCleaner.Test.csproj", "{F606FDEA-9BB4-4626-83DC-C1ED4A29643C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9AC17769-BD0A-4DB7-A828-2FC47533314B}" ProjectSection(SolutionItems) = preProject Local.testsettings = Local.testsettings RobotCleaner.vsmdi = RobotCleaner.vsmdi TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobotCleaner.Entity", "RobotCleaner.Entity\RobotCleaner.Entity.csproj", "{FBAE4384-2EC3-4204-B80A-47B321BF68E2}" EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = RobotCleaner.vsmdi EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Debug|Any CPU.ActiveCfg = Debug|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Debug|Mixed Platforms.Build.0 = Debug|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Debug|x86.ActiveCfg = Debug|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Debug|x86.Build.0 = Debug|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Release|Any CPU.ActiveCfg = Release|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Release|Mixed Platforms.ActiveCfg = Release|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Release|Mixed Platforms.Build.0 = Release|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Release|x86.ActiveCfg = Release|x86 {96BF0E94-A85E-4AEC-AA44-0777D742DF00}.Release|x86.Build.0 = Release|x86 {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Debug|Any CPU.Build.0 = Debug|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Debug|x86.ActiveCfg = Debug|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Release|Any CPU.ActiveCfg = Release|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Release|Any CPU.Build.0 = Release|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Release|Mixed Platforms.Build.0 = Release|Any CPU {F606FDEA-9BB4-4626-83DC-C1ED4A29643C}.Release|x86.ActiveCfg = Release|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Debug|x86.ActiveCfg = Debug|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Release|Any CPU.Build.0 = Release|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Release|Mixed Platforms.Build.0 = Release|Any CPU {FBAE4384-2EC3-4204-B80A-47B321BF68E2}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {96BF0E94-A85E-4AEC-AA44-0777D742DF00} = {C1D1EA87-A74F-491B-8C42-35562D33A8B6} {F606FDEA-9BB4-4626-83DC-C1ED4A29643C} = {C1D1EA87-A74F-491B-8C42-35562D33A8B6} {9AC17769-BD0A-4DB7-A828-2FC47533314B} = {C1D1EA87-A74F-491B-8C42-35562D33A8B6} {FBAE4384-2EC3-4204-B80A-47B321BF68E2} = {C1D1EA87-A74F-491B-8C42-35562D33A8B6} EndGlobalSection EndGlobal
Now, let’s aim for our need. There may be lots of way, but I prefer more structured way in every of my implementations. In this solution, as you can see, there are 3 projects, all of which are in a folder named as com.cint.RobotCleaner
/* * * * * * * * * * * * * * * * * * * * * * Company: CINT * * Assignment: Robot Cleaner * * Deadline: 2012-02-11 * * Programmer: Baran Topal * * Solution name: Cint.RobotCleaner * * Folder name: com.cint.RobotCleaner * * Project name: RobotCleaner.Entity * * File name: WorkItem.cs * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LICENSE: This source file is subject to have the protection of GNU General * * Public License. You can distribute the code freely but storing this license information. * * Contact Baran Topal if you have any questions. jazzIIIlove@gmail.com || topal@kth.se * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using System; using System.Collections.Generic; using System.Linq; using System.Text; //entity to store the workitem and position in given coordinates namespace RobotCleaner.Entity { ////// WorkItem class dealing with the places visited, /// current position of the robot and /// instructions given in the plane limits ///
public class WorkItem { #region member variables ///
public bool[,] Plane; ///
public Position CurrentPosition; ///
public int PlacesVisited; ///
public ListInstructions; #endregion member variables #region constructors ///
/// Important note: /// clr limit: 2 147 483 648 || 2GB = 2 x 1024 x 1024 x 1024 /// assignment array size: 40 000 000 000 || 200000 x 200000 /// I have to go for a simplification for the need and i omit one ‘0’ in each dimension. public WorkItem() { Instructions = new List(); Plane = new bool[20001, 20001]; PlacesVisited = 0; } ///
//////public WorkItem(Position startingPosition, List instructions) { Plane = new bool[20001, 20001]; Move(startingPosition); Instructions = instructions; } #endregion constructors #region member methods ///
///position to be checked /// True if the position is inside the plane, false otherwise public static bool CanMove(Position position) { //return (position.X >= -10000 && position.X = -10000 && position.Y = 0 && position.X = 0 && position.Y
///Position to move public void Move(Position position) { if (!PositionAlreadyVisited(position)) { PlacesVisited++; } CurrentPosition = position; } ///
///Position to be checked /// True if the position is already visited, false otherwise public bool PositionAlreadyVisited(Position position) { if (Plane[position.X, position.Y]) return true; else { Plane[position.X, position.Y] = true; return false; } } ///
/// Places visited by the robotpublic int GetOutput() { FollowInstructions(); return PlacesVisited; } ///
public void FollowInstructions() { Move(CurrentPosition); for (int i = 0; i < Instructions.Count; i++) MoveRobot(Instructions[i]); } ///
///X and Y coordinates, e.g. “6 8” /// Position w.r.t. (0, 0) at center. public static Position GetPosition(string p) { //slitting input with the tokenizer char, ‘ ‘ string[] tokens = p.Split(‘ ‘); //initializing the Position object with the given splitted values return new Position((Int32.Parse(tokens[0]) + 10000), Int32.Parse(tokens[1]) + 10000); } ///
///number of commands /// public static int GetNumberOfCommands(string c) { return Int32.Parse(c); } ///
///private void MoveRobot(string instruction) { //slitting instruction with the tokenizer char, ‘ ‘ string[] tokens = instruction.Split(‘ ‘); //direction string direction = tokens[0]; //number of steps int steps = Int32.Parse(tokens[1]); switch (direction) { //Move north with the given number of steps case “N”: MoveNorth(steps); break; //Move south with the given number of steps case “S”: MoveSouth(steps); break; //Move east with the given number of steps case “E”: MoveEast(steps); break; //Move west with the given number of steps case “W”: MoveWest(steps); break; default: //None of above break; } } ///
///Number of steps private void MoveNorth(int steps) { //loop until the number of steps is reached for (int i = 0; i < steps; i++) { //New position Position position = new Position(CurrentPosition.X + 0, CurrentPosition.Y + 1); //Check whether it can move or not if (CanMove(position)) Move(position); else break; } } ///
///Number of steps private void MoveSouth(int steps) { //loop until the number of steps is reached for (int i = 0; i < steps; i++) { //New position Position position = new Position(CurrentPosition.X + 0, CurrentPosition.Y – 1); //Check whether it can move or not if (CanMove(position)) Move(position); else break; } } ///
///Number of steps private void MoveEast(int steps) { //loop until the number of steps is reached for (int i = 0; i < steps; i++) { //New position Position position = new Position(CurrentPosition.X + 1, CurrentPosition.Y + 0); //Check whether it can move or not if (CanMove(position)) Move(position); else break; } } ///
///Number of steps private void MoveWest(int steps) { //loop until the number of steps is reached for (int i = 0; i < steps; i++) { //New position Position position = new Position(CurrentPosition.X – 1, CurrentPosition.Y + 0); //Check whether it can move or not if (CanMove(position)) Move(position); else break; } } #endregion member methods } }
/* * * * * * * * * * * * * * * * * * * * * * Company: CINT * * Assignment: Robot Cleaner * * Deadline: 2012-02-11 * * Programmer: Baran Topal * * Solution name: Cint.RobotCleaner * * Folder name: com.cint.RobotCleaner * * Project name: RobotCleaner.Entity * * File name: Position.cs * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LICENSE: This source file is subject to have the protection of GNU General * * Public License. You can distribute the code freely but storing this license information. * * Contact Baran Topal if you have any questions. jazzIIIlove@gmail.com || topal@kth.se * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using System; using System.Collections.Generic; using System.Linq; using System.Text; //entity to store the workitem and position in given coordinates namespace RobotCleaner.Entity { ////// position class to store x, y member variables ///
public class Position { #region member variables ///
private int x; ///
private int y; #endregion member variables #region accessors ///
public int X { get { return x; } set { x = value; } } ///
public int Y { get { return y; } set { y = value; } } #endregion accessors #region constructors ///
//////public Position(int xPosition, int yPosition) { x = xPosition; y = yPosition; } #endregion constructors } }
/* * * * * * * * * * * * * * * * * * * * * * * * * Company: CINT * * Assignment: Robot Cleaner * * Deadline: 2012-02-11 * * Programmer: Baran Topal * * Solution name: Cint.RobotCleaner * * Folder name: com.cint.RobotCleaner * * Project name: RobotCleaner.Application * * File name: Program.cs * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LICENSE: This source file is subject to have the protection of GNU General * * Public License. You can distribute the code freely but storing this license information. * * Contact Baran Topal if you have any questions. jazzIIIlove@gmail.com || topal@kth.se * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using RobotCleaner.Entity; //Robot cleaner console application main gate namespace RobotCleaner { ////// Program to access to main gate ///
class Program { #region methods ///
///No cmd line argument expected static void Main(string[] args) { //Console.Write(“Enter the number of instructions: “); //user inputs the number of commands, e.g. 2 //int numberOfCommands = Int32.Parse(Console.ReadLine()); int numberOfCommands = WorkItem.GetNumberOfCommands(Console.ReadLine()); //Console.Write(“Enter the starting position: “); //user inputs the starting position for the robot, e.g. 10 22 Position startingPosition = WorkItem.GetPosition(Console.ReadLine()); //list to store the instructions given by the user List instructions = new List(); //Console.WriteLine(“Enter the instructions: “); //loop over the instructions and add each of them to the list, until the numberOfCommand is reached for (int i = 0; i < numberOfCommands; i++) { //Console.Write((i + 1) + “: “); instructions.Add(Console.ReadLine()); } //passing starting position and instructions of the robot WorkItem workItem = new WorkItem(startingPosition, instructions); //output after the process int output = workItem.GetOutput(); //Console.WriteLine(“Cleaned (Start Position counted): {0}”, output); Console.WriteLine(“=> Cleaned: {0}”, output); //output–; //Console.WriteLine(“Cleaned (Start Position neglected): {0}”, output); Console.ReadLine(); } #endregion methods } }
/* * * * * * * * * * * * * * * * * * * * * * Company: CINT * * Assignment: Robot Cleaner * * Deadline: 2012-02-11 * * Programmer: Baran Topal * * Solution name: Cint.RobotCleaner * * Folder name: com.cint.RobotCleaner * * Project name: RobotCleaner.Test * * File name: PositionTest.cs * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LICENSE: This source file is subject to have the protection of GNU General * * Public License. You can distribute the code freely but storing this license information. * * Contact Baran Topal if you have any questions. jazzIIIlove@gmail.com || topal@kth.se * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using System; using System.Text; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using RobotCleaner.Entity; //Test Project for Position and WorkItem namespace RobotCleaner.Test { ////// This is a test class for PositionTest and is intended /// to contain all PositionTest for unit tests. ///
[TestClass] public class PositionTest { #region member variables private TestContext testContextInstance; #endregion member variables #region constructors ///
public PositionTest() { // // TODO: Add constructor logic here // } #endregion constructors #region accessors ///
public TestContext TestContext { get { return testContextInstance; } set { testContextInstance = value; } } #endregion accessors #region member functions ///
[TestMethod] public void Set_X_Position_0_By_Constructor() { //Arrange int xPosition = 0; int yPosition = 0; //target position object Position target = new Position(xPosition, yPosition); //Actual var actual = target.X; //Assert Assert.AreEqual(xPosition, actual); } ///
[TestMethod] public void Set_Y_Position_0_By_Constructor() { //Arrange int xPosition = 0; int yPosition = 0; //target position object Position target = new Position(xPosition, yPosition); //Actual var actual = target.Y; //Assert Assert.AreEqual(yPosition, actual); } ///
[TestMethod] public void Set_X_Position_By_Constructor() { //Arrange int xPosition = 15; int yPosition = 0; //target position object Position target = new Position(xPosition, yPosition); //Actual var actual = target.X; //Assert Assert.AreEqual(xPosition, actual); } ///
[TestMethod] public void Set_Y_Position_By_Constructor() { //Arrange int xPosition = 0; int yPosition = 15; //target position object Position target = new Position(xPosition, yPosition); //Actual var actual = target.Y; //Assert Assert.AreEqual(yPosition, actual); } #endregion member functions } }
/* * * * * * * * * * * * * * * * * * * * * * Company: CINT * * Assignment: Robot Cleaner * * Deadline: 2012-02-11 * * Programmer: Baran Topal * * Solution name: Cint.RobotCleaner * * Folder name: com.cint.RobotCleaner * * Project name: RobotCleaner.Test * * File name: PositionTest.cs * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LICENSE: This source file is subject to have the protection of GNU General * * Public License. You can distribute the code freely but storing this license information. * * Contact Baran Topal if you have any questions. jazzIIIlove@gmail.com || topal@kth.se * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using System; using System.Text; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using RobotCleaner.Entity; //Test Project for Position and WorkItem namespace RobotCleaner.Test { ////// This is a test class for WorkItemTest and is intended /// to contain all WorkItemTest unit tests. ///
[TestClass] public class WorkItemTest { #region member functions ///
[TestMethod] public void WorkItem_Constructor_Sets_Everything() { //Arrange var placesVisited = 0; var instructionsCount = 0; //Actual var target = new WorkItem(); //Assert Assert.AreEqual(placesVisited, target.PlacesVisited); Assert.AreEqual(instructionsCount, target.Instructions.Count); } ///
[TestMethod] public void WorkItem_Constructor_With_Arguments() { //Arrange var startingPosition = WorkItem.GetPosition(“5 5”); Listinstructions = new List(); instructions.Add(“S 2”); var visitedPlaces = 1; //Actual var target = new WorkItem(startingPosition, instructions); //Assert Assert.AreEqual(startingPosition, target.CurrentPosition); Assert.AreEqual(instructions.Count, target.Instructions.Count); Assert.AreEqual(visitedPlaces, target.PlacesVisited); } ///
[TestMethod] public void CurrentPosition_Set_And_Get_Returns_Same() { //Arrange var expected = new Position(0, 0); var target = new WorkItem(); //Actual target.CurrentPosition = expected; var actual = target.CurrentPosition; //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void Instructions_Set_And_Get_Returns_Same() { //Arrange var expected = new List(); var target = new WorkItem(); //Actual target.Instructions = expected; var actual = target.Instructions; //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void GetOutput_Returns_Places_Visited() { //Arrange var expected = 3; var instructions = new List(); var position = new Position(5, 10); instructions.Add(“N 2”); var target = new WorkItem(position, instructions); //Actual var actual = target.GetOutput(); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void Follow_Instructions_Set_CurrentPosition() { //Arrange var expected = new Position(105, 110); var instructions = new List(); instructions.Add(“105 110”); var target = new WorkItem(expected, instructions); //Actual target.FollowInstructions(); var actual = target.CurrentPosition; //Assert Assert.AreEqual(expected.X, actual.X); Assert.AreEqual(expected.Y, actual.Y); } ///
[TestMethod] public void Follow_Instructions_Incremets_PlacesVisited() { //Arrange var expected = 1; var position = new Position(105, 110); var instructions = new List(); instructions.Add(“105 110”); var target = new WorkItem(position, instructions); //Actual target.FollowInstructions(); var actual = target.PlacesVisited; //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void GetPosition_Returns_Position_According_To_ZeroBase() { //Arrange var expected = new Position(10105, 10110); //Actual var actual = WorkItem.GetPosition(“105 110”); //Assert Assert.AreEqual(expected.X, actual.X); Assert.AreEqual(expected.Y, actual.Y); } ///
[TestMethod] public void GetInput_NumberOfCommands() { //Arrange var expected = 4; //Actual var actual = WorkItem.GetNumberOfCommands(“4”); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void Exceed_NumberOfCommands() { //Arrange bool notExceed = true; var expected = false; if (WorkItem.GetNumberOfCommands(“10001”) > 10000) { notExceed = false; } //Actual var actual = notExceed; //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_True() { //Arrange var expected = true; var position = new Position(100, 100); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_False_For_Negative_X() { //Arrange var expected = false; var position = new Position(-10001, 0); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_False_For_Negative_Y() { //Arrange var expected = false; var position = new Position(0, -10001); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_False_For_Negative_X_And_Y() { //Arrange var expected = false; var position = new Position(-10001, -10001); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_False_For_Greater_X() { //Arrange var expected = false; var position = new Position(20001, 0); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_False_For_Greater_Y() { //Arrange var expected = false; var position = new Position(0, 20001); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void CanMove_Returns_False_For_Greater_X_And_Y() { //Arrange var expected = false; var position = new Position(20001, 20001); //Actual var actual = WorkItem.CanMove(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void PositionAlreadyVisited_Returns_False_For_Unvisited_Place() { //Arrange var expected = false; var position = new Position(5, 5); var target = new WorkItem(); target.Plane[5, 5] = false; //Actual var actual = target.PositionAlreadyVisited(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void PositionAlreadyVisited_Sets_PositionVisited_If_Not_Visited() { //Arrange var expected = true; var position = new Position(5, 5); var target = new WorkItem(); target.PositionAlreadyVisited(position); //Actual var actual = target.Plane[5, 5]; //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void PositionAlreadyVisited_Returns_True_For_Visited_Place() { //Arrange var expected = true; var position = new Position(5, 5); var target = new WorkItem(); target.Plane[5, 5] = true; //Actual var actual = target.PositionAlreadyVisited(position); //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void Move_Sets_New_CurrentPosition() { //Arrange var expected = new Position(5, 5); var target = new WorkItem(); //Actual target.Move(expected); var actual = target.CurrentPosition; //Assert Assert.AreEqual(expected, actual); } ///
[TestMethod] public void Move_Increments_PlaceVisited_If_Position_Is_Not_Visited() { //Arrange var position = new Position(5, 5); var target = new WorkItem(); target.PlacesVisited = 0; var expected = target.PlacesVisited + 1; //Actual target.Move(position); var actual = target.PlacesVisited; //Assert Assert.AreEqual(expected, actual); } ///
public void Move_Dont_Increment_PlaceVisited_If_Position_Is_Visited() { //Arrange var position = new Position(5, 5); var target = new WorkItem(); target.PlacesVisited = 1; var expected = target.PlacesVisited; target.Plane[5, 5] = true; //Actual target.Move(position); var actual = target.PlacesVisited; //Assert Assert.AreEqual(expected, actual); } #endregion member functions } }
I also provide this in the public dropbox link:
https://dl.dropbox.com/u/1327371/RobotCleaner.rar