|
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; }
|