From: Steve F. <sm...@us...> - 2002-08-18 01:42:15
|
Update of /cvsroot/mockobjects/no-stone-unturned/doc/xdocs In directory usw-pr-cvs1:/tmp/cvs-serv2467/doc/xdocs Modified Files: doc-book.xml how_mocks_happened.xml htmlbook.css Log Message: more on how mocks happened Index: doc-book.xml =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/doc-book.xml,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- doc-book.xml 12 Aug 2002 23:10:20 -0000 1.10 +++ doc-book.xml 18 Aug 2002 01:42:12 -0000 1.11 @@ -78,21 +78,37 @@ </chapter> </part> - <part><title>Some other languages</title> + <part status="todo"> + <title>Some other languages</title> + &TODO; <chapter> - <title>C++</title> - &TODO; - <comment><para>with Workshare?</para></comment> + <title>Static languages</title> + <section> + <title>C++</title> + <comment><para>with Workshare?</para></comment> + </section> </chapter> <chapter> - <title>Dynamic and metaprogramming</title> - &TODO; + <title>Languages with reflection</title> + <section> + <title>C#</title> + </section> </chapter> + + <chapter> + <title>Dynamic languages</title> + <section> + <title>Ruby</title> + </section> + </chapter> + <chapter> - <title>bash</title> - &TODO; + <title>Scripts</title> + <section> + <title>bash</title> + </section> </chapter> </part> Index: how_mocks_happened.xml =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/how_mocks_happened.xml,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- how_mocks_happened.xml 17 Aug 2002 12:59:10 -0000 1.7 +++ how_mocks_happened.xml 18 Aug 2002 01:42:12 -0000 1.8 @@ -83,14 +83,13 @@ assertEquals("Should be destination", DESTINATION, robot.getCurrentPosition()); List moves = robot.getRecentMoveRequests(); assertEquals("Should be one move", 1, moves.size()); - assertEquals("Should be same move", - new MoveRequest(1, MoveRequest.SOUTH), moves.get(1)); + assertEquals("Should be same move", new MoveRequest(1, MoveRequest.SOUTH), moves.get(1)); }</programlisting> <sidebar> <para> Of course, you've noticed that we haven't said anything about the layout of the warehouse. We'll - assume for now that it's regular and hard-coded into the Robot. + assume for now that the Robot knows about it by some other mechanism. </para> </sidebar> @@ -240,6 +239,15 @@ assertEquals("Should be same", POSITION, robot.getCurrentPosition()); }</programlisting> + <sidebar> + <para> + I'm being inconsistent again by keeping <function>getCurrentPosition()</function>. In my defence, + it seems more reasonable to me that a robot should know its current position than that it should + keep a list of its recent movements. One day I'll replace this with a + <classname>CurrentPositionListener</classname>, or some such technique. Really I will. + </para> + </sidebar> + <para> We have just locked down a little piece of the specification. We can be sure that, however complex our routing code gets, the <classname>Robot</classname> will not move if asked to go to its current position. @@ -277,7 +285,7 @@ </para> <programlisting> -public void testMoveOnePoint() { +public void testMoveOneStep() { final Position DESTINATION = new Position(1, 0); Motor mockMotor = new Motor() { @@ -314,11 +322,11 @@ the <varname>moveCount</varname> field. </para> <programlisting> -static class AbstractMotorStub implements Motor { +<emphasis>static class AbstractMotorStub implements Motor { int moveCount = 0; -} +}</emphasis> -public void testMoveOnePoint() { +public void testMoveOneStep() { final Position DESTINATION = new Position(1, 0); AbstractMotorStub mockMotor = new AbstractMotorStub() { @@ -334,7 +342,7 @@ robot.goTo(DESTINATION); assertEquals("Should be destination", DESTINATION, robot.getCurrentPosition()); - assertEquals("Should be one move", 1, mockMotor.moveCount); + <emphasis>assertEquals("Should be one move", 1, mockMotor.moveCount);</emphasis> }</programlisting> <para> @@ -343,17 +351,17 @@ </para> <programlisting> -public RobotTest extends TestCase implements Motor { +public RobotTest extends TestCase <emphasis>implements Motor</emphasis> { - // Implementation of Motor + <emphasis>// Implementation of Motor private int moveCount = 0; public void move(MoveRequest request) { assertEquals("Should be move", new MoveRequest(1, MoveRequest.SOUTH), request); moveCount++; assertEquals("Should be first move", 1, moveCount); - } + }</emphasis> - public void testMoveOnePoint() { + public void testMoveOneStep() { final Position DESTINATION = new Position(1, 0); Robot robot = new Robot(this); @@ -361,7 +369,7 @@ robot.goTo(DESTINATION); assertEquals("Should be destination", DESTINATION, robot.getCurrentPosition()); - assertEquals("Should be one move", 1, moveCount); + <emphasis>assertEquals("Should be one move", 1, moveCount);</emphasis> } }</programlisting> @@ -381,40 +389,87 @@ <section> <title>Testing more than one step</title> - <!-- TODO --> <comment>Under development</comment> <para> - Now we want to test a route that requires two steps. + Now we want to test a route that takes two steps which we need to check. Our current test implementation + can only handle one step, so we need to introduce a collection. In this test we need to be sure that the + steps are taken in the right sequence, so we'll use an <classname>ArrayList</classname> to describe the + <classname>MoveRequest</classname>s that we expect the <classname>Robot</classname> to generate. + </para> + + <programlisting> +public void testMoveTwoSteps() { + ArrayList expectedMoveRequests = new ArrayList(); + + expectedMoveRequests.add(new MoveRequest(1, MoveRequests.SOUTH)); + expectedMoveRequests.add(new MoveRequest(2, MoveRequests.WEST); +}</programlisting> + + <para> + We can use to the <varname>expectedMoveRequests</varname> in the mock motor, and cross off the + actual move requests as they arrive. </para> + <programlisting> -public void testMoveOnePoint() { - final Position DESTINATION = new Position(1, 0); +public void testMoveTwoSteps() { + final ArrayList expectedMoveRequests = new ArrayList(); - AbstractMotorStub mockMotor = new AbstractMotorStub() { + <emphasis>Motor mockMotor = new Motor() { public void move(MoveRequest request) { - assertEquals("Should be move", new MoveRequest(1, MoveRequest.SOUTH), request); - moveCount++; - assertEquals("Should be first move", 1, moveCount); + assertEquals("Should be move", expectedMoveRequests.remove(0), request); } - }; + };</emphasis> + + expectedMoveRequests.add(new MoveRequest(1, MoveRequests.SOUTH)); + expectedMoveRequests.add(new MoveRequest(2, MoveRequests.WEST)); Robot robot = new Robot(mockMotor); + robot.setCurrentPosition(new Position(0, 0)); - robot.goTo(DESTINATION); + robot.goTo(new Position(-1, 2)); - assertEquals("Should be destination", DESTINATION, robot.getCurrentPosition()); - assertEquals("Should be one move", 1, mockMotor.moveCount); + assertEquals("Should be destination", new Position(-1, 2), robot.getCurrentPosition()); }</programlisting> + <para> + Which will fail if the robot asks the mock motor to make an incorrect move. We need to add a little more + code to handle the cases where the robot generates too many or too few steps. + </para> + + <programlisting> +public void testMoveTwoSteps() { + final ArrayList expectedMoveRequests = new ArrayList(); + + Motor mockMotor = new Motor() { + public void move(MoveRequest request) { + <emphasis>try {</emphasis> + assertEquals("Should be move", expectedMoveRequests.remove(0), request); + <emphasis>} catch (IndexOutOfBoundsException ex) { + fail("Should be more moves"); + }</emphasis> + } + }; + + expectedMoveRequests.add(new MoveRequest(1, MoveRequests.SOUTH)); + expectedMoveRequests.add(new MoveRequest(2, MoveRequests.WEST)); + + Robot robot = new Robot(mockMotor); + + robot.setCurrentPosition(new Position(0, 0)); + robot.goTo(new Position(-1, 2)); + + assertEquals("Should be destination", new Position(-1, 2), robot.getCurrentPosition()); + <emphasis>assertEquals("Should be no more moves", 0, expectedMoveRequests.size());</emphasis> +}</programlisting> <para> - Third, we could change the way we hold our move requests, we can let the + Now we have a technique that will test any sequence of steps that we need, including one step or none. We + can rework our original tests for consistency. </para> <programlisting> -public void testMoveOnePoint() { +public void testMoveOneStep() { final Position DESTINATION = new Position(1, 0); - final ArrayList expectedMoveRequests = new ArrayList(); Motor mockMotor = new Motor() { public void move(MoveRequest request) { @@ -425,31 +480,47 @@ } } }; - Robot robot = new Robot(mockMotor); - expectedMoveRequests.add(new MoveRequest(1, MoveRequest.SOUTH)); + expectedMoveRequests.add( new MoveRequest(1, MoveRequest.SOUTH)); + + Robot robot = new Robot(mockMotor); robot.setCurrentPosition(new Position(0, 0)); robot.goTo(DESTINATION); assertEquals("Should be destination", DESTINATION, robot.getCurrentPosition()); assertEquals("Should be no more moves", 0, expectedMoveRequests.size()); -}</programlisting> +} - <para> - In this version, I'm holding the details of the expected route in <varname>expectedMoveRequests</varname>. - </para> +public void testGotoSamePlace() { + final Position POSITION = new Position(1, 0); + + Motor mockMotor = new Motor() { + public void move(MoveRequest request) { + try { + assertEquals("Should be move", expectedMoveRequests.remove(0), request); + } catch (IndexOutOfBoundsException ex) { + fail("Should be more moves"); + } + } + }; + + Robot robot = new Robot(mockMotor); + robot.setCurrentPosition(POSITION); + robot.goTo(POSITION); + + assertEquals("Should be destination", POSITION, robot.getCurrentPosition()); + assertEquals("Should be no more moves", 0, expectedMoveRequests.size()); +} +</programlisting> <para> - You can chose which style you prefer. I have to admit that, unreasonably, I'm biased against Self Shunt. - I can never remember which methods belong to the test class and which to the shunt, and it's a little bit - harder to separate out the two aspects later on. That said, the second approach can be a but more complicated - to write. At this level, it's a matter of taste but you should probably use only one style across your team. + There's a lot of repetetive code here. I think we should do something about that. </para> - - <!-- TODO --> <comment>Under development</comment> </section> <section> + + <!-- TODO --> <comment>Under development</comment> <title>Under development</title> <para>As my tests grow, I can refactor the various mock implementations into a single, more sophisticated MockMotor and use it throughout all the Robot @@ -511,7 +582,7 @@ </section> -<section> + <section> <title>What does this mean?</title> <para>My code moved in this direction because I was committed to unit Index: htmlbook.css =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/htmlbook.css,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- htmlbook.css 17 Aug 2002 12:59:10 -0000 1.8 +++ htmlbook.css 18 Aug 2002 01:42:12 -0000 1.9 @@ -11,7 +11,7 @@ .programlisting { margin-left: 5%; } .screen { margin-left: 5%; } -.sidebar { border: double black 1px; font-size: 80%; padding: 4px; text-align: center; margin-left: 80%; } +.sidebar { border: double black 1px; font-size: 80%; padding: 4px; text-align: center; margin-left: 70%; } .tip { border: double black 1px; font-size: 80%; padding: 2px; } .screenshot { margin-left: 20%; } .caption { font-size: 80%; font-style: italic; } |