You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(13) |
Aug
(151) |
Sep
(21) |
Oct
(6) |
Nov
(70) |
Dec
(8) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(47) |
Feb
(66) |
Mar
(23) |
Apr
(115) |
May
(24) |
Jun
(53) |
Jul
(10) |
Aug
(279) |
Sep
(84) |
Oct
(149) |
Nov
(138) |
Dec
(52) |
2003 |
Jan
(22) |
Feb
(20) |
Mar
(29) |
Apr
(106) |
May
(170) |
Jun
(122) |
Jul
(70) |
Aug
(64) |
Sep
(27) |
Oct
(71) |
Nov
(49) |
Dec
(9) |
2004 |
Jan
(7) |
Feb
(38) |
Mar
(3) |
Apr
(9) |
May
(22) |
Jun
(4) |
Jul
(1) |
Aug
(2) |
Sep
(2) |
Oct
|
Nov
(15) |
Dec
(2) |
2005 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
(1) |
May
(28) |
Jun
(3) |
Jul
(11) |
Aug
(5) |
Sep
(1) |
Oct
(5) |
Nov
(2) |
Dec
(3) |
2006 |
Jan
(8) |
Feb
(3) |
Mar
(8) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Jeff M. <cus...@us...> - 2002-09-05 08:39:27
|
Update of /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/test In directory usw-pr-cvs1:/tmp/cvs-serv1044/src/core/com/mockobjects/test Modified Files: TestMapEntry.java Log Message: Fixed MapEntry's equality behaviour when working with arrays Index: TestMapEntry.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/test/TestMapEntry.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TestMapEntry.java 29 Jul 2001 19:50:24 -0000 1.1 +++ TestMapEntry.java 5 Sep 2002 08:39:22 -0000 1.2 @@ -1,9 +1,9 @@ package com.mockobjects.test; -import java.util.*; -import junit.framework.*; -import com.mockobjects.*; -import com.mockobjects.util.*; +import com.mockobjects.MapEntry; +import com.mockobjects.util.TestCaseMo; +import junit.framework.Test; +import junit.framework.TestSuite; /** * JUnit test case for TestMapEntry @@ -16,7 +16,7 @@ } public static void main(String[] args) { - start(new String[] { TestMapEntry.class.getName()}); + start(new String[]{TestMapEntry.class.getName()}); } public static Test suite() { @@ -28,19 +28,48 @@ "Should be expected value", new MapEntry("A", "2"), new MapEntry("A", "2")); + assertTrue( "Should not be equal", !new MapEntry("A", "2").equals(new MapEntry("A", "1"))); + assertTrue( "Should not be equal", !new MapEntry("A", "2").equals(new MapEntry("B", "2"))); + assertEquals( "Should be equal with null value", new MapEntry("A", null), new MapEntry("A", null)); + assertEquals( "Should be equal with null key", new MapEntry(null, "A"), new MapEntry(null, "A")); + + assertEquals( + "Should be equal byte arrays", + new MapEntry("A", "A".getBytes()), + new MapEntry("A", "A".getBytes())); + + assertTrue( + "Should not be equal byte arrays", + !new MapEntry("A", "AB".getBytes()).equals(new MapEntry("A", "A".getBytes()))); + + assertTrue( + "Should not be equal byte arrays", + !new MapEntry("A", "A".getBytes()).equals(new MapEntry("A", "AB".getBytes()))); + + assertTrue( + "Should not be equal byte arrays", + !new MapEntry("A", null).equals(new MapEntry("A", "AB".getBytes()))); + } + + public void testHashCode() { + assertEquals( + "Should be equal hashcodes", + new MapEntry("A", "A".getBytes()).hashCode(), + new MapEntry("A", "A".getBytes()).hashCode()); + } } |
From: Tim M. <tim...@po...> - 2002-09-03 22:56:21
|
Haven't got the source handy, but my only recollection of equals is that it needs to be done in such a way that we can pass in wildcard objects that always compare true (it has to do with comparing in the right direction). We've been having a lot of success with this approach especially with generated mocks that take lots of parameters and you are only interested in a few of them. Actually, now that Vectors and collections implement equals properly, we can possibly even ditch this object and just use the more general ArrayList? Tim -----Original Message----- From: moc...@li... [mailto:moc...@li...]On Behalf Of Jeff Martin Sent: 03 September 2002 19:00 To: MockObjects Subject: [MO-java-dev] MapEntry.equals Currently MapEntry.equals will only compare the references to a byte array not the content. I think we should probably change this. Comments? -- jeff martin information technologist mkodo limited mobile: 44 (0) 78 5547 8331 phone: 44 (0) 20 2226 4545 email: je...@mk... www.mkodo.com --- Incoming mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.384 / Virus Database: 216 - Release Date: 21/08/2002 --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.384 / Virus Database: 216 - Release Date: 21/08/2002 |
From: Jeff M. <je...@mk...> - 2002-09-03 18:03:24
|
Currently MapEntry.equals will only compare the references to a byte array not the content. I think we should probably change this. Comments? -- jeff martin information technologist mkodo limited mobile: 44 (0) 78 5547 8331 phone: 44 (0) 20 2226 4545 email: je...@mk... www.mkodo.com |
From: Jeff M. <je...@mk...> - 2002-09-03 14:42:01
|
The following works for my okay. cvs -d:ext:cus...@cv...:/cvsroot/mockobjects co mockobjects-java On Tue, 2002-09-03 at 15:21, Ted Husted wrote: > Thanks. I do have more ready to commit, but seem to be having a problem > with some of my SourceForge accounts. The older ones are fine, but the > newest ones complain when I try to check anything in or out. > > cvs checkout -P mockobjects-java > unrecognized request `-responses ok error Valid-requests Checked-in > New-entry Checksum Copy-file Updated Created Update-existing Merged > Patched Rcs-diff Mode Mod-time Removed Remove-entry Set-static-directory > Clear-static-directory Set-sticky Clear-sticky Template Set-checkin-prog > Set-update-prog Notified Module-expansion Wrapper-rcsOption M Mbinary E > F MT' > > *****CVS exited normally with code 1***** > > cvs commit -m "License; JavaDocs." MockResultSet.java > cvs [server aborted]: "commit" requires write access to the repository > > > I'm not sure what the problem could be, since older accounts are working > just fine, and everything is setup the same way. I've a ticket into > SourceForge in case its something on their side. > > -Ted. > > > Steve Freeman wrote: > > > OK, OK, I give in with all these changes... > > > > Added Ted to the project. > > > > S. > > > > - - - - - - - - - - - - - - - > > Steve Freeman st...@m3... > > Programme chair OT2003. http://www.ot2003.org > > > > "Nonsense is just nonsense, but the study of nonsense is science." > > > > > > > > > > ------------------------------------------------------- > > This sf.net email is sponsored by: OSDN - Tired of that same old > > cell phone? Get a new here for FREE! > > https://www.inphonic.com/r.asp?r=sourceforge1&refcode1=vs3390 > > _______________________________________________ > > Mockobjects-java-dev mailing list > > Moc...@li... > > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev > > > > > > > -- > Ted Husted, Husted dot Com, Fairport NY US > -- Author, Java Web Development with Struts > -- Order it today: > -- http://husted.com/struts/book.html > > > > ------------------------------------------------------- > This sf.net email is sponsored by: OSDN - Tired of that same old > cell phone? Get a new here for FREE! > https://www.inphonic.com/r.asp?r=sourceforge1&refcode1=vs3390 > _______________________________________________ > Mockobjects-java-dev mailing list > Moc...@li... > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev -- jeff martin information technologist mkodo limited mobile: 44 (0) 78 5547 8331 phone: 44 (0) 20 2226 4545 email: je...@mk... www.mkodo.com |
From: Ted H. <hu...@ap...> - 2002-09-03 14:21:42
|
Thanks. I do have more ready to commit, but seem to be having a problem with some of my SourceForge accounts. The older ones are fine, but the newest ones complain when I try to check anything in or out. cvs checkout -P mockobjects-java unrecognized request `-responses ok error Valid-requests Checked-in New-entry Checksum Copy-file Updated Created Update-existing Merged Patched Rcs-diff Mode Mod-time Removed Remove-entry Set-static-directory Clear-static-directory Set-sticky Clear-sticky Template Set-checkin-prog Set-update-prog Notified Module-expansion Wrapper-rcsOption M Mbinary E F MT' *****CVS exited normally with code 1***** cvs commit -m "License; JavaDocs." MockResultSet.java cvs [server aborted]: "commit" requires write access to the repository I'm not sure what the problem could be, since older accounts are working just fine, and everything is setup the same way. I've a ticket into SourceForge in case its something on their side. -Ted. Steve Freeman wrote: > OK, OK, I give in with all these changes... > > Added Ted to the project. > > S. > > - - - - - - - - - - - - - - - > Steve Freeman st...@m3... > Programme chair OT2003. http://www.ot2003.org > > "Nonsense is just nonsense, but the study of nonsense is science." > > > > > ------------------------------------------------------- > This sf.net email is sponsored by: OSDN - Tired of that same old > cell phone? Get a new here for FREE! > https://www.inphonic.com/r.asp?r=sourceforge1&refcode1=vs3390 > _______________________________________________ > Mockobjects-java-dev mailing list > Moc...@li... > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev > > -- Ted Husted, Husted dot Com, Fairport NY US -- Author, Java Web Development with Struts -- Order it today: -- http://husted.com/struts/book.html |
From: Jeff M. <cus...@us...> - 2002-09-03 10:02:52
|
Update of /cvsroot/mockobjects/mockobjects-java/doc In directory usw-pr-cvs1:/tmp/cvs-serv6048 Modified Files: SiteHack.java Log Message: Added usage comments Index: SiteHack.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/SiteHack.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SiteHack.java 29 Aug 2002 12:17:21 -0000 1.1 +++ SiteHack.java 3 Sep 2002 10:02:50 -0000 1.2 @@ -2,6 +2,18 @@ import java.text.MessageFormat; /** + * SiteHack is a simple templating tool used to build the MockObjects site. + * It takes as it's arguements a list of text files, the first of these is + * the name of the file to be used as the template. All files specified + * after this will be inserted into this template file before the result of the + * merge is written into a directory called out. + * If the out directory does not exist it will automatically be create prior to + * writing the merged files. + * The template file can be any plain text file. The pattern {0} is used to mark + * the point where other files will be inserted. If the characters { or } are + * used within the template other than the merge point these need to be escaped + * by sourrounding them in single quotes e.g. '{' + * * $Revision$ */ public class SiteHack { |
From: Jeff M. <cus...@us...> - 2002-09-03 10:02:23
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/html In directory usw-pr-cvs1:/tmp/cvs-serv5675/html Modified Files: template.txt Log Message: Added list section to menu Index: template.txt =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/template.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- template.txt 2 Sep 2002 11:39:57 -0000 1.4 +++ template.txt 3 Sep 2002 10:02:19 -0000 1.5 @@ -46,9 +46,10 @@ <h4>Documentation</h4> <a href="./endotesting.html" class="menu">Introduction</a><br> - <a href="./papers.html" class="menu">Papers</a><br> + <a href="./papers.html" class="menu">Papers & Articles</a><br> <a href="./naming_conventions.html" class="menu">Naming conventions</a><br> - <a target="" href="javadoc/index.html" class="menu">API Reference</a><br> + <a target="" href="javadoc/1.3" class="menu">Mock Javadoc (JDK1.3)</a><br> + <a target="" href="javadoc/1.4" class="menu">Mock Javadoc (JDK1.4)</a><br> <h4>Support</h4> <a target="" href="http://sourceforge.net/tracker/?atid=118189&group_id=18189&func=browse" class="menu">Bug database</a><br> @@ -59,6 +60,11 @@ <a target="" href="http://sourceforge.net/cvs/?group_id=18189" class="menu">CVS</a><br> <a href="./coding_conventions.html" class="menu">Coding conventions</a><br> <a href="./release_process.html" class="menu">Release process</a><br> +<h4>Links</h4> + <a href="http://www.easymock.org/">Easy Mock</a><br> + <a href="http://www.junit.org/">JUnit</a><br> + <a href="http://www.abstrakt.de/mockcreator.html">Mock Creator</a><br> + <a href="http://www.mockmaker.org/">Mock Maker</a> </td> |
From: Jeff M. <cus...@us...> - 2002-09-03 10:01:52
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/html In directory usw-pr-cvs1:/tmp/cvs-serv5146/html Modified Files: papers.html Log Message: Added developer works paper on mockobjects and aspectj Index: papers.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/papers.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- papers.html 29 Aug 2002 12:17:21 -0000 1.1 +++ papers.html 3 Sep 2002 10:01:49 -0000 1.2 @@ -1,4 +1,4 @@ -<h1>Papers</h1> +<h1>Papers & Articles</h1> <p> This is a collection of papers on Mock Objects style and practice.</p> @@ -13,6 +13,23 @@ do. It also shows how an approach based on Mock Objects can lead to more rigourous unit testing and, I believe, better structured code than working with a real database. +</p> +<p> <i>Steve Freeman</i></p> +</li> +<li> +<a href="http://www-106.ibm.com/developerworks/java/library/j-aspectj2/?open&l=007,t=gr">Test flexibly with AspectJ and mock objects</a> +<p> +Programmers who have incorporated unit testing into their development process +know the advantages it brings: cleaner code, courage to refactor, and higher +velocity. But even the most die-hard unit testers can falter when faced with +testing a class that relies on system state for its behavior. Nicholas Lesiecki, +a respected Java programmer and leader in the XP community, introduces the +problems surrounding test-case isolation and shows us how to use mock objects +and AspectJ to develop precise and robust unit tests. +</p> +<p> +<i>Nicholas Lesiecki</i> +</p> </li> </ul> |
From: Jeff M. <je...@mk...> - 2002-09-03 09:24:30
|
-----Forwarded Message----- > From: Steve Freeman <st...@m3...> > To: Jeff Martin <je...@mk...> > Subject: Re: [MO-java-dev] Web site > Date: 02 Sep 2002 23:59:26 +0100 > > It'll do for starters, but could put a little explanation in SiteHack? What comment type explanation? > Actually, Ant 1.5 comes with an XLST task built in, might be worth porting > to a simple schema eventually. Maybe but for the time being I'd prefer to keep it simple. As soon as we have a schema to manage we're pretty much committed to the type of content we can handle. At this point I think a degree of fluidity is probably quiet a good thing. > > S. > > - - - - - - - - - - - - - - - > Steve Freeman st...@m3... > Programme chair OT2003. http://www.ot2003.org > > "Nonsense is just nonsense, but the study of nonsense is science." > > ----- Original Message ----- > From: "Jeff Martin" <je...@mk...> > To: "MockObjects" <moc...@li...> > Sent: Monday, September 02, 2002 12:38 PM > Subject: [MO-java-dev] Web site > > > > Anyone mind if I promote the version of the sire at > > http://www.custommonkey.org/mock/ to http://www.mockobjects.com/ > > > > there's not much difference between the two but it will bring the live > > site in line with cvs > > > > -- > > jeff martin > > information technologist > > mkodo limited > > > > mobile: 44 (0) 78 5547 8331 > > phone: 44 (0) 20 2226 4545 > > email: je...@mk... > > > > www.mkodo.com > > > > > > > > ------------------------------------------------------- > > This sf.net email is sponsored by: OSDN - Tired of that same old > > cell phone? Get a new here for FREE! > > https://www.inphonic.com/r.asp?r=sourceforge1&refcode1=vs3390 > > _______________________________________________ > > Mockobjects-java-dev mailing list > > Moc...@li... > > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev > > > > -- jeff martin information technologist mkodo limited mobile: 44 (0) 78 5547 8331 phone: 44 (0) 20 2226 4545 email: je...@mk... www.mkodo.com |
From: Steve F. <sm...@us...> - 2002-09-02 22:40:14
|
Update of /cvsroot/mockobjects/no-stone-unturned/src/java/nostone/addressbook In directory usw-pr-cvs1:/tmp/cvs-serv3673/src/java/nostone/addressbook Modified Files: AddressBookServlet.java AddressBookServletTest.java Log Message: first working servlet test, no answers found Index: AddressBookServlet.java =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/java/nostone/addressbook/AddressBookServlet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AddressBookServlet.java 31 Aug 2002 10:55:21 -0000 1.1 +++ AddressBookServlet.java 2 Sep 2002 22:40:11 -0000 1.2 @@ -1,9 +1,19 @@ package nostone.addressbook; import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import java.io.IOException; public class AddressBookServlet extends HttpServlet { public AddressBookServlet() { } + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + response.setContentType("text/plain"); + response.getWriter().println( "No address found" ); + } } Index: AddressBookServletTest.java =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/java/nostone/addressbook/AddressBookServletTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AddressBookServletTest.java 31 Aug 2002 10:55:21 -0000 1.1 +++ AddressBookServletTest.java 2 Sep 2002 22:40:11 -0000 1.2 @@ -16,25 +16,28 @@ HttpServletRequest mockRequest = new NullHttpServletRequest() { public String getMethod() { - return "PUT"; + return "GET"; } public String getProtocol() { return "HTTP/1.1"; } }; - HttpServletResponse mockResponse = new NullHttpServletResponse() /*{ - public void setContentType(String contentType) { - assertEquals("Should be content type", "text/plain", contentType); + HttpServletResponse mockResponse = new NullHttpServletResponse() { + private String contentType; + public void setContentType(String aContentType) { + assertEquals("Content type", "text/plain", aContentType); + contentType = aContentType; } public PrintWriter getWriter() throws IOException { + assertNotNull("Should have content type", contentType); return new PrintWriter(page); } - }*/; + }; AddressBookServlet servlet = new AddressBookServlet(); servlet.service(mockRequest, mockResponse); - // assertEquals("Response page", "No address found", page.toString()); + assertEquals("Should be empty response", "No address found", page.toString().trim()); } } |
From: Steve F. <sm...@us...> - 2002-09-02 22:40:14
|
Update of /cvsroot/mockobjects/no-stone-unturned/doc/xdocs In directory usw-pr-cvs1:/tmp/cvs-serv3673/doc/xdocs Modified Files: a_longer_example.xml Log Message: first working servlet test, no answers found Index: a_longer_example.xml =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/a_longer_example.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- a_longer_example.xml 27 Aug 2002 19:17:33 -0000 1.3 +++ a_longer_example.xml 2 Sep 2002 22:40:11 -0000 1.4 @@ -114,7 +114,7 @@ <programlisting> HttpServletRequest mockRequest = new NullHttpServletRequest() { public String getMethod() { - return "PUT"; + return "GET"; } public String getProtocol() { return "HTTP/1.1"; @@ -157,11 +157,178 @@ As you've seen in the first example, now we only have to override the methods that we use in our test. </para> </sidebar> - </section> + </section> <!-- We accept a name and find no result --> + + <section> + <title>We write our first implementation of the servlet</title> + <para> + So we've finally got our servlet doing nothing, so let's make it do what we need to get through the + first task. The first step is to extend our test with the output we expect to see: + </para> + <programlisting> +public void testNoEntries() throws ServletException, IOException { + <emphasis>final StringWriter page = new StringWriter();</emphasis> + + HttpServletRequest mockRequest = new NullHttpServletRequest() { + public String getMethod() { + return "GET"; + } + public String getProtocol() { + return "HTTP/1.1"; + } + }; + <emphasis>HttpServletResponse mockResponse = new NullHttpServletResponse() { + public PrintWriter getWriter() throws IOException { + return new PrintWriter(page); + } + };</emphasis> + + AddressBookServlet servlet = new AddressBookServlet(); + servlet.service(mockRequest, mockResponse); + + <emphasis>assertEquals("Should be empty response", "No address found", page.toString().trim());</emphasis> +}</programlisting> + <para> + The <classname>HttpServletResponse</classname> interface provides a <classname>PrintWriter</classname> that + the servlet can use to write out the page that it wants to send back to the browser. We've implemented this + by wrapping a <classname>StringWriter</classname> that's declared as a variable in the test. We can check + whether our servlet has written out something like the right page contents with a simple comparison at the end + of the test. We've also trimmed our output string to avoid disagreements over new lines. + Let's run the test. + </para> + + &redbar; + <screen> +There was 1 failure: +1) testNoEntries(nostone.addressbook.AddressBookServletTest) +AssertionFailedError: Response page expected:<No address found> but was:<> + at nostone.addressbook.AddressBookServletTest.testNoEntries(AddressBookServletTest.java:41) +FAILURES!!! +Tests run: 1, Failures: 1, Errors: 0</screen> + + <para> + Good, our test has failed. We haven't yet implemented the relevant method in the servlet, so let's + write just enough code to get our green bar back. + </para> + + <programlisting> +public class AddressBookServlet extends HttpServlet { + + <emphasis>protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException + { + resp.getWriter().println( "No address found" ); + }</emphasis> +}</programlisting> + + &greenbar; + <para> + Now the test passes because the returned page matches the text we asked for — we said + <emphasis>just</emphasis> enough code to pass the test, and we meant it. There's one more thing missing + before we can sign off this task. The servlet response specification says that a servlet must set + the content type of the response before getting hold of a writer, and we have no test (and therefore no + implementation) for that. If we hold onto the content type in the mock response object, we can check that + it's been set before we get the writer. + </para> + + <programlisting> + HttpServletResponse mockResponse = new NullHttpServletResponse() { + <emphasis>private String contentType; + public void setContentType(String aContentType) { + contentType = aContentType; + }</emphasis> + + public PrintWriter getWriter() throws IOException { + <emphasis>assertNotNull("Should have content type", contentType);</emphasis> + return new PrintWriter(page); + } + };</programlisting> + + <para> + Of course this fails + </para> + + &redbar; + <screen> +There was 1 failure: +1) testNoEntries(nostone.addressbook.AddressBookServletTest) +AssertionFailedError: Should have content type + at nostone.addressbook.AddressBookServletTest$2.getWriter(AddressBookServletTest.java:33) + <emphasis>at nostone.addressbook.AddressBookServlet.doGet(AddressBookServlet.java:16)</emphasis> + at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) + at nostone.addressbook.AddressBookServletTest.testNoEntries(AddressBookServletTest.java:39) +FAILURES!!!</screen> + + <para> + The interesting thing about this failure report is that it's our first example that fails + <emphasis>within</emphasis> the production code, not the test case. The stack trace shows + that we detected the failure in the middle of <methodname>doGet()</methodname> when the + servlet is getting hold of the writer. Let's fix the problem by setting the content type + as we're supposed to. + </para> + + <programlisting> +protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException +{ + <emphasis>response.setContentType("text/plan");</emphasis> + response.getWriter().println( "No address found" ); +}</programlisting> + + &greenbar; + + <para> + Done! Well, maybe not. One of us just noticed that we've set the content type to <quote>text/plan</quote>, + which is not what we meant. We want to test the value that we set for the content type as well. We could + just call <methodname>assertEquals("text/plain",...)</methodname> where now we call + <methodname>assertNotNull()</methodname>, but that wouldn't show us the failure until after it had + happened. Instead, we'll add an assertion to <methodname>setContentType()</methodname>. + </para> + + <programlisting> + public void setContentType(String aContentType) { + <emphasis>assertEquals("Content type", "text/plain", aContentType);</emphasis> + contentType = aContentType; + }</programlisting> + + &redbar; + <screen> +There was 1 failure: +1) testNoEntries(nostone.addressbook.AddressBookServletTest) +<emphasis>AssertionFailedError: Content type expected:<text/plain> but was:<text/plan></emphasis> + at nostone.addressbook.AddressBookServletTest$2.setContentType(AddressBookServletTest.java:28) + <emphasis>at nostone.addressbook.AddressBookServlet.doGet(AddressBookServlet.java:16)</emphasis> + at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) + at nostone.addressbook.AddressBookServletTest.testNoEntries(AddressBookServletTest.java:39) +FAILURES!!!</screen> + + <para> + Once again, our stacktrace shows us exactly where the failure happened and we can go straight in + and fix it. + </para> + + <programlisting> +protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException +{ + response.setContentType(<emphasis>"text/plain"</emphasis>); + response.getWriter().println( "No address found" ); +}</programlisting> + + &greenbar; + + <para> + Now we're ready for our first acceptance test. + </para> + </section> <!-- We write our first implementation of the servlet --> + + <!-- TODO --> <section> <title>accept a name and return a result from a hard-coded collection.</title> - </section> + </section> <!-- accept a name and return a result from a hard-coded collection --> <section> <title> @@ -169,7 +336,7 @@ Values are held in memory. </title> </section> - </chapter> + </chapter> <!-- Search for an entry in the book --> <chapter> <title>List all the entries in the book</title> |
From: Steve F. <sm...@us...> - 2002-09-02 22:39:29
|
Update of /cvsroot/mockobjects/no-stone-unturned/doc/xdocs In directory usw-pr-cvs1:/tmp/cvs-serv3492/doc/xdocs Modified Files: htmlbook.xsl htmlbook.css Log Message: changed fixed font emphasis to bold added emphasis to <screen> Index: htmlbook.xsl =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/htmlbook.xsl,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- htmlbook.xsl 1 Sep 2002 00:29:07 -0000 1.11 +++ htmlbook.xsl 2 Sep 2002 22:39:25 -0000 1.12 @@ -55,6 +55,12 @@ </xsl:call-template> </xsl:template> + <xsl:template match="screen/emphasis"> + <xsl:call-template name="inline.span"> + <xsl:with-param name="spanclass" select="'emphasis'" /> + </xsl:call-template> + </xsl:template> + <xsl:template match="comment|remark"> <xsl:if test="$show.comments != 0"> <xsl:call-template name="inline.span"> Index: htmlbook.css =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/htmlbook.css,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- htmlbook.css 1 Sep 2002 00:29:07 -0000 1.14 +++ htmlbook.css 2 Sep 2002 22:39:25 -0000 1.15 @@ -31,7 +31,7 @@ DIV.sidebar P { margin-top: 10px; margin-bottom: 10px; } DIV.sidebar P.title { margin-top: 0%; font-style: italic; font-size: 130%; } -PRE SPAN.emphasis { font-style: italic; } +PRE SPAN.emphasis { font-weight: bold; } .lineannotation { font-style: italic; font-family: "Century Schoolbook", Times, serif; } .footnote { margin-left: 5%; text-indent: -3% } |
From: Steve F. <sm...@us...> - 2002-09-02 20:22:03
|
Update of /cvsroot/mockobjects/no-stone-unturned/src/ruby In directory usw-pr-cvs1:/tmp/cvs-serv30521/src/ruby Removed Files: test_addrservlet.rb Log Message: removed --- test_addrservlet.rb DELETED --- |
From: Steve F. <sm...@us...> - 2002-09-02 20:15:37
|
Update of /cvsroot/mockobjects/no-stone-unturned/src/ruby In directory usw-pr-cvs1:/tmp/cvs-serv28807/src/ruby Modified Files: addrservlet.rb test_addrservlet.rb Log Message: *** keyword substitution change *** Index: addrservlet.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addrservlet.rb,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 Index: test_addrservlet.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/test_addrservlet.rb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- test_addrservlet.rb 31 Aug 2002 10:55:21 -0000 1.1 +++ test_addrservlet.rb 2 Sep 2002 20:15:33 -0000 1.2 @@ -1,81 +1,81 @@ - - -require 'test/unit' -require 'webrick' -require 'addrservlet' - - -class MockRequest - def _setup_query_string( query ) - @query_string = WEBrick::HTTPUtils::escape_form(query) - end - attr_reader :query_string -end - -class MockResponse - include Test::Unit::Assertions - - def initialize - @content_type_set = false - @body_set = false - @body_expectation = nil - end - - def []=( header, value ) - assert_equal( "content-type", header ) - assert_match( /^text\/.*/, value ) - @content_type_set = true - end - - def _expect_body( &proc ) - @body_expectation = proc - end - - def body=( value ) - @body_expectation.call(value) if @body_expectation - @body_set = true - end - - def _verify - assert( "content-type", @content_type_set ) - assert( "body", @body_expectation && @body_set ) - end -end - - -class AddressBookServletTest < Test::Unit::TestCase - NAME1 = "First Last" - ADDR1 = "ADDRESS" - - def set_up - @request = MockRequest.new - @response = MockResponse.new - @servlet = AddressBookServlet.new( {}, NAME1 => ADDR1 ) - end - - def test_no_address_found - @request._setup_query_string( "UNKNOWN NAME" ) - @response._expect_body { |text| assert_match( /no address found/, text ) } - - @servlet.do_GET( @request, @response ) - - @response._verify - end - - def test_no_address_found_when_no_name - @response._expect_body { |text| assert_match( /no address found/, text ) } - - @servlet.do_GET( @request, @response ) - - @response._verify - end - - def test_address_found - @request._setup_query_string( NAME1 ) - @response._expect_body { |text| assert_match( /#{ADDR1}/, text ) } - - @servlet.do_GET( @request, @response ) - - @response._verify - end -end + + +require 'test/unit' +require 'webrick' +require 'addrservlet' + + +class MockRequest + def _setup_query_string( query ) + @query_string = WEBrick::HTTPUtils::escape_form(query) + end + attr_reader :query_string +end + +class MockResponse + include Test::Unit::Assertions + + def initialize + @content_type_set = false + @body_set = false + @body_expectation = nil + end + + def []=( header, value ) + assert_equal( "content-type", header ) + assert_match( /^text\/.*/, value ) + @content_type_set = true + end + + def _expect_body( &proc ) + @body_expectation = proc + end + + def body=( value ) + @body_expectation.call(value) if @body_expectation + @body_set = true + end + + def _verify + assert( "content-type", @content_type_set ) + assert( "body", @body_expectation && @body_set ) + end +end + + +class AddressBookServletTest < Test::Unit::TestCase + NAME1 = "First Last" + ADDR1 = "ADDRESS" + + def set_up + @request = MockRequest.new + @response = MockResponse.new + @servlet = AddressBookServlet.new( {}, NAME1 => ADDR1 ) + end + + def test_no_address_found + @request._setup_query_string( "UNKNOWN NAME" ) + @response._expect_body { |text| assert_match( /no address found/, text ) } + + @servlet.do_GET( @request, @response ) + + @response._verify + end + + def test_no_address_found_when_no_name + @response._expect_body { |text| assert_match( /no address found/, text ) } + + @servlet.do_GET( @request, @response ) + + @response._verify + end + + def test_address_found + @request._setup_query_string( NAME1 ) + @response._expect_body { |text| assert_match( /#{ADDR1}/, text ) } + + @servlet.do_GET( @request, @response ) + + @response._verify + end +end |
From: Steve F. <sm...@us...> - 2002-09-02 20:15:02
|
Update of /cvsroot/mockobjects/no-stone-unturned/src/ruby In directory usw-pr-cvs1:/tmp/cvs-serv28547/src/ruby Modified Files: addrservlet.rb Log Message: *** keyword substitution change *** |
From: Steve F. <sm...@us...> - 2002-09-02 20:14:25
|
Update of /cvsroot/mockobjects/no-stone-unturned/src/ruby In directory usw-pr-cvs1:/tmp/cvs-serv28424/src/ruby Modified Files: server.rb Log Message: *** keyword substitution change *** Index: server.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/server.rb,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 |
From: Steve F. <sm...@us...> - 2002-09-02 20:13:34
|
Update of /cvsroot/mockobjects/no-stone-unturned/doc/xdocs In directory usw-pr-cvs1:/tmp/cvs-serv28237/doc/xdocs Modified Files: how_mocks_happened.xml Log Message: more Index: how_mocks_happened.xml =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/doc/xdocs/how_mocks_happened.xml,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- how_mocks_happened.xml 1 Sep 2002 00:30:11 -0000 1.15 +++ how_mocks_happened.xml 2 Sep 2002 20:13:29 -0000 1.16 @@ -744,6 +744,37 @@ trying to place bets on the what we think we're going to need. </para> <para> + Speculating wildly, the next requirements might push us to extract a <classname>Navigator</classname> + object that works out the route, so that the <classname>Robot</classname> becomes just a frame that + holds together the objects that do the real work. This is how the process often works: we start with a + top-level object, fill in some implementation, and hollow it out as we understand more about what's + inside. We then do the same to the new objects we've created, and so on. We end up with a collection of + classes, each focussed on a particular task, that have well-defined interfaces to their collaborating + objects. + </para> + <sidebar> + <title>Top-Down Decomposition</title> + <para> + Some of you may recognise the similarities between &TDD; and the ancient discipline of + <glossterm linkend="topdowndecomposition"><quote>Top-Down Decomposition</quote></glossterm>, also known as + <quote>Structured Programming</quote>. The idea is to start from the top-most level of the program, stub out + the bits that have not yet been implemented, and work your way down; repeat until you have a complete + application. In the days when many programmers found procedures and nested scope exotic, + Top-Down Decomposition was a useful technique for avoiding + <glossterm linkend="sdd">Spaghetti-Driven Development</glossterm>. + </para> + <para> + Top-Down Decomposition had two powerful insights: to keep each level focussed and consistent, + and to drive the design of interfaces from their use rather than their implementation. It also had + a couple of critical failings: it turned out to be hard to change early design + decisions because, of course, they're embedded in the top-level structure, and it's not good at + encouraging reuse between lower-level components. It looks like &TDD; avoids these problems because + object-orientation makes it easier to share components throughout the application and + the emphasis on refactoring means we can remove duplication as the codebase grows. + </para> + </sidebar> + + <para> One more design issue is our unusually heavy use of the <quote>Tell, don't ask</quote> pattern. We prefer to pass behaviour into an object, rather than pulling values out, which is why we wrote a <quote>route following object</quote> rather than returning a collection of @@ -774,34 +805,7 @@ </para> </note> - <para> - Speculating wildly, the next requirements might push us to extract a <classname>Navigator</classname> - object that works out the route, and the <classname>Robot</classname> becomes just a frame that - holds together the objects that do the real work. This is how the process often works: we start with a - top level object, fill in some implementation, and hollow it out as we understand more about what's - inside. We then do the same to the new objects we've created, and so on. - </para> - <sidebar> - <title>Top-Down Decomposition</title> - <para> - Some of you may recognise the similarities between &TDD; and the ancient discipline of - <glossterm linkend="topdowndecomposition"><quote>Top-Down Decomposition</quote></glossterm>, also known as - <quote>Structured Programming</quote>. The idea is to start from the top-most level of the program, stub out - the bits that have not yet been implemented, and work your way down; repeat until you have a complete - application. In the days when many programmers found procedures and nested scope exotic, - Top-Down Decomposition was a useful technique for avoiding - <glossterm linkend="sdd">Spaghetti-Driven Development</glossterm>. - </para> - <para> - Top-Down Decomposition had two powerful insights: to keep each level focussed and consistent, - and to drive the design of interfaces from their use rather than their implementation. It also had - a couple of critical failings: it turned out to be hard to change early design - decisions because, of course, they're embedded in the top-level structure, and it's not good at - encouraging reuse between lower-level components. It looks like &TDD; avoids these problems because - object-orientation makes it easier to share components throughout the application and - the emphasis on refactoring means we can remove duplication as the codebase grows. - </para> - </sidebar> + </section> <!-- What about design? --> <!-- TODO --> <comment>Under development</comment> |
Update of /cvsroot/mockobjects/no-stone-unturned/src/ruby In directory usw-pr-cvs1:/tmp/cvs-serv23153 Modified Files: addrbook.rb addrbook_test.rb addresses.txt addrservlet.rb addrservlet_test.rb notes.txt tasks.txt Added Files: addrbook_mock.rb Log Message: Story 2 complete --- NEW FILE: addrbook_mock.rb --- require 'mockobjects' class MockAddressBook < MockObject def initialize( entries = {} ) @entries = entries @each_entries = nil end def empty? @entries.empty? end def _setup_index( name, address ) @entries[name] = address end def has_key?( name ) @entries.has_key?(name) end def []( name ) @entries[name] end def _setup_each( *entries ) @each_entries = entries end def each if @each_entries @each_entries.each else @entries.each end end end Index: addrbook.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addrbook.rb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- addrbook.rb 2 Sep 2002 14:53:00 -0000 1.1 +++ addrbook.rb 2 Sep 2002 14:56:58 -0000 1.2 @@ -3,16 +3,23 @@ class AddressBook def initialize( filename, file_store=File ) @entries = Hash.new - read_file( file_store, filename ) end + def empty? + @entries.empty? + end + def has_key?( name ) @entries.has_key?(name) end def []( name ) @entries[name] + end + + def each + @entries.each end def read_file( file_store, filename ) Index: addrbook_test.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addrbook_test.rb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- addrbook_test.rb 2 Sep 2002 14:53:00 -0000 1.1 +++ addrbook_test.rb 2 Sep 2002 14:56:58 -0000 1.2 @@ -9,7 +9,7 @@ @name = Expectation.new("name") @mode = Expectation.new("mode") @open_proc = Expectation.new("open_proc") - @open_result = nil + @open_action = proc { nil } end def _expect_name( &checks ) @@ -25,8 +25,13 @@ @open_proc.expect( &checks ) end - def _setup_open( result ) - @open_result = result + def _setup_open( result=nil, &proc ) + if proc + raise "result should not be given if block given" if result + @open_action = proc + else + @open_action = proc { result } + end end def open( name, mode, &proc ) @@ -34,11 +39,13 @@ @mode.actual = mode @open_proc.actual = proc + result = @open_action.call( name, mode ) + if proc - proc.call( @open_result ) - @open_result.close + proc.call( result ) + result.close else - return @open_result + return result end end end @@ -81,10 +88,51 @@ book = AddressBook.new(FILENAME,store) + assert( !book.empty?, "not empty" ) assert( book.has_key?("NAME1"), "has key NAME1" ) assert_equal( "ADDRESS1", book["NAME1"] ) assert( book.has_key?("NAME2"), "has key NAME2" ) assert_equal( "ADDRESS2", book["NAME2"] ) + + contents._verify + store._verify + end + + def test_empty_file + contents = MockInputStream.new + + store = MockFileStore.new + store._expect_name { |name| assert_equal( FILENAME, name ) } + store._expect_mode { |mode| assert_match( /r/, mode, "read mode" ) } + store._expect_open_proc { |proc| assert_not_nil(proc,"open proc") } + store._setup_open( contents ) + + book = AddressBook.new( FILENAME, store ) + + assert( book.empty?, "is empty" ) + + contents._verify + store._verify + end + + def test_each + contents = MockInputStream.new( "NAME1=ADDRESS1", "NAME2=ADDRESS2" ) + + store = MockFileStore.new + store._expect_name { |name| assert_equal( FILENAME, name ) } + store._expect_mode { |mode| assert_match( /r/, mode, "read mode" ) } + store._expect_open_proc { |proc| assert_not_nil(proc,"open proc") } + store._setup_open( contents ) + + book = AddressBook.new(FILENAME,store) + + names = {} + book.each { |name,address| names[name] = address } + + assert( names.has_key?("NAME1") ) + assert_equal( "ADDRESS1", names["NAME1"] ) + assert( names.has_key?("NAME2") ) + assert_equal( "ADDRESS2", names["NAME2"] ) contents._verify store._verify Index: addresses.txt =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addresses.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- addresses.txt 2 Sep 2002 14:53:00 -0000 1.1 +++ addresses.txt 2 Sep 2002 14:56:58 -0000 1.2 @@ -1,3 +1,3 @@ -Nat Pryce=nat...@so..., +Nat Pryce=nat...@so... Steve Freeman=st...@so... Jeff Martin=cus...@so... Index: addrservlet.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addrservlet.rb,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- addrservlet.rb 2 Sep 2002 14:53:00 -0000 1.2 +++ addrservlet.rb 2 Sep 2002 14:56:58 -0000 1.3 @@ -9,6 +9,64 @@ end def do_GET( request, response ) + command = request.path_info + + case command + when "/list" + do_list( request, response ) + when "/search" + do_search( request, response ) + else + raise WEBrick::HTTPStatus::NotFound + end + end + + def do_list( request, response ) + if @address_book.empty? + respond_empty_book( response ) + else + list_addresses( response ) + end + end + + def respond_empty_book( response ) + response['content-type'] = 'text/plain' + response.body = "no addresses" + end + + def list_addresses( response ) + response['content-type'] = 'text/html' + + body = <<-EOF + <html><head><title>Address Book</title></head> + <body><table> + EOF + + entries = [] + @address_book.each do |name,address| + entries << [name,address] + end + + entries.sort! do |e,f| + e_surname = e[0].split[-1] + f_surname = f[0].split[-1] + e_surname <=> f_surname + end + + entries.each do |e| + body << <<-EOF + <tr><td>#{e[0]}</td><td>#{e[1]}</td></tr> + EOF + end + + body << <<-EOF + </table></body></html> + EOF + + response.body = body + end + + def do_search( request, response ) response['content-type'] = 'text/plain' query = request.query_string Index: addrservlet_test.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addrservlet_test.rb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- addrservlet_test.rb 2 Sep 2002 14:53:00 -0000 1.1 +++ addrservlet_test.rb 2 Sep 2002 14:56:58 -0000 1.2 @@ -4,13 +4,24 @@ require 'webrick' require 'mockobjects' require 'addrservlet' +require 'addrbook_mock' class MockRequest < MockObject + def initialize + @query_string = "" + @path_info = "" + end + def _setup_query_string( query ) @query_string = WEBrick::HTTPUtils::escape_form(query) end attr_reader :query_string + + def _setup_path_info( path_info ) + @path_info = path_info + end + attr_reader :path_info end @@ -44,39 +55,30 @@ end -class MockAddressBook - def initialize( entries ) - @entries = entries - end - - def has_key?( name ) - @entries.has_key?(name) - end - - def []( name ) - @entries[name] - end -end - - class AddressBookServletTest < Test::Unit::TestCase - NAME1 = "First Last" - ADDR1 = "ADDRESS" + NAME1 = "Pete Brown" # Note: in reverse alphabetical order + ADDR1 = "Address1" + NAME2 = "John Adams" + ADDR2 = "Address2" + def set_up @request = MockRequest.new @response = MockResponse.new - @book = MockAddressBook.new( NAME1 => ADDR1 ) + @book = MockAddressBook.new( NAME1 => ADDR1, NAME2 => ADDR2 ) @servlet = AddressBookServlet.new( {}, @book ) end def test_no_address_found + @request._setup_path_info("/search") @request._setup_query_string( "UNKNOWN NAME" ) - @response._expect_header("content-type") do |value| - assert_match( /^text\/.*/, value ) + @response._expect_header("content-type") do |type| + assert_match( /^text\/.*/, type ) + end + @response._expect_body do |text| + assert_match( /no address found/, text ) end - @response._expect_body { |text| assert_match( /no address found/, text ) } @servlet.do_GET( @request, @response ) @@ -84,10 +86,13 @@ end def test_no_address_found_when_no_name + @request._setup_path_info("/search") @response._expect_header("content-type") do |value| assert_match( /^text\/.*/, value ) end - @response._expect_body { |text| assert_match( /no address found/, text ) } + @response._expect_body do |text| + assert_match( /no address found/, text ) + end @servlet.do_GET( @request, @response ) @@ -95,15 +100,83 @@ end def test_address_found + @request._setup_path_info("/search") @request._setup_query_string( NAME1 ) - @response._expect_header("content-type") do |value| - assert_match( /^text\/.*/, value ) + @response._expect_header("content-type") do |type| + assert_match( /^text\/.*/, type ) end @response._expect_body { |text| assert_match( /#{ADDR1}/, text ) } @servlet.do_GET( @request, @response ) @response._verify + end + + def test_list_all_empty_book + book = MockAddressBook.new( {} ) + servlet = AddressBookServlet.new( {}, book ) + + @request._setup_path_info("/list") + + @response._expect_header("content-type") do |type| + assert_match( /^text\/.*/, type ) + end + @response._expect_body { |text| assert_match( /no addresses/, text ) } + + servlet.do_GET( @request, @response ) + + @response._verify + end + + def test_list_entries + @request._setup_path_info("/list") + + @response._expect_header("content-type") do |type| + assert_equal( "text/html", type ) + end + @response._expect_body do |text| + assert_address_as_table_row( text, NAME1, ADDR1 ) + assert_address_as_table_row( text, NAME2, ADDR2 ) + end + + @servlet.do_GET( @request, @response ) + + @response._verify + end + + def test_list_is_sorted + @request._setup_path_info("/list") + + @book._setup_each( [NAME1,ADDR1],[NAME2,ADDR2] ) # reverse order + + @response._expect_header("content-type") do |type| + assert_equal( "text/html", type ) + end + @response._expect_body do |text| + name1_index = text.index(NAME1) + name2_index = text.index(NAME2) + assert_not_nil( name1_index, "#{NAME1} in body" ) + assert_not_nil( name2_index, "#{NAME2} in body" ) + assert( name1_index > name2_index, "names in alphatical order" ) + end + + @servlet.do_GET( @request, @response ) + + @response._verify + end + + def test_invalid_command + @request._setup_path_info("*INVALID*") + + assert_raises WEBrick::HTTPStatus::NotFound do + @servlet.do_GET( @request, @response ) + end + + @response._verify + end + + def assert_address_as_table_row( body, name, address ) + assert_match( /<tr><td>#{name}<\/td><td>#{address}<\/td><\/tr>/, body ) end end Index: notes.txt =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/notes.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- notes.txt 2 Sep 2002 14:53:00 -0000 1.1 +++ notes.txt 2 Sep 2002 14:56:58 -0000 1.2 @@ -9,6 +9,8 @@ For example, it is trivial to mock the file system in Ruby, but it is quite hard to do so in Java (see the alt.java.* packages in the Mock Objects library). + + STORY 1, TASK a 2) Expectations can be defined using closures, rather than various expectation classes. Closures can call the Test::Unit assertions @@ -17,6 +19,8 @@ This makes mock-object classes very flexible, because expectations can be tailored for each test method. + STORY 1, TASK b + 3) There is less need to define factories to insert mock objects into your classes. In Ruby, classes just objects with a "new" method, and sometimes other methods that create objects. That is, classes @@ -29,6 +33,8 @@ the stub responds to the same messages as a class, and so to all intents and purposes *is* a class. + STORY 1, TASK c + 4) NOTE: POTENTIAL PITFALL Servlet used a hash to store names. Changed to use an address book @@ -55,3 +61,17 @@ sync, so that they both implement the same methods. That way you catch errors where client code is being tested against a mock that does not actually implement the same methods as the real class that it is mocking. + + STORY 1, TASK c + +5) Organising tests and mocks. + <file>.rb + <file>_test.rb + <file>_mock.rb + + STORY 1, TASK c + + + Put this in a sidebar + + Index: tasks.txt =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/tasks.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- tasks.txt 2 Sep 2002 14:53:00 -0000 1.2 +++ tasks.txt 2 Sep 2002 14:56:58 -0000 1.3 @@ -1,29 +1,30 @@ -Stories -1) anyone can search the entries in the book. -2) anyone can add their name and email address to the book. -3) anyone can remove an entry from the book. +Story: Load from file, do search -Tasks +Note: don't need to check for errors, because errors when loading file will + stop server at startup. -1a) accept a name and find no result -DONE +Story: List all the entries in the book -Points of Interest: - - no need to implement any interfaces when defining mocks +Tasks: + * Branch on servlet path: search vs. list + DONE + + * Show an empty book. + DONE + * Show all the entries + DONE -1b) accept a name and return a result from a hard-coded collection. -1b.1) what about the servlet receiving no name? -DONE + * Sort the results alphabetically + DONE. -Points of Interest: - - using blocks to handle expectations +Note: need to add _setup_each to MockAddressBook to force a particular + interation order because Hash doesn't specify order + * Invalid path? + DONE -REFACTORING - - refactor code - - refactor tests to use expectation and mockobject classes +Note: throws HTTPStatus::NotFound exception when unknown path info +Note: requires changing tests to explicitly set path_info to "/search" where + no explicit path info eas specified - -1c) Retrieve the entries from a file, specified as a servlet property. - Values are held in memory. |
From: Nat P. <np...@us...> - 2002-09-02 14:53:05
|
Update of /cvsroot/mockobjects/no-stone-unturned/src/ruby In directory usw-pr-cvs1:/tmp/cvs-serv21646 Modified Files: addrservlet.rb server.rb tasks.txt Added Files: addrbook.rb addrbook_test.rb addresses.txt addrservlet_test.rb all_tests mockobjects.rb mockobjects_test.rb notes.txt Log Message: Story 1 completed. --- NEW FILE: addrbook.rb --- class AddressBook def initialize( filename, file_store=File ) @entries = Hash.new read_file( file_store, filename ) end def has_key?( name ) @entries.has_key?(name) end def []( name ) @entries[name] end def read_file( file_store, filename ) file_store.open( filename, "r" ) do |file| @entries.clear file.each do |line| name,address = line.split("=") @entries[name] = address end end end end --- NEW FILE: addrbook_test.rb --- require 'test/unit' require 'mockobjects' require 'addrbook' class MockFileStore < MockObject def initialize @name = Expectation.new("name") @mode = Expectation.new("mode") @open_proc = Expectation.new("open_proc") @open_result = nil end def _expect_name( &checks ) @name.expect &checks end def _expect_mode( &checks ) @mode.expect( &checks ) end def _expect_open_proc( &checks ) checks = proc {|value|} if checks == nil @open_proc.expect( &checks ) end def _setup_open( result ) @open_result = result end def open( name, mode, &proc ) @name.actual = name @mode.actual = mode @open_proc.actual = proc if proc proc.call( @open_result ) @open_result.close else return @open_result end end end class MockInputStream < MockObject include Test::Unit::Assertions def initialize( *lines ) @lines = lines @closed = false end def each @lines.each { |line| yield line } end def close @closed = true end def _verify assert( @closed, "closed" ) end end class AddressBookTest < Test::Unit::TestCase FILENAME = "FILENAME" def test_open contents = MockInputStream.new( "NAME1=ADDRESS1", "NAME2=ADDRESS2" ) store = MockFileStore.new store._expect_name { |name| assert_equal( FILENAME, name ) } store._expect_mode { |mode| assert_match( /r/, mode, "read mode" ) } store._expect_open_proc { |proc| assert_not_nil(proc,"open proc") } store._setup_open( contents ) book = AddressBook.new(FILENAME,store) assert( book.has_key?("NAME1"), "has key NAME1" ) assert_equal( "ADDRESS1", book["NAME1"] ) assert( book.has_key?("NAME2"), "has key NAME2" ) assert_equal( "ADDRESS2", book["NAME2"] ) contents._verify store._verify end end --- NEW FILE: addresses.txt --- Nat Pryce=nat...@so..., Steve Freeman=st...@so... Jeff Martin=cus...@so... --- NEW FILE: addrservlet_test.rb --- require 'test/unit' require 'webrick' require 'mockobjects' require 'addrservlet' class MockRequest < MockObject def _setup_query_string( query ) @query_string = WEBrick::HTTPUtils::escape_form(query) end attr_reader :query_string end class MockResponse < MockObject include Test::Unit::Assertions def initialize @headers = ExpectationHash.new("headers") @body = Expectation.new("body") end def _expect_header(header,&proc) @headers[header].expect(&proc) end def []( header ) @headers[header].actual end def []=( header, value ) @headers[header] = value end def _expect_body( &proc ) @body.expect &proc end def body=( value ) @body.actual = value end end class MockAddressBook def initialize( entries ) @entries = entries end def has_key?( name ) @entries.has_key?(name) end def []( name ) @entries[name] end end class AddressBookServletTest < Test::Unit::TestCase NAME1 = "First Last" ADDR1 = "ADDRESS" def set_up @request = MockRequest.new @response = MockResponse.new @book = MockAddressBook.new( NAME1 => ADDR1 ) @servlet = AddressBookServlet.new( {}, @book ) end def test_no_address_found @request._setup_query_string( "UNKNOWN NAME" ) @response._expect_header("content-type") do |value| assert_match( /^text\/.*/, value ) end @response._expect_body { |text| assert_match( /no address found/, text ) } @servlet.do_GET( @request, @response ) @response._verify end def test_no_address_found_when_no_name @response._expect_header("content-type") do |value| assert_match( /^text\/.*/, value ) end @response._expect_body { |text| assert_match( /no address found/, text ) } @servlet.do_GET( @request, @response ) @response._verify end def test_address_found @request._setup_query_string( NAME1 ) @response._expect_header("content-type") do |value| assert_match( /^text\/.*/, value ) end @response._expect_body { |text| assert_match( /#{ADDR1}/, text ) } @servlet.do_GET( @request, @response ) @response._verify end end --- NEW FILE: all_tests --- #!/usr/bin/ruby require 'test/unit' Dir.glob( File.join( File.dirname(__FILE__), "*_test.rb" ) ) do |file| $stdout.print "loading tests from #{file}\n" require File.basename(file) end --- NEW FILE: mockobjects.rb --- require 'test/unit' class Expectation include Test::Unit::Assertions def initialize( name, actual=nil ) @name = name @check = proc { |value| } @check_set = false @actual = nil @actual_set = false end attr_reader :name def expect( &assertions ) @check = assertions @check_set = true end def actual if @actual_set @actual else flunk("#{@name}: actual value not set") end end def actual=( value ) @check.call(value) @actual = value @actual_set = true end def verify assert( @actual_set, "#{@name} does not verify" ) if @check_set end end class ExpectationHash def initialize( name ) @name = name @elements = Hash.new end attr_reader :name def []( key ) if not @elements.has_key?(key) name = "#{@name}[#{key}]" @elements[key] = Expectation.new(name) end return @elements[key] end def []=( key, value ) self[key].actual = value end def verify @elements.each_value { |expectation| expectation.verify } end end class MockObject def _verify self.instance_variables.sort.each do |varname| value = self.instance_eval(varname) if value.respond_to? :verify value.verify end end end end --- NEW FILE: mockobjects_test.rb --- require 'test/unit' require 'mockobjects' class ExpectationTest < Test::Unit::TestCase def set_up @expectation = Expectation.new("tested expectation") end def test_expectation_name name = "NAME" assert_equal( name.to_s, Expectation.new(name).name ) end def test_verify_passes_if_nothing_called @expectation.verify end def test_verify_fails_if_expectation_but_no_actual @expectation.expect { |value| } assert_raises Test::Unit::AssertionFailedError do @expectation.verify end end def test_no_check_defined @expectation.actual = "ACTUAL" @expectation.verify end def test_verify_succeeds_if_expected_and_actual @expectation.expect { |value| } @expectation.actual = "Some value" assert_nothing_raised do @expectation.verify end end def test_actual_value_stored actual_value = "ACTUAL" @expectation.actual = actual_value assert_same( actual_value, @expectation.actual ) end def test_failure_if_actual_value_queried_before_it_is_set assert_raises Test::Unit::AssertionFailedError do @expectation.actual end end def test_expectation_check_Called check_called = false actual_value = "VALUE" @expectation.expect do |value| assert_equal( value, actual_value ) check_called = true end @expectation.actual = actual_value @expectation.verify end end class ExpectationHashTest < Test::Unit::TestCase def set_up @hash = ExpectationHash.new("hash") end def test_empty_hash_verifies @hash.verify end def test_index_creates_new_named_expectation expectation1 = @hash[:KEY1] expectation2 = @hash["KEY2"] assert_instance_of( Expectation, expectation1 ) assert_equal( "#{@hash.name}[KEY1]", expectation1.name ) assert_instance_of( Expectation, expectation2 ) assert_equal( "#{@hash.name}[KEY2]", expectation2.name ) end def test_index_returns_same_expectation assert_same( @hash[:KEY], @hash[:KEY] ) end def test_elements_verified @hash["KEY"].expect { |value| } assert_raises Test::Unit::AssertionFailedError do @hash.verify end end def test_assign_sets_actual_value @hash["KEY"] = "VALUE" assert_equal( "VALUE", @hash["KEY"].actual ) end end class ExpectationStub attr_reader :verify_called def initialize @verify_called = false end def verify @verify_called = true end end class MockObjectTest < Test::Unit::TestCase def test_verify expectation1 = ExpectationStub.new expectation2 = ExpectationStub.new mock = MockObject.new mock.instance_eval do @expectation1 = expectation1 @expectation2 = expectation2 end mock._verify assert( expectation1.verify_called, "expectation1 verify called" ) assert( expectation2.verify_called, "expectation2 verify called" ) end end --- NEW FILE: notes.txt --- 1) No need for mocks to subclass existing interfaces -- dynamic languages don't have or *need* interfaces. This is especially useful when we need to test the interactions between our classes and third party classes, such as those defined by the language and standard library. We don't have to work out how to mock concrete classes that are not implementations of abstract interfaces or final classes. For example, it is trivial to mock the file system in Ruby, but it is quite hard to do so in Java (see the alt.java.* packages in the Mock Objects library). 2) Expectations can be defined using closures, rather than various expectation classes. Closures can call the Test::Unit assertions defined in the TestCase class and access local variables defined in the test method, even though they are called from within a mock object. This makes mock-object classes very flexible, because expectations can be tailored for each test method. 3) There is less need to define factories to insert mock objects into your classes. In Ruby, classes just objects with a "new" method, and sometimes other methods that create objects. That is, classes *are* factories. So, where in Java we would pass a factory to our objects, so that we could use a factory to create mock objects in our tests, we can pass *classes* to our objects. However, because a class is just an object, in our tests we can create a stub class that returns prepared mock objects, and pass that object to our tested objects instead of a class. To the tested object, the stub responds to the same messages as a class, and so to all intents and purposes *is* a class. 4) NOTE: POTENTIAL PITFALL Servlet used a hash to store names. Changed to use an address book object with the same interface. Address book was tested, but servlet tests were not changed, so servlet still tested against hash object. However, address book didn't implement all methods used by the servlet so servlet failed when run in server. Implemented a mock address book that implemented the same methods as the actual address book, and then changed the servlet tests to use that mock. That caught the error. Alternatively, integration tests (acceptance tests) would have caught the error. LESSON LEARNED: Type system does not help you catch errors at compile time. So, need to be more disciplined in writing your tests. If you introduce a new class, you must write both unit tests for that class *and* a mock for that class, and change the tests for the client classes to use the mock. Keep the mock and the class/unit tests in sync, so that they both implement the same methods. That way you catch errors where client code is being tested against a mock that does not actually implement the same methods as the real class that it is mocking. Index: addrservlet.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/addrservlet.rb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- addrservlet.rb 31 Aug 2002 10:55:21 -0000 1.1 +++ addrservlet.rb 2 Sep 2002 14:53:00 -0000 1.2 @@ -1,38 +1,38 @@ - -require 'webrick' - - -class AddressBookServlet < WEBrick::HTTPServlet::AbstractServlet - def initialize( config, address_book ) - super - @address_book = address_book - end - - def do_GET( request, response ) - response['content-type'] = 'text/plain' - - query = request.query_string - if query == nil - respond_no_match( response ) - else - name = WEBrick::HTTPUtils::unescape_form( query ) - find_address( name, response ) - end - end - - def find_address( name, response ) - if @address_book.has_key?(name) - respond_address( response, @address_book[name] ) - else - respond_no_match( response ) - end - end - - def respond_address( response, address ) - response.body = address - end - - def respond_no_match( response ) - response.body = "no address found" - end -end + +require 'webrick' + + +class AddressBookServlet < WEBrick::HTTPServlet::AbstractServlet + def initialize( config, address_book ) + super + @address_book = address_book + end + + def do_GET( request, response ) + response['content-type'] = 'text/plain' + + query = request.query_string + if query == nil + respond_no_match( response ) + else + name = WEBrick::HTTPUtils::unescape_form( query ) + find_address( name, response ) + end + end + + def find_address( name, response ) + if @address_book.has_key?(name) + respond_address( response, @address_book[name] ) + else + respond_no_match( response ) + end + end + + def respond_address( response, address ) + response.body = address + end + + def respond_no_match( response ) + response.body = "no address found" + end +end Index: server.rb =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/server.rb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- server.rb 31 Aug 2002 10:55:21 -0000 1.1 +++ server.rb 2 Sep 2002 14:53:00 -0000 1.2 @@ -1,14 +1,13 @@ -#!/usr/bin/ruby - -require 'webrick' -require 'addrservlet' - -server = WEBrick::HTTPServer.new( :Port => 2000 ) -server.mount( "/address", AddressBookServlet, - "Nat Pryce" => "nat...@so...", - "Steve Freeman" => "st...@so...", - "Jeff Martin" => "cus...@so..." ) - -trap("INT") { server.shutdown } - -server.start +#!/usr/bin/ruby + +require 'webrick' +require 'addrbook' +require 'addrservlet' + +server = WEBrick::HTTPServer.new( :Port => 2000 ) +server.mount( "/address", AddressBookServlet, + AddressBook.new("addresses.txt") ) + +trap("INT") { server.shutdown } + +server.start Index: tasks.txt =================================================================== RCS file: /cvsroot/mockobjects/no-stone-unturned/src/ruby/tasks.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- tasks.txt 31 Aug 2002 10:55:21 -0000 1.1 +++ tasks.txt 2 Sep 2002 14:53:00 -0000 1.2 @@ -21,6 +21,8 @@ REFACTORING + - refactor code + - refactor tests to use expectation and mockobject classes 1c) Retrieve the entries from a file, specified as a servlet property. |
From: Jeff M. <je...@mk...> - 2002-09-02 11:42:04
|
Anyone mind if I promote the version of the sire at http://www.custommonkey.org/mock/ to http://www.mockobjects.com/ there's not much difference between the two but it will bring the live site in line with cvs -- jeff martin information technologist mkodo limited mobile: 44 (0) 78 5547 8331 phone: 44 (0) 20 2226 4545 email: je...@mk... www.mkodo.com |
From: Jeff M. <cus...@us...> - 2002-09-02 11:40:00
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/html In directory usw-pr-cvs1:/tmp/cvs-serv23661/html Modified Files: template.txt Log Message: Move FAG to about section and todo to developers Index: template.txt =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/template.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- template.txt 2 Sep 2002 10:26:25 -0000 1.3 +++ template.txt 2 Sep 2002 11:39:57 -0000 1.4 @@ -37,7 +37,7 @@ <h4>About</h4> <a href="./index.html" class="menu">Home</a><br> - <a href="./todo.html" class="menu">Roadmap/Todo</a><br> + <a href="./faq.html" class="menu">FAQ</a><br> <a href="./changes.html" class="menu">Changes</a><br> <a href="./license.html" class="menu">License</a><br> @@ -46,7 +46,6 @@ <h4>Documentation</h4> <a href="./endotesting.html" class="menu">Introduction</a><br> - <a href="./faq.html" class="menu">FAQ</a><br> <a href="./papers.html" class="menu">Papers</a><br> <a href="./naming_conventions.html" class="menu">Naming conventions</a><br> <a target="" href="javadoc/index.html" class="menu">API Reference</a><br> @@ -56,6 +55,7 @@ <a target="" href="http://sourceforge.net/mail/?group_id=18189" class="menu">Mailing list</a><br> <h4>Developers</h4> + <a href="./todo.html" class="menu">Roadmap/Todo</a><br> <a target="" href="http://sourceforge.net/cvs/?group_id=18189" class="menu">CVS</a><br> <a href="./coding_conventions.html" class="menu">Coding conventions</a><br> <a href="./release_process.html" class="menu">Release process</a><br> |
From: Jeff M. <cus...@us...> - 2002-09-02 11:35:11
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/html In directory usw-pr-cvs1:/tmp/cvs-serv22179/html Modified Files: coding_conventions.html release_process.html stylesheet.css todo.html Log Message: More tidy ups Index: coding_conventions.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/coding_conventions.html,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- coding_conventions.html 2 Sep 2002 10:26:25 -0000 1.2 +++ coding_conventions.html 2 Sep 2002 11:35:07 -0000 1.3 @@ -17,8 +17,6 @@ <h2>Mock Objects specific coding conventions</h2> -<ol> -<li> <h3>Brackets</h3> <p>For class and method declaration, brackets should begin on the <b>same</b> line. Example:</p> <pre> @@ -58,9 +56,7 @@ // some code } </pre> -</li> -<li> <h3>Blank Spaces</h3> <p> keywords followed by a parenthesis should be separated by a space. Example : @@ -84,133 +80,30 @@ printSize("size is " + foo + "\n"); </pre> -</li> -<li> <h3>Indentations</h3> <p><b>4 spaces. NO tabs</b>. Period. We understand that a lot of you like to use tabs, but the fact of the matter is that in a distributed development environment, when the cvs commit messages get sent to a mailing list, they are almost impossible to read if you use tabs.</p> - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>4. Comments</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Javadoc SHOULD exist - on all your class members (methods - + class variables), including the - private ones. Also, if you are - working on existing code and there - currently isn't a javadoc for that - method/class/variable or whatever, - then you should contribute and add - it. This will improve the project - as a whole.</p> - - <p class="c9">Also add code - comments when you think it's - necessary (like assumptions), - especially when the code is not - obvious.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>5. License</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">The Jakarta - Apache/Cactus License MUST be - placed at the top of each and every - file.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>6. Author references</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">If you contribute to - a file (code or documentation), add - yourself to the top of the file - (below the existing authors). For - java files the preferred Javadoc - format is:</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> +<h3>Comments</h3> +<p>Javadoc SHOULD exist on all your class members (methods + class variables), including the private ones. Also, if you are working on existing code and there currently isn't a javadoc for that method/class/variable or whatever, then you should contribute and add it. This will improve the project as a whole.</p> + +<p>Also add code comments when you think it's necessary (like assumptions), especially when the code is not obvious.</p> + +<h3>License</h3> +<p>The Jakarta Apache/Cactus License MUST be placed at the top of each and every file.</p> + +<h3>Author references</h3> + +<p>If you contribute to a file (code or documentation), add yourself to the top of the file (below the existing authors). For java files the preferred Javadoc format is:</p> + <pre> @author <a href="mailto:us...@do...">John Doe</a> </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>7. Class variables</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Class variables - should be prefixed with <b>my</b>. - Example :</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> + +<h3>Class variables</h3> + +<p>Class variables should be prefixed with <b>my</b>. Example :</p> + <pre> public class SomeClass { private String myString; @@ -220,141 +113,25 @@ } } </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>8. Parameter names</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Method parameters - should be prefixed by "<code class= - "c14">a</code>" (for - differentiating them from inner - variables). For example :</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> + +<h3>Parameter names</h3> + +<p>Method parameters should be prefixed by "<code>a</code>" (for differentiating them from inner variables). For example :</p> + <pre> public void someMethod(String aClassName) { String className; // inner variable } </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>9. Line length</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Avoid lines longer - than 78 characters for Code, - comments, ...</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>10. Versionning</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">All .java files - should have a <code class= - "c14">@version</code> tag like the - one below.</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> +<h3>Line length</h3> +<p>Avoid lines longer than 78 characters for Code, comments, ...</p> + +<h3>Versioning</h3> + +<p>All .java files should have a <code>@version</code> tag like the one below.</p> + <pre> @version $Id$ </pre> - </td> - </tr> - </table> - </div> - - <table border="0" cellpadding="0" - cellspacing="3" width="100%"> - <tr> - <td valign="top" width="28"> - <img alt="Note" border="0" - hspace="0" vspace="0" height= - "29" width="28" src= - "images/note.gif"></td> - - <td valign="top"><span class= - "c10"><i>You just need to write - <code class="c14">@version $Id: - coding_conventions.xml,v 1.4 - 2001/08/22 10:36:45 vmassol Exp - $</code> and CVS will add the - rest during commits</i></span> - </td> - </tr> - </table> - <br> - <br> - <span class="c8"></span> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - </td> - </tr> - </table> - </div> - <br> + +<p><img align="left" alt="Note" border="0" height= "29" width="28" src="images/note.gif"><i>You just need to write <code >@version $Id: $</code> and CVS will add the rest during commits</i></p> Index: release_process.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/release_process.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- release_process.html 29 Aug 2002 12:17:21 -0000 1.1 +++ release_process.html 2 Sep 2002 11:35:07 -0000 1.2 @@ -1,153 +1,27 @@ - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" width= - "100%"> - <tr> - <td bgcolor="#525D76" class="c7"><b>Introduction</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">This document highlights our release - process. It defines all the steps that need to be - performed <b>before</b> releasing a new version of the - Mock Objects project.</p> - </td> - </tr> - </table> - </div> - <br> +<h1>Release Process</h1> +<h2>Introduction</h2> + +<p class="c9">This document highlights our release process. It defines all the steps that need to be performed <b>before</b> releasing a new version of the Mock Objects project.</p> - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" width= - "100%"> - <tr> - <td bgcolor="#525D76" class="c7"><b>General - steps</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" - width="99%"> - <tr> - <td bgcolor="#525D76" class="c11"><b>Decide on - the content of a release</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Long before any release, we need - to define what will go into that release, i.e. - the list of tasks that need to be performed - <b>prior</b> to that release. These tasks will - be listed on the <a href="todo.html">Todo - page</a>. Tasks can be proposed on the <a href= - "http://sourceforge.net/mail/?group_id=18189">mailing - list</a>.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" - width="99%"> - <tr> - <td bgcolor="#525D76" class="c11"><b>Deciding on - doing a release</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Releasing a version is a - community action that we all need to decide - together (the committers of the project). - Before <b>any</b> release, we will need to - agree on doing a release. This entails sending - a message on the <a href= - "http://sourceforge.net/mail/?group_id=18189">mailing - list</a> asking for a vote on the release. We - will use the <a href= - "http://jakarta.apache.org/site/decisions.html"> - Apache Jakarta system for voting</a>.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" - width="99%"> - <tr> - <td bgcolor="#525D76" class="c11"><b>Updating the - Changes page</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">The <a href= - "changes.html">Changes page</a> need to be up - to date at any time. The goal of this page is - not to described fine-grained changes in CVS - like "I have corrected a typo" but rather to - advertise changes that are useful to end users - (for example: "Improved the Mailing-list - example by ..."). As it is very hard to - remember everything that everyone has done, it - is mandatory to fill this page as we do the - modifications and not to wait till the release - to fill it.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - </td> - </tr> - </table> - </div> - <br> +<h2>General steps</h2> +<h3>Decide on the content of a release</h3> + +<p class="c9">Long before any release, we need to define what will go into that release, i.e. the list of tasks that need to be performed <b>prior</b> to that release. These tasks will be listed on the <a href="todo.html">Todo page</a>. Tasks can be proposed on the <a href="http://sourceforge.net/mail/?group_id=18189">mailing list</a>.</p> + +<h3>Deciding on doing a release</h3> + +<p>Releasing a version is a community action that we all need to decide together (the committers of the project). Before <b>any</b> release, we will need to agree on doing a release. This entails sending a message on the <a href= "http://sourceforge.net/mail/?group_id=18189">mailing list</a> asking for a vote on the release. We will use the <a href= "http://jakarta.apache.org/site/decisions.html"> Apache Jakarta system for voting</a>.</p> + +<h3>Updating the Changes page</h3> + +<p>The <a href= "changes.html">Changes page</a> need to be up to date at any time. The goal of this page is not to described fine-grained changes in CVS like "I have corrected a typo" but rather to advertise changes that are useful to end users (for example: "Improved the Mailing-list example by ..."). As it is very hard to remember everything that everyone has done, it is mandatory to fill this page as we do the modifications and not to wait till the release to fill it.</p> - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" width= - "100%"> - <tr> - <td bgcolor="#525D76" class="c7"><b>Detailed - administrative steps</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> +<h2>Detailed administrative steps</h2> - <p class="c9">This is a detailed check list of all the - steps involved to actually perform the release :</p> +<p>This is a detailed check list of all the steps involved to actually perform the release : - <blockquote> <ol> <li>Agree on a release (see above).</li> @@ -212,8 +86,4 @@ <li>... then relax ! ;-)</li> </ol> - </blockquote> - </td> - </tr> - </table> - </div> +</p> Index: stylesheet.css =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/stylesheet.css,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- stylesheet.css 2 Sep 2002 10:26:25 -0000 1.1 +++ stylesheet.css 2 Sep 2002 11:35:07 -0000 1.2 @@ -9,7 +9,7 @@ color: white; background-color: #023264; padding: 5; - font-size:150%; + font-size:120%; } h2{ @@ -17,7 +17,7 @@ background-color: #023264; padding: 3; margin-left: 10; - font-size:130%; + font-size:110%; } h3{ @@ -25,12 +25,13 @@ background-color: #023264; padding: 3; margin-left: 20; - font-size:110%; + font-size:100%; } p{ margin-left: 30; margin-right: 30; + font-size:12px; } :link { color: #525D76 } Index: todo.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/todo.html,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- todo.html 30 Aug 2002 14:50:32 -0000 1.2 +++ todo.html 2 Sep 2002 11:35:07 -0000 1.3 @@ -25,6 +25,7 @@ <h2>Version 0.02</h2> <h3>Documentation</h3> +<p> <table cellpadding="2" cellspacing= "2" border="0" width="100%"> <tr> @@ -88,9 +89,11 @@ "c13"> </span> </td> </tr> </table> + </p> <h3>Code</h3> +<p> <table cellpadding="2" cellspacing= "2" border="0" width="100%"> <tr> @@ -127,8 +130,10 @@ </td> </tr> </table> +</p> <h3>Build</h3> +<p> <table cellpadding="2" cellspacing= "2" border="0" width="100%"> <tr> @@ -162,3 +167,4 @@ Massol </span> </td> </tr> </table> +</p> |
From: Jeff M. <cus...@us...> - 2002-09-02 10:26:28
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/html In directory usw-pr-cvs1:/tmp/cvs-serv1754/html Modified Files: changes.html coding_conventions.html license.html naming_conventions.html template.txt Added Files: stylesheet.css Log Message: Tidy up html and change template to use external css --- NEW FILE: stylesheet.css --- body { background-color: white; color: black; font-size:12px; font-family: Verdana, Arial, Helvetica, sans-serif; } h1{ color: white; background-color: #023264; padding: 5; font-size:150%; } h2{ color: white; background-color: #023264; padding: 3; margin-left: 10; font-size:130%; } h3{ color: white; background-color: #023264; padding: 3; margin-left: 20; font-size:110%; } p{ margin-left: 30; margin-right: 30; } :link { color: #525D76 } :visited { color: #023264 } :active { color: #023264 } pre{ background: #eee; padding: 10; margin-left: 30; margin-right: 30; } Index: changes.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/changes.html,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- changes.html 30 Aug 2002 14:50:32 -0000 1.2 +++ changes.html 2 Sep 2002 10:26:25 -0000 1.3 @@ -1,26 +1,24 @@ <h1>Changes</h1> -<h2> 0.4 (release on 24 July 2002</h2> -<h2> 0.01 (release on 12 August 2001</h2> +<h2> 0.4 release on 24 July 2002</h2> +<p> +Well a lot happend here, but we weren't really counting +</p> +<h2> 0.01 release on 12 August 2001</h2> <ul> <li><img align="absmiddle" border="0" - alt="update" src="images/update.jpg"> The - distribution zip now includes a zip of - the sources. (SMGF)</li> + alt="update" src="images/update.jpg"> +The distribution zip now includes a zip of the sources. (SMGF) + </li> <li><img align="absmiddle" border="0" alt="update" src="images/update.jpg"> - Improved the build process and generate - the user web site from XML files using - stylebook. (VMA)</li> +Improved the build process and generate the user web site from XML files using stylebook. (VMA) + </li> <li><img align="absmiddle" border="0" - alt="add" src="images/add.jpg"> Added a - user web site (in addition to the <a - href= - "http://sf.net/projects/mockobjects">developer's - web site</a> provided by SourceForge). - Added a project description, todo and - changes pages. (VMA)</li> + alt="add" src="images/add.jpg"> +Added a user web site (in addition to the <a href= "http://sf.net/projects/mockobjects">developer's web site</a> provided by SourceForge). Added a project description, todo and changes pages. (VMA) + </li> </ul> Index: coding_conventions.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/coding_conventions.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- coding_conventions.html 29 Aug 2002 12:17:21 -0000 1.1 +++ coding_conventions.html 2 Sep 2002 10:26:25 -0000 1.2 @@ -1,123 +1,37 @@ - <div class="c11"> - <table cellpadding="2" cellspacing="0" border="0" - width="100%"> - <tr> - <td bgcolor="#525D76" class="c7"> - <b>Forewords</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">This document describes a - list of coding conventions that are - required for code submissions to the - project. By default, the coding conventions - for most Open Source Projects should follow - the existing coding conventions in the code - that you are working on. For example, if - the bracket is on the same line as the if - statement, then you should write all your - code to have that convention.</p> - - <table border="0" cellpadding="0" - cellspacing="3" width="100%"> - <tr> - <td valign="top" width="28"><img alt= - "Note" border="0" hspace="0" vspace="0" - height="29" width="28" src= - "images/note.gif"></td> - - <td valign="top"><span class= - "c10"><i><b>If you commit code that - does not follow these conventions and - you are caught, you are responsible for - also fixing your own - code.</b></i></span> </td> - </tr> - </table> - <br> - <br> - <span class="c8"></span> - - <p class="c9">Below is a list of coding - conventions that are specific to Mock - Objects, everything else not specificially - mentioned here should follow the official - <a href= - "http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html"> - Sun Java Coding Conventions</a>.</p> - </td> - </tr> - </table> - </div> - <br> +<h1>Coding Conventions</h1> +<h2>Forewords</h2> + +<p> +This document describes a list of coding conventions that are required for code submissions to the project. By default, the coding conventions for most Open Source Projects should follow the existing coding conventions in the code that you are working on. For example, if the bracket is on the same line as the if statement, then you should write all your code to have that convention. +</p> + +<p> +<img alt= "Note" border="0" align="left" height="29" width="28" src= "images/note.gif"> +<b><i>If you commit code that does not follow these conventions and you are caught, you are responsible for also fixing your own code.</b></i> +</p> + +<p> +Below is a list of coding conventions that are specific to Mock Objects, everything else not specificially mentioned here should follow the official <a href= "http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html"> Sun Java Coding Conventions</a>. +</p> - <div class="c11"> - <table cellpadding="2" cellspacing="0" border="0" - width="100%"> - <tr> - <td bgcolor="#525D76" class="c7"><b>Mock - Objects specific coding conventions</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>1. Brackets</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">For class and method - declaration, brackets should begin - on the <b>same</b> line. Example - :</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> +<h2>Mock Objects specific coding conventions</h2> + +<ol> +<li> + <h3>Brackets</h3> + <p>For class and method declaration, brackets should begin on the <b>same</b> line. Example:</p> <pre> public class SomeClass { public void someMethod() { } } </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">Brackets for blocks - of code inside methods should begin - and end on the <b>same</b> line - (this applies to <code class= - "c14">if</code>, <code class= - "c14">for</code>, <code class= - "c14">while</code>, <code class= - "c14">try/catch</code>, ...). - Example :</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> + +<p> +Brackets for blocks of code inside methods should begin and end on the <b>same</b> line (this applies to <code>if</code>, <code>for</code>, <code>while</code>, <code>try/catch</code>, ...). Example : +</p> + <pre> public void someMethod() { if (expression) { @@ -129,20 +43,11 @@ } } </pre> - </td> - </tr> - </table> - </div> <p class="c9"><b>Brackets are mandatory even for single line statements !</b></p> - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> // Incorrect if (expression) @@ -153,60 +58,22 @@ // some code } </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>2. Blank Spaces</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">keywords followed by - a parenthesis should be separated - by a space. Example :</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> +</li> + +<li> +<h3>Blank Spaces</h3> +<p> +keywords followed by a parenthesis should be separated by a space. Example : +</p> + <pre> while (true) { // some code } </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">Blank space should - appear after commas in argument - lists. Binary operators should be - separated from their operands by - spaces :</p> - - <div class="c13"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> + +<p>Blank space should appear after commas in argument lists. Binary operators should be separated from their operands by spaces :</p> + <pre> a += c + d; a = (a + b) / (c * d); @@ -217,45 +84,11 @@ printSize("size is " + foo + "\n"); </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c11"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c12"> - <b>3. Indentations</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9"><b>4 spaces. NO - tabs</b>. Period. We understand - that a lot of you like to use tabs, - but the fact of the matter is that - in a distributed development - environment, when the cvs commit - messages get sent to a mailing - list, they are almost impossible to - read if you use tabs.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> +</li> + +<li> +<h3>Indentations</h3> +<p><b>4 spaces. NO tabs</b>. Period. We understand that a lot of you like to use tabs, but the fact of the matter is that in a distributed development environment, when the cvs commit messages get sent to a mailing list, they are almost impossible to read if you use tabs.</p> <div class="c11"> <table cellpadding="2" cellspacing="0" Index: license.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/license.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- license.html 29 Aug 2002 12:17:21 -0000 1.1 +++ license.html 2 Sep 2002 10:26:25 -0000 1.2 @@ -1,22 +1,4 @@ - - <div class="c10"> - <table cellpadding="2" cellspacing="0" border="0" - width="100%"> - <tr> - <td bgcolor="#525D76" class="c7"><b>Mock - Objects Public License</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <div class="c9"> - <table cellpadding="2" cellspacing="2" - border="1"> - <tr> - <td> +<h1>Mock Objects Public License</h1> <pre> /* ==================================================================== * The Apache Software License, Version 1.1 @@ -72,14 +54,3 @@ * <http://www.apache.org/>. */ </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <br> - - Index: naming_conventions.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/naming_conventions.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- naming_conventions.html 29 Aug 2002 12:17:21 -0000 1.1 +++ naming_conventions.html 2 Sep 2002 10:26:25 -0000 1.2 @@ -1,173 +1,55 @@ +<h1>Mock Object Naming Conventions</h1> +<p> +Over time we have developed some naming conventions for how we write mock objects which we believe make them easier to work with. +</p> + +<h2>Creating expectations</h2> + +<p> +We have built up a library of expectation classes to help with the development of mock objects. Each expectation object will compare pre-loaded expected values with actual values as they arrive. Where possible, the comparison will be made as the actual object is set, which helps to locate errors when they occur. Each expectation class has a constructor that takes a name value. This name will be displayed when an assertion fails, so it should help to identify the source of any error. For example, the instance variables for the mock sql statement include: +</p> - <div class="c13"> - <table cellpadding="2" cellspacing="0" border="0" - width="100%"> - <tr> - <td bgcolor="#525D76" class="c7"><b>Mock - Object Naming Conventions</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">Over time we have developed - some naming conventions for how we write - mock objects which we believe make them - easier to work with.</p> - - <div class="c13"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c10"> - <b>Creating expectations</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">We have built up a - library of expectation classes to - help with the development of mock - objects. Each expectation object - will compare pre-loaded expected - values with actual values as they - arrive. Where possible, the - comparison will be made as the - actual object is set, which helps - to locate errors when they occur. - Each expectation class has a - constructor that takes a name - value. This name will be displayed - when an assertion fails, so it - should help to identify the source - of any error. For example, the - instance variables for the mock sql - statement include:</p> - - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - protected ExpectationCounter myCloseCalls = - new ExpectationCounter("MockStatement.closeCalls"); - protected ExpectationCounter myExecuteCalls = - new ExpectationCounter("MockStatement.executeCalls"); - protected ExpectationValue myQueryString = - new ExpectationValue("MockStatement.queryString"); +protected ExpectationCounter myCloseCalls = + new ExpectationCounter("MockStatement.closeCalls"); +protected ExpectationCounter myExecuteCalls = + new ExpectationCounter("MockStatement.executeCalls"); +protected ExpectationValue myQueryString = + new ExpectationValue("MockStatement.queryString"); </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">Note that the - variables have the name of the - thing they test, <code class= - "c12">myQueryString</code> rather - than <code class= - "c12">myExpectedQueryString</code>. - This is to avoid repetitions such - as :</p> - - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> + +<p> +Note that the variables have the name of the thing they test, <code>myQueryString</code> rather than <code>myExpectedQueryString</code>. This is to avoid repetitions such as :</p> + <pre> - myExpectedQueryString.setExpected(aString); +myExpectedQueryString.setExpected(aString); </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c13"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c10"> - <b>Setting expectations</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">All expectations are - set with a method beginning <code - class= - "c12">setExpected<condition>,</code> - where <code class= - "c12"><condition></code> is a - state or behaviour that will be - verified during or at the end of - the test. For example,</p> - - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> + +<h2>Setting expectations</h2> + +<p> +All expectations are set with a method beginning <code>setExpected<condition>,</code> where <code><condition></code> is a state or behaviour that will be verified during or at the end of the test. For example, +</p> + <pre> - myMockHttpResponse.setExpectedContentType("text/plain"); +myMockHttpResponse.setExpectedContentType("text/plain"); </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">says that the <code - class="c12">HttpResponse</code> - expects to have its content type - set to <code class= - "c12">"text/plain"</code> during - the test.</p> - - <p class="c9">If an expectation - that a mock object supports is not - set, then it will not be verified, - this makes it easier to use a mock - object for multiple tests. To check - that a value is not changed during - a test, each Expectation type - supports the method <code class= - "c12">setExpectNothing</code>. For - example, to test that no properties - of a bean have been set its mock - implementation might include the - method :</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> +<p> +says that the <code>HttpResponse</code> expects to have its content type set to <code>"text/plain"</code> during the test. +</p> + +<p> +If an expectation that a mock object supports is not set, then it will not be verified, this makes it easier to use a mock object for multiple tests. To check that a value is not changed during a test, each Expectation type supports the method <code>setExpectNothing</code>. For example, to test that no properties of a bean have been set its mock implementation might include the method : +</p> + <pre> - public void setExpectNoPropertiesSet() { +public void setExpectNoPropertiesSet() { myProperties.setExpectNothing(); - } +} </pre> - </td> - </tr> - </table> - </div> - <p class="c9">The expectation + <p>The expectation collections include methods for adding single objects and collections of objects. This is to @@ -182,127 +64,45 @@ expected values. For example, the method :</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - public void addExpectedProperty(String property) { +public void addExpectedProperty(String property) { myProperties.addExpected(property); - } +} </pre> - </td> - </tr> - </table> - </div> - <p class="c9">adds an additional + <p>adds an additional property that the mock object will expect to receive. The method :</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - public void setExpectedProperty(String property) { +public void setExpectedProperty(String property) { myProperties.setExpectNothing(); myProperties.addExpected(property); - } +} </pre> - </td> - </tr> - </table> - </div> - <p class="c9">resets the property + <p>resets the property expectation.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c13"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c10"> - <b>Setting actual values</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> - - <p class="c9">The actual values for - comparison against the expected - values will be set in the mock - implementations of real methods. - For example, we count the number of - times <code class= - "c12">close</code> is called in a - mock sql statement in the method - :</p> +<h3>Setting actual values</h3> +<p>The actual values for comparison against the expected values will be set in the mock implementations of real methods. For example, we count the number of times <code>close</code> is called in a mock sql statement in the method:</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - public void close() throws SQLException { +public void close() throws SQLException { myCloseCalls.inc(); - } +} </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">similarly, to set a +<p>similarly, to set a positional parameter in a mock prepared statement :</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - public void setObject(int param, Object obj) throws SQLException { +public void setObject(int param, Object obj) throws SQLException { mySetParameters.addActual(new MapEntry(new Integer(param), obj)); - } +} </pre> - </td> - </tr> - </table> - </div> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - - <div class="c13"> - <table cellpadding="2" cellspacing="0" - border="0" width="99%"> - <tr> - <td bgcolor="#525D76" class="c10"> - <b>Setting stub values</b></td> - </tr> - - <tr> - <td> - <span class="c8"><br> - </span> +<h3>Setting stub values</h3> - <p class="c9">Many mock objects are +<p>Many mock objects are used for both validation of expectations and as stub implementations to allow tests to @@ -316,67 +116,34 @@ they are set. The setter method is :</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - public void setupAddParameter(String paramName, String value) { +public void setupAddParameter(String paramName, String value) { setupAddParameter(paramName, new String[] { value }); - } +} </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">Our convention is + <p>Our convention is that stub methods start with <code - class= - "c12">setup<state></code> to + >setup<state></code> to distinguish them from Java setter methods which have the format <code - class= - "c12">set<state></code>. Stub + >set<state></code>. Stub values are used by mock implementations of real methods.</p> - <p class="c9">One unusual stub + <p>One unusual stub setting we use quite often is to force exceptions to be thrown. For example, the mock sql statement includes the method :</p> - <div class="c11"> - <table cellpadding="2" - cellspacing="2" border="1"> - <tr> - <td> <pre> - public void setupThrowExceptionOnExecute(SQLException exception); +public void setupThrowExceptionOnExecute(SQLException exception); </pre> - </td> - </tr> - </table> - </div> - - <p class="c9">The statement stores + <p>The statement stores the given exception object and - throws it when <code class= - "c12">execute()</code> is called. + throws it when <code + >execute()</code> is called. This technique is sometimes the only way to test certain types of failure.</p> - </td> - </tr> - </table> - </div> - <span class="c8"><br> - </span> - </td> - </tr> - </table> - </div> - <br> Index: template.txt =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/template.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- template.txt 29 Aug 2002 12:57:50 -0000 1.2 +++ template.txt 2 Sep 2002 10:26:25 -0000 1.3 @@ -3,32 +3,7 @@ <meta name="generator" content="HTML Tidy, see www.w3.org"> <title>Mock Objects</title> -<style type="text/css"> - body '{' - background-color: #ffffff; - color: #000000; - '}' - :link '{' color: #525D76 '}' - :visited '{' color: #023264 '}' - :active '{' color: #023264 '}' - span.c14 '{'color: #525D76; font-family: arial,helvetica,sanserif; font-size: -80%'}' - div.c13 '{'text-align: right'}' - code.c12 '{'font-family: courier, monospaced'}' - div.c11 '{'text-align: center'}' - td.c10 '{'color: #ffffff; font-family: arial,helvetica,sanserif; font-size: -100%'}' - p.c9 '{'color: #000000; font-family: arial,helvetica,sanserif; text-align: -justify'}' - span.c8 '{'color: #000000; font-family: arial,helvetica,sanserif'}' - td.c7 '{'color: #ffffff; font-family: arial,helvetica,sanserif; font-size: -119%'}' - li.c6 '{'list-style: none'}' - a.menu '{'font-size: 80%'}' - span.c4 '{'font-family: arial,helvetica,sanserif'}' - span.c3 '{'font-size: 80%'}' - span.c1 '{'font-size: 64%'}' -</style> + <link rel="stylesheet" href="stylesheet.css" type="text/css"> </head> <body marginheight="4" marginwidth="4" leftmargin="4" topmargin= @@ -111,7 +86,7 @@ </tr> <tr> - <td align="center"><span class="c14"><i>Copyright © + <td align="center"><span><i>Copyright © 2001 Mock Objects. All Rights Reserved.</i></span> </td> </tr> </table> |
From: Jeff M. <cus...@us...> - 2002-09-02 10:26:27
|
Update of /cvsroot/mockobjects/mockobjects-java/doc In directory usw-pr-cvs1:/tmp/cvs-serv1754 Modified Files: site.xml Log Message: Tidy up html and change template to use external css Index: site.xml =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/site.xml,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- site.xml 29 Aug 2002 12:57:49 -0000 1.2 +++ site.xml 2 Sep 2002 10:26:25 -0000 1.3 @@ -1,7 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <project name="site" default="site" basedir="."> - <target name="site"> + <target name="copy-stylesheet"> + <copy file="html/stylesheet.css" todir="out"/> + </target> + + <target name="site" depends="copy-stylesheet"> <javac srcdir="."> <include name="SiteHack.java"/> </javac> |
From: Jeff M. <cus...@us...> - 2002-09-02 10:24:40
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/html In directory usw-pr-cvs1:/tmp/cvs-serv1324/html Modified Files: faq.html Log Message: Added additions from ted and split into sections Index: faq.html =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/html/faq.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- faq.html 29 Aug 2002 12:57:50 -0000 1.1 +++ faq.html 2 Sep 2002 10:24:37 -0000 1.2 @@ -1,66 +1,128 @@ -<ul> - <li> +<h1>MockObject FAQ</h1> +<h2>General Questions About Mocks</h2> <h3>What's a mock object?</h3> - <p> - It's a thing! + + <p>A mock object is a "double agent" used to test the behavior +of other objects. First, a mock object acts as a faux implementation +of an interface or class that simulates the external behavior of a true implementation. +Second, a mock object observes how other objects interact with its +methods and compares actual behavior with preset expectations. When a discrepancy +occurs, a mock object can interrupt the test and report the anomaly. If the +discrepancy cannot be noted during the test, a verification method called +by the tester ensures that all expectations have been met or failures reported.<br> </p> - </li> - <li> + <h3>What's an expectation?</h3> - <p> - It's another thing! - </p> - </li> - <li> + + <p>When any component is used in a program, we anticipate a set of preconditions +and postconditions. For example, we might anticipate that a database connection +will be used once and then closed. We might also anticipate that a JDBC ResultSet +will be passed a certain set of parameters for use with a given SQL command. +A mock object can be told to expect conditions such as these, so that it +can report back when our expectations are not met. The MockObjects API has +refactored this mechanism into a framework of Expectation classes. </p> + <h3>Why should I bother?</h3> - <p> - </p> - </li> - <li> +<p>Today, most developers recognize the value of unit testing. But many developers +also find that creating and maintaining non-trivial unit tests becomes difficult +as products mature. Writing significant unit tests can tempt developers into +making objects "test-aware". This can complicate production code and begins +to defeat the purpose of unit testing. Mock objects simplify the creation +and maintenance of non-trivial unit tests by allowing us to test one object +at a time. Mock objects make it possible to test an object without its knowledge.</p> +<p> +Mock objects allow you to unit test your application independently of the +production infrastructure. Developers do not need access to a real database +to run the unit tests. The same is true of any external resource, including +hardware devices.</p> +<p> +Mock objects can also simulate states that may be difficult or time-consuming +to realize in a runtime environment. A mock object can throw any exception +or produce any error condition on demand. For example, using a real database, +to see how an object will react to an offline database you would have to +actually down the database. Using a mock JDBC connection, you can simulate +a dead database in one test and a live database in the next, all in a fraction +of a second.</p> + <p> +As products mature, and test suites grow larger, tracing the cause of a failed +test can become difficult. A mock implementation can test assertions each +time it interacts with production (or "domain") code. The test is then more +likely to fail at the right time and generate a useful message. </p> + <p> +We can also build base assertions about how domain objects are suppose to +work into our mock objects. These assertions can be applied automatically +whenever the mock object is used. This ensures that our base assertions remain +true as the application matures. </p> + <p> +We use mock objects because they allow us to quickly create inexpensive, +effective tests that are easy to maintain. </p> + + <h3>Do I have to change the way I write my programs?</h3> +<p>Usually not. In fact , mock objects should make it easier to test your programs +without making changes to your production objects. Generally, the better +designed your application, the easier it should be to test with mock objects. +If an application does not test well, there are usually ways to improve its +design and provide better testability. In practice, many developers +find that approaching new development with a test-first perspective helps +them write better programs more quickly. Writing tests for features helps +defines the objects we need to provide those features. Test-driven design +helps us discover the interfaces our objects actually need</p> + + <h3>What are some of the patterns used to create tests with mock objects?</h3> + <h3>Who discovered mock objects?</h3> + <h3>What is the difference between stub objects and mock objects?</h3> + + +<h2>About the Mock Object Implementation</h2> + + <h3>Why do I have to call setup???? to instead of set??? to add something to a map?</h3> <p> </p> - </li> - <li> + + <h3>Who do I contribute changes back to the mock objects project?</h3> <p> </p> - </li> - <li> + + <h3>What does it mean when I get a NotImplementedException?</h3> <p> </p> - </li> - <li> + + <h3>How do I write a mock?</h3> <p> </p> - </li> - <li> + + <h3>Why don't mocks verify their expectations?</h3> <p> </p> - </li> - <li> + + <h3>What are the alt.* packages for?</h3> <p> </p> - </li> - <li> + + <h3>What do I do if I can't find a mock for a class?</h3> <p> </p> - </li> - <li> + + <h3>Are there any tools to help create mocks?</h3> <p> </p> - </li> - <li> - <h3>Why are the internals of mock private when there just test classes?</h3> - <p> - </p> - </li> -</ul> + + + <h3>Why are the internals of mock private when there just test class?</h3> + <h3>What is the best practice for integrating mocks into a project?</h3> + +<h2>Other Questions</h2> + + <h3>What are the differences between the EasyMock and MockMaker approaches?</h3> + + |