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: Steve F. <st...@m3...> - 2001-08-13 21:38:29
|
PiBzb21lIHJlZm9ybWF0dGluZyBpbiB0aGUgZGlzdCB0YXJnZXQuIENhbiB3ZSBhZ3JlZSBvbiB1 c2luZyA0IHNwYWNlcyBmb3IgdGFidWxhdGlvbnMgDQogIGFuZCBfbm90XyB0YWJzIGFzIHRoZXkg YXJlIGRpZmZlcmVudCBmb3IgZXZlcnlvbmUgYW5kIG1ha2VzIHRoZSBjb2RlIHVucmVhZGFibGUu IA0KICBBbHNvIEkgd291bGQgcHJlZmVyIHRvIHVzZSB0aGUgbmVzdGVkIGVsZW1lbnRzIGZvcm0g aW5zdGVhZCBvZiBhdHRyaWJ1dGVzIA0KICBhcyB0aGlzIGlzIG5vdyB0aGUgcHJlZmVycmVkIG1l dGhvZCBpbiBBbnQgYW5kIGFsbG93cyBmb3IgbW9yZSBmbGV4aWJpbGl0eSAod2lsZGNhcmRzLCAu Li4pIA0KICBidXQgdGhpcyBpcyByZWFsbHkgIG5vdCB0aGF0IGltcG9ydGFudCAuLi4gOikNCg0K QUNLLiBFZGl0b3IgcHJvYmxlbXMuDQoNClN0ZXZlDQoNCg== |
From: Vincent M. <vm...@us...> - 2001-08-13 06:59:54
|
Update of /cvsroot/mockobjects/mockobjects-java In directory usw-pr-cvs1:/tmp/cvs-serv13337 Modified Files: build.xml Log Message: some reformatting in the dist target. Can we agree on using 4 spaces for tabulations and _not_ tabs as they are different for everyone and makes the code unreadable. Also I would prefer to use the nested elements form instead of attributes as this is now the preferred method in Ant and allows for more flexibility (wildcards, ...) but this is really not that important ... :) Index: build.xml =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/build.xml,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** build.xml 2001/08/12 23:01:45 1.9 --- build.xml 2001/08/13 06:59:52 1.10 *************** *** 560,565 **** </zipfileset> <zipfileset dir="${out.doc.dir}" prefix="doc"/> ! <zipfileset dir="${out.dir}" prefix="src" ! includes="${src.name}.zip" /> </zip> --- 560,566 ---- </zipfileset> <zipfileset dir="${out.doc.dir}" prefix="doc"/> ! <zipfileset dir="${out.dir}" prefix="src"> ! <include name="${src.name}.zip"/> ! </zipfileset> </zip> |
From: Vincent M. <vm...@oc...> - 2001-08-13 06:59:23
|
----- Original Message ----- From: "Steve Freeman" <st...@m3...> To: <moc...@li...> Sent: Sunday, August 12, 2001 11:17 PM Subject: [Mockobjects-java-dev] ant targets? > At work, I've adopted a convention of making internal targets CamelCase and external targets lower case, it seems to read quite well. I would have preferred something like "_my_internal_target" for internal targets and "my_external_target" for external ones, or prefix internal targets with a word like "internal" (for example "my_target" would give "internal_my_target"). I think the latter is the ones that would read the best. I've just reread the build.xml and noticed that I have used another convention, which is, for any xxx target, to prepare all environment setup (directory creation, copies of files, ...) in a "prepare-xxx" target. Also, I tend to prefer to write "my.target" rather than "my-target" or "my_target". We could homogeneize on this pattern if you like it. So with the proposition above, that would give "_my..target" or "internal.my.target" However if you strongly prefer CamelCase, that's fine. Coding conventions are always hard to decide .... :) > > What do you think? > > steve -Vincent |
From: Steve F. <sm...@us...> - 2001-08-12 23:01:48
|
Update of /cvsroot/mockobjects/mockobjects-java In directory usw-pr-cvs1:/tmp/cvs-serv29803 Modified Files: build.xml Log Message: distribution now includes a zip of the sources Index: build.xml =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/build.xml,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** build.xml 2001/08/10 15:46:17 1.8 --- build.xml 2001/08/12 23:01:45 1.9 *************** *** 1,8 **** <?xml version="1.0"?> ! <!-- ============================================================================= Build file for the mockobjects project. ! The following properties need to be set in a ./build.properties or or ${user.home}/build.properties file : --- 1,8 ---- <?xml version="1.0"?> ! <!-- ============================================================================= Build file for the mockobjects project. ! The following properties need to be set in a ./build.properties or or ${user.home}/build.properties file : *************** *** 22,26 **** in your Ant installation for running the unit tests and the documentation and web site generation. ! This script should be started with the following command line : --- 22,26 ---- in your Ant installation for running the unit tests and the documentation and web site generation. ! This script should be started with the following command line : *************** *** 28,36 **** Run "ant -projecthelp" to get a list of available targets. ! ============================================================================= --> <project name="mockobjects" default="jar" basedir="."> ! <!-- Give user a chance to override without editing this file (and without typing -D each time it compiles it) --> <property file="build.properties" /> --- 28,36 ---- Run "ant -projecthelp" to get a list of available targets. ! ============================================================================= --> <project name="mockobjects" default="jar" basedir="."> ! <!-- Give user a chance to override without editing this file (and without typing -D each time it compiles it) --> <property file="build.properties" /> *************** *** 49,53 **** <property name="package.prefix" value="com/mockobjects/"/> ! <!-- ======================================================================== Set the properties related to the source tree --- 49,53 ---- <property name="package.prefix" value="com/mockobjects/"/> ! <!-- ======================================================================== Set the properties related to the source tree *************** *** 65,69 **** <property name="lib.dir" value="lib"/> ! <!-- ======================================================================== Set the properties related to the build area --- 65,69 ---- <property name="lib.dir" value="lib"/> ! <!-- ======================================================================== Set the properties related to the build area *************** *** 85,89 **** <property name="out.xdoc.site.dir" value="${out.dir}/xdoc/site"/> ! <!-- ======================================================================== Default values for properties not defined in build.properties --- 85,89 ---- <property name="out.xdoc.site.dir" value="${out.dir}/xdoc/site"/> ! <!-- ======================================================================== Default values for properties not defined in build.properties *************** *** 92,96 **** <property name="dist.dir" value="dist"/> ! <!-- ======================================================================== Short names of deliverables --- 92,96 ---- <property name="dist.dir" value="dist"/> ! <!-- ======================================================================== Short names of deliverables *************** *** 114,118 **** <property name="dist.name" value="${project.name}-${project.version}"/> ! <!-- ======================================================================== Useful file patterns for targets --- 114,118 ---- <property name="dist.name" value="${project.name}-${project.version}"/> ! <!-- ======================================================================== Useful file patterns for targets *************** *** 147,151 **** </patternset> ! <!-- ======================================================================== Check to see what libraries are available in order to decide what --- 147,151 ---- </patternset> ! <!-- ======================================================================== Check to see what libraries are available in order to decide what *************** *** 161,165 **** <target name="check.availabilities"> ! <available property="servlet.present" classname="javax.servlet.Servlet" classpathref="lib.classpath"/> --- 161,165 ---- <target name="check.availabilities"> ! <available property="servlet.present" classname="javax.servlet.Servlet" classpathref="lib.classpath"/> *************** *** 167,171 **** </target> ! <!-- ======================================================================== Initialize the build. Must be called by all targets --- 167,171 ---- </target> ! <!-- ======================================================================== Initialize the build. Must be called by all targets *************** *** 193,197 **** </target> ! <!-- ======================================================================== Prepare the output directory by copying the source files into it --- 193,197 ---- </target> ! <!-- ======================================================================== Prepare the output directory by copying the source files into it *************** *** 218,222 **** </target> ! <!-- ======================================================================== Compiles the source directory --- 218,222 ---- </target> ! <!-- ======================================================================== Compiles the source directory *************** *** 275,279 **** </target> ! <!-- ======================================================================== Create the runtime jar file --- 275,279 ---- </target> ! <!-- ======================================================================== Create the runtime jar file *************** *** 296,302 **** <!-- Generate the jar file --> <target name="jar" depends="prepare-jar" ! description="--> generate the framework runtime jar"> ! <jar jarfile="${out.dir}/${jar.name}.jar" manifest="${out.conf.dir}/manifest"> --- 296,302 ---- <!-- Generate the jar file --> <target name="jar" depends="prepare-jar" ! description="generate the framework runtime jar"> ! <jar jarfile="${out.dir}/${jar.name}.jar" manifest="${out.conf.dir}/manifest"> *************** *** 307,311 **** </target> ! <!-- ======================================================================== Generate the javadoc --- 307,311 ---- </target> ! <!-- ======================================================================== Generate the javadoc *************** *** 317,321 **** <mkdir dir="${out.javadoc.dir}"/> ! <uptodate property="javadoc.notrequired" targetfile="${out.javadoc.dir}/packages.html"> --- 317,321 ---- <mkdir dir="${out.javadoc.dir}"/> ! <uptodate property="javadoc.notrequired" targetfile="${out.javadoc.dir}/packages.html"> *************** *** 326,330 **** <!-- Generate the javadoc for the current Servlet API --> ! <target name="javadoc" depends="prepare-javadoc" unless="javadoc.notrequired"> --- 326,330 ---- <!-- Generate the javadoc for the current Servlet API --> ! <target name="javadoc" depends="prepare-javadoc" unless="javadoc.notrequired"> *************** *** 355,361 **** web site --> ! <tar tarfile="${out.dir}/${javadoc.name}.tar" basedir="${out.javadoc.dir}"/> ! <gzip zipfile="${out.dir}/${javadoc.name}.tar.gz" src="${out.dir}/${javadoc.name}.tar"/> <delete file="${out.dir}/${javadoc.name}.tar"/> --- 355,361 ---- web site --> ! <tar tarfile="${out.dir}/${javadoc.name}.tar" basedir="${out.javadoc.dir}"/> ! <gzip zipfile="${out.dir}/${javadoc.name}.tar.gz" src="${out.dir}/${javadoc.name}.tar"/> <delete file="${out.dir}/${javadoc.name}.tar"/> *************** *** 363,367 **** </target> ! <!-- ======================================================================== Generate the full documentation, i.e. web site + javadoc --- 363,367 ---- </target> ! <!-- ======================================================================== Generate the full documentation, i.e. web site + javadoc *************** *** 379,383 **** tofile="${out.xdoc.doc.dir}/book.xml" filtering="on"/> ! <!-- Copy all remaining files from ${xdoc.dir} to ${out.xdoc.doc.dir} --> <copy todir="${out.xdoc.doc.dir}" filtering="on"> --- 379,383 ---- tofile="${out.xdoc.doc.dir}/book.xml" filtering="on"/> ! <!-- Copy all remaining files from ${xdoc.dir} to ${out.xdoc.doc.dir} --> <copy todir="${out.xdoc.doc.dir}" filtering="on"> *************** *** 392,396 **** </copy> ! <uptodate property="stylebook.doc.notrequired" targetfile="${out.doc.dir}/index.html"> --- 392,396 ---- </copy> ! <uptodate property="stylebook.doc.notrequired" targetfile="${out.doc.dir}/index.html"> *************** *** 404,408 **** <target name="doc" depends="prepare-doc" unless="stylebook.doc.notrequired" ! description="--> generate the documentation"> <!-- Generate the documentation web site --> --- 404,408 ---- <target name="doc" depends="prepare-doc" unless="stylebook.doc.notrequired" ! description="generate the documentation"> <!-- Generate the documentation web site --> *************** *** 416,423 **** </stylebook> ! </target> ! <!-- ======================================================================== Generate the web site --- 416,423 ---- </stylebook> ! </target> ! <!-- ======================================================================== Generate the web site *************** *** 435,439 **** tofile="${out.xdoc.site.dir}/book.xml" filtering="on"/> ! <!-- Copy all remaining files from ${xdoc.dir} to ${out.xdoc.site.dir} --> <copy todir="${out.xdoc.site.dir}" filtering="on"> --- 435,439 ---- tofile="${out.xdoc.site.dir}/book.xml" filtering="on"/> ! <!-- Copy all remaining files from ${xdoc.dir} to ${out.xdoc.site.dir} --> <copy todir="${out.xdoc.site.dir}" filtering="on"> *************** *** 448,452 **** </copy> ! <uptodate property="stylebook.site.notrequired" targetfile="${out.site.dir}/index.html"> --- 448,452 ---- </copy> ! <uptodate property="stylebook.site.notrequired" targetfile="${out.site.dir}/index.html"> *************** *** 465,469 **** <target name="site" depends="prepare-site" unless="stylebook.site.notrequired" ! description="--> generate the web site"> <stylebook book="${out.xdoc.site.dir}/book.xml" --- 465,469 ---- <target name="site" depends="prepare-site" unless="stylebook.site.notrequired" ! description="generate the web site"> <stylebook book="${out.xdoc.site.dir}/book.xml" *************** *** 479,483 **** <!-- Create the gzipped web site --> <tar tarfile="${out.dir}/${site.name}.tar" basedir="${out.site.dir}"/> ! <gzip zipfile="${out.dir}/${site.name}.tar.gz" src="${out.dir}/${site.name}.tar"/> <delete file="${out.dir}/${site.name}.tar"/> --- 479,483 ---- <!-- Create the gzipped web site --> <tar tarfile="${out.dir}/${site.name}.tar" basedir="${out.site.dir}"/> ! <gzip zipfile="${out.dir}/${site.name}.tar.gz" src="${out.dir}/${site.name}.tar"/> <delete file="${out.dir}/${site.name}.tar"/> *************** *** 485,489 **** </target> ! <!-- ======================================================================== Run the unit tests --- 485,489 ---- </target> ! <!-- ======================================================================== Run the unit tests *************** *** 491,495 **** --> <target name="test" depends="compile" ! description="--> run the unit tests"> <junit fork="yes" haltonfailure="yes"> --- 491,495 ---- --> <target name="test" depends="compile" ! description="run the unit tests"> <junit fork="yes" haltonfailure="yes"> *************** *** 514,518 **** </target> ! <!-- ======================================================================== Remove all build generated files --- 514,518 ---- </target> ! <!-- ======================================================================== Remove all build generated files *************** *** 520,524 **** --> <target name="clean" depends="init" ! description="--> clean up all generated files"> <delete> --- 520,524 ---- --> <target name="clean" depends="init" ! description="clean up all generated files"> <delete> *************** *** 538,542 **** </target> ! <!-- ======================================================================== Create the distributables --- 538,542 ---- </target> ! <!-- ======================================================================== Create the distributables *************** *** 544,554 **** --> <target name="prepare-dist" depends="jar,doc"> - <mkdir dir="${dist.dir}"/> </target> ! <target name="dist" depends="prepare-dist" ! description="--> generate the distributables"> <zip zipfile="${dist.dir}/${dist.name}.zip"> --- 544,557 ---- --> <target name="prepare-dist" depends="jar,doc"> <mkdir dir="${dist.dir}"/> + </target> + <target name="ZipJavaSources" depends="prepare"> + <zip zipfile="${out.dir}/${src.name}.zip" + basedir="${out.src.dir}" /> </target> ! <target name="dist" depends="prepare-dist, ZipJavaSources" ! description="generate the distributables"> <zip zipfile="${dist.dir}/${dist.name}.zip"> *************** *** 557,565 **** </zipfileset> <zipfileset dir="${out.doc.dir}" prefix="doc"/> </zip> </target> ! <!-- ======================================================================== Do it all --- 560,570 ---- </zipfileset> <zipfileset dir="${out.doc.dir}" prefix="doc"/> + <zipfileset dir="${out.dir}" prefix="src" + includes="${src.name}.zip" /> </zip> </target> ! <!-- ======================================================================== Do it all *************** *** 567,574 **** --> <target name="all" depends="clean,jar,doc,test,site,dist" ! description="--> do it all (clean, jar, doc, test, site)"> </target> ! <!-- ======================================================================== Deploy the web site to SourceForge, using the 'scp' --- 572,579 ---- --> <target name="all" depends="clean,jar,doc,test,site,dist" ! description="do it all (clean, jar, doc, test, site)"> </target> ! <!-- ======================================================================== Deploy the web site to SourceForge, using the 'scp' *************** *** 576,585 **** when calling this target and represent your username on SourceForge. ! Ex: ant -Dusername=vmassol deploy-site ======================================================================== --> <target name="deploy-site" depends="clean,site" if="username" ! description="--> deploy the web site to SourceForge (see target for details)"> <property name="deploy.homepage" value="/home/groups/m/mo/mockobjects/htdocs"/> --- 581,590 ---- when calling this target and represent your username on SourceForge. ! Ex: ant -Dusername=vmassol deploy-site ======================================================================== --> <target name="deploy-site" depends="clean,site" if="username" ! description="deploy the web site to SourceForge (see target for details)"> <property name="deploy.homepage" value="/home/groups/m/mo/mockobjects/htdocs"/> |
From: Steve F. <st...@m3...> - 2001-08-12 22:16:57
|
QXQgd29yaywgSSd2ZSBhZG9wdGVkIGEgY29udmVudGlvbiBvZiBtYWtpbmcgaW50ZXJuYWwgdGFy Z2V0cyBDYW1lbENhc2UgYW5kIGV4dGVybmFsIHRhcmdldHMgbG93ZXIgY2FzZSwgaXQgc2VlbXMg dG8gcmVhZCBxdWl0ZSB3ZWxsLiANCg0KV2hhdCBkbyB5b3UgdGhpbms/DQoNCnN0ZXZlDQoNCg== |
From: Vincent M. <vm...@oc...> - 2001-08-12 15:54:28
|
----- Original Message ----- From: "Steve Freeman" <st...@m3...> To: <moc...@li...> Sent: Sunday, August 12, 2001 4:27 PM Subject: Re: [Mockobjects-java-dev] Mock Objects white paper PDF location ? > > Question: Where is the official URL for the "Endo-Testing" white paper PDF ? > > It should be in a documentation section of the mockobjects paper. I should port it again to the doc book format. What is the problem with the current page (endotesting.html) on the web site ? As I said we could add a link there to the PDF version. I am not sure what you mean about DocBook .... DocBook is simply a DTD, the result is done through XSL. So you could change all the web site to use the DocBook DTD but still have the same look and feel. What do you want to change : - the XML DTD for writing the web site pages ? - the web site look and feel ? > > > However, to do this we still need to have www.mockobjects.com to _really_ > > point to http://mockobjects.sourceforge.net (in the DNS sense). Currently > > this is _not_ what is in place : there is a page (hosted somewhere, probably > > on one of the server from the company where the domain name was purchased) > > that does a redirect. This is probably not what we want, because it means we > > cannot type something like http://www.mockobjects.com/endotesting.html ... > > (or http://www.mockobjects.com/mockobjects.pdf)... Steve, can you handle > > this issue if you agree ? Thanks. > > the forwarding uk2 provides will support subdirectories. I can add some if you like. Alternatively, I can change the DNS entry to point somewhere else if we have a suitable host. > yes: http://mockobjects.sourceforge.net ! -Vincent |
From: Steve F. <st...@m3...> - 2001-08-12 15:43:18
|
SSBzZWVtIHRvIHJlbWVtYmVyIFRpbSBnZXR0aW5nIHVwc2V0IGFib3V0IHRoaXMgb25lLiBUaGUg c3R1YmJpbmcgaXMgaW50ZXJlc3RpbmcsIGJ1dCB0aGV5J3ZlIG1pc3NlZCB0aGUgcG9pbnQgb24g dGhlIGlzc3VlIG9mIGZvbGRpbmcgaW4gdGhlIGV4cGVjdGF0aW9ucy4gQWxzbywgdGhleSBhcHBl YXIgdG8gaGF2ZSBtaXNyZWFkIG91ciBvcmlnaW5hbCBwYXBlci4gVGhlcmUncyBjbGVhcmx5IGEg bmVlZCBmb3IgZ2VuZXJhdGlvbiBiYXNlZCBvbiByZWZsZWN0aW9uIC0tIGFsdGhvdWdoIEkgZG9u J3QgdGhpbmsgdGhhdCBKMk1FIHN1cHBvcnRzIGl0IC0tIGJ1dCB0aGluZ3MgYXJlIGdldHRpbmcg c3BsaW50ZXJlZC4NCg0KU3RldmUNCg0KLS0tLS0gT3JpZ2luYWwgTWVzc2FnZSAtLS0tLSANCkZy b206ICJWaW5jZW50IE1hc3NvbCIgPHZtYXNzb2xAb2N0by5jb20+DQpUbzogPG1vY2tvYmplY3Rz LWphdmEtZGV2QGxpc3RzLnNvdXJjZWZvcmdlLm5ldD4NClNlbnQ6IFN1bmRheSwgQXVndXN0IDEy LCAyMDAxIDM6NTEgUE0NClN1YmplY3Q6IFtNb2Nrb2JqZWN0cy1qYXZhLWRldl0gQXV0b21hdGlj YWxseSBHZW5lcmF0aW5nIFN5c3RlbSBNb2NrIE9iamVjdHMNCg0KDQo+IEhlcmUgaXMgYSBwYXBl ciBwcmVzZW50ZWQgYXQgWFBVbml2ZXJzIG9uIHRoZSBzdWJqZWN0OiAiQXV0b21hdGljYWxseQ0K PiBHZW5lcmF0aW5nIFN5c3RlbSBNb2NrIE9iamVjdHMiDQo+IFVSTDogaHR0cDovL3d3dy54cHVu aXZlcnNlLmNvbS9UZXN0aW5nMDQucGRmDQoNCg== |
From: Steve F. <st...@m3...> - 2001-08-12 15:43:18
|
PiBRdWVzdGlvbjogV2hlcmUgaXMgdGhlIG9mZmljaWFsIFVSTCBmb3IgdGhlICJFbmRvLVRlc3Rp bmciIHdoaXRlIHBhcGVyIFBERiA/DQoNCkl0IHNob3VsZCBiZSBpbiBhIGRvY3VtZW50YXRpb24g c2VjdGlvbiBvZiB0aGUgbW9ja29iamVjdHMgcGFwZXIuIEkgc2hvdWxkIHBvcnQgaXQgYWdhaW4g dG8gdGhlIGRvYyBib29rIGZvcm1hdC4NCg0KPiBIb3dldmVyLCB0byBkbyB0aGlzIHdlIHN0aWxs IG5lZWQgdG8gaGF2ZSB3d3cubW9ja29iamVjdHMuY29tIHRvIF9yZWFsbHlfDQo+IHBvaW50IHRv IGh0dHA6Ly9tb2Nrb2JqZWN0cy5zb3VyY2Vmb3JnZS5uZXQgKGluIHRoZSBETlMgc2Vuc2UpLiBD dXJyZW50bHkNCj4gdGhpcyBpcyBfbm90XyB3aGF0IGlzIGluIHBsYWNlIDogdGhlcmUgaXMgYSBw YWdlIChob3N0ZWQgc29tZXdoZXJlLCBwcm9iYWJseQ0KPiBvbiBvbmUgb2YgdGhlIHNlcnZlciBm cm9tIHRoZSBjb21wYW55IHdoZXJlIHRoZSBkb21haW4gbmFtZSB3YXMgcHVyY2hhc2VkKQ0KPiB0 aGF0IGRvZXMgYSByZWRpcmVjdC4gVGhpcyBpcyBwcm9iYWJseSBub3Qgd2hhdCB3ZSB3YW50LCBi ZWNhdXNlIGl0IG1lYW5zIHdlDQo+IGNhbm5vdCB0eXBlIHNvbWV0aGluZyBsaWtlIGh0dHA6Ly93 d3cubW9ja29iamVjdHMuY29tL2VuZG90ZXN0aW5nLmh0bWwgLi4uDQo+IChvciBodHRwOi8vd3d3 Lm1vY2tvYmplY3RzLmNvbS9tb2Nrb2JqZWN0cy5wZGYpLi4uIFN0ZXZlLCBjYW4geW91IGhhbmRs ZQ0KPiB0aGlzIGlzc3VlIGlmIHlvdSBhZ3JlZSA/IFRoYW5rcy4NCg0KdGhlIGZvcndhcmRpbmcg dWsyIHByb3ZpZGVzIHdpbGwgc3VwcG9ydCBzdWJkaXJlY3Rvcmllcy4gSSBjYW4gYWRkIHNvbWUg aWYgeW91IGxpa2UuIEFsdGVybmF0aXZlbHksIEkgY2FuIGNoYW5nZSB0aGUgRE5TIGVudHJ5IHRv IHBvaW50IHNvbWV3aGVyZSBlbHNlIGlmIHdlIGhhdmUgYSBzdWl0YWJsZSBob3N0Lg0KDQo+IFAu Uy46IEkgaGF2ZSBhc2tlZCBFcmlrIE1lYWRlIChmcm9tIGp1bml0Lm9yZykgdG8gbW9kaWZ5IHRo ZSBVUkwgZm9yIHRoZQ0KPiBtb2Nrb2JqZWN0cyBwcm9qZWN0IHRoYXQgaXMgbGlua2VkIGluIHRo ZSBleHRlbnNpb24gc2VjdGlvbiB0bw0KPiBodHRwOi8vd3d3Lm1vY2tvYmplY3RzLmNvbSBhbmQg dG8gY2hhbmdlIHRoZSBkZXNjcmlwdGlvbiBmcm9tICJNb2NrIG9iamVjdHMNCj4gdG8gaGVscCB5 b3UgdGVzdC4iIHRvICJUaGUgTW9jayBPYmplY3RzIHByb2plY3QgaXMgYSBnZW5lcmljIHVuaXQg dGVzdGluZw0KPiBmcmFtZXdvcmsgd2hvc2UgZ29hbCBpcyB0byBmYWNpbGl0YXRlIGRldmVsb3Bp bmcgdW5pdCB0ZXN0cyBpbiB0aGUgbW9jaw0KPiBvYmplY3Qgc3R5bGUiLiBIb3BlIHRoaXMgaXMg ZmluZS4NCg0KZ29vZC4NCg0KDQo= |
From: Vincent M. <vm...@oc...> - 2001-08-12 15:17:30
|
Hi, Question: Where is the official URL for the "Endo-Testing" white paper PDF ? My ideas : * We put it on http://www.mockobjects.com/mockobjects.pdf (instead of http://www.sidewize.com/company/mockobjects.pdf), so that we regroup everything that has to do with mockobjects on www.mockobjects.com * We put a link to it in http://www.mockobjects.com/endotesting.html (the HTML version), something like "You can also download the original PDF version" ... * We modify the link on junit.org to point to the new location (and anywhere else where it was posted to). However, to do this we still need to have www.mockobjects.com to _really_ point to http://mockobjects.sourceforge.net (in the DNS sense). Currently this is _not_ what is in place : there is a page (hosted somewhere, probably on one of the server from the company where the domain name was purchased) that does a redirect. This is probably not what we want, because it means we cannot type something like http://www.mockobjects.com/endotesting.html ... (or http://www.mockobjects.com/mockobjects.pdf)... Steve, can you handle this issue if you agree ? Thanks. Comments ? Do you like this idea ? Thanks -Vincent P.S.: I have asked Erik Meade (from junit.org) to modify the URL for the mockobjects project that is linked in the extension section to http://www.mockobjects.com and to change the description from "Mock objects to help you test." to "The Mock Objects project is a generic unit testing framework whose goal is to facilitate developing unit tests in the mock object style". Hope this is fine. |
From: Vincent M. <vm...@oc...> - 2001-08-12 14:49:17
|
Here is a paper presented at XPUnivers on the subject: "Automatically Generating System Mock Objects" URL: http://www.xpuniverse.com/Testing04.pdf Here is the abstract: ABSTRACT In test before code environments [1], writing many quick and efficient unit tests helps projects execute quickly. As the software product under test becomes increasingly complex, it becomes harder to write unit tests to test one particular software object without interacting with the entire system (systemic testing). [5] proposes the MockObject pattern [2, 6] as a technique to replace a real object with a fake test object during testing. We propose a variation, which focuses on the following two goals: (a) Replace external systems for which the unit test developer has no control with mock systems. (b) Generate as much of the mock implementation automatically using Java's reflection Application Interface (API). I have not read it yet. Will do soon though ... -Vincent |
From: Steve F. <st...@m3...> - 2001-08-12 11:49:20
|
SW50ZXJlc3RpbmcuIFRoaXMgaXMganVzdCB3aGF0IHlvdSBhbmQgSSB0YWxrZWQgYWJvdXQsIGFu ZCBpcyBhbHNvIHN1aXRhYmxlIGZvciBtb2NraW5nIHVwIGNsYXNzZXMgcmF0aGVyIHRoYW4ganVz dCBpbnRlcmZhY2VzLg0KDQpMZXQncyBpbnZlc3RpZ2F0ZSBmdXJ0aGVyLg0KDQpTdGV2ZQ0KDQoN Ci0tLS0tIE9yaWdpbmFsIE1lc3NhZ2UgLS0tLS0gDQpGcm9tOiAiVmluY2VudCBNYXNzb2wiIDx2 bWFzc29sQG9jdG8uY29tPg0KVG86IDxtb2Nrb2JqZWN0cy1qYXZhLWRldkBsaXN0cy5zb3VyY2Vm b3JnZS5uZXQ+DQpTZW50OiBTdW5kYXksIEF1Z3VzdCAxMiwgMjAwMSAxMDoyNCBBTQ0KU3ViamVj dDogW01vY2tvYmplY3RzLWphdmEtZGV2XSBBIHNvbHV0aW9uIGZvciBydW50aW1lIGdlbmVyYXRp b24gb2YgbW9jayBvYmplY3RzIHdpdGggSkRLIDwgMS4zDQoNCg0KPiBXaXRoIEpESyAxLjMgd2Ug Y2FuIHVzZSBkeW5hbWljIHByb3h5IChhcyBpbiBlYXN5IG1vY2spIGZvciBhdXRvbWF0aWNhbGx5 DQo+IGdlbmVyYXRpbmcgdGhlIG1vY2sgb2JqZWN0cy4NCj4gDQo+IEhvd2V2ZXIgaXQgZG9lcyBu b3Qgd29yayB3aXRoIEpESyAxLjEgYW5kIDEuMi4gSSBoYXZlIGZvdW5kIHRoaXMgaW50ZXJlc3Rp bmcNCj4gZnJhbWV3b3JrIChjYWxsZWQgaG90c3dhcCkgdGhhdCB3aWxsIGxldCB5b3UgZG8gaG90 IHN3YXBwaW5nIGF0IHJ1bnRpbWUuIEl0DQo+IHdvdWxkIHdvcmsgZm9yIG91ciBwcm9ibGVtIEJV VCBpdCBzZWVtcyBpdCBvbmx5IHdvcmtzIHdpdGggSkRLIDEuMiAuLi4gVGhlcmUNCj4gaXMgbm8g bWVudGlvbiBpbiB0aGUgZG9jIG9mIEpESyAxLjEgLi4uDQo+IA0KPiBTdGlsbCBJIGZvdW5kIHRo ZSBhcnRpY2xlIGludGVyZXN0aW5nIGFuZCB3YW50ZWQgdG8gbGV0IHlvdSBrbm93IDoNCj4gaHR0 cDovL3d3dy5pbnhhci5vcmcvaG90c3dhcC9pbnhhci9ob3Rzd2FwLTBfOF82L2RvY3MvbWFudWFs L21hbnVhbC5odG1sDQo+IA0KPiBUaGFua3MNCj4gLVZpbmNlbnQNCj4gDQo+IA0KPiBfX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KPiBNb2Nrb2JqZWN0cy1q YXZhLWRldiBtYWlsaW5nIGxpc3QNCj4gTW9ja29iamVjdHMtamF2YS1kZXZAbGlzdHMuc291cmNl Zm9yZ2UubmV0DQo+IGh0dHA6Ly9saXN0cy5zb3VyY2Vmb3JnZS5uZXQvbGlzdHMvbGlzdGluZm8v bW9ja29iamVjdHMtamF2YS1kZXYNCj4gDQo= |
From: Vincent M. <vm...@oc...> - 2001-08-12 09:21:39
|
With JDK 1.3 we can use dynamic proxy (as in easy mock) for automatically generating the mock objects. However it does not work with JDK 1.1 and 1.2. I have found this interesting framework (called hotswap) that will let you do hot swapping at runtime. It would work for our problem BUT it seems it only works with JDK 1.2 ... There is no mention in the doc of JDK 1.1 ... Still I found the article interesting and wanted to let you know : http://www.inxar.org/hotswap/inxar/hotswap-0_8_6/docs/manual/manual.html Thanks -Vincent |
From: Steve F. <sm...@us...> - 2001-08-11 23:51:19
|
Update of /cvsroot/mockobjects/doc In directory usw-pr-cvs1:/tmp/cvs-serv12398 Modified Files: jdbc_testfirst.html Log Message: Added Introduction and Send Message To Members Index: jdbc_testfirst.html =================================================================== RCS file: /cvsroot/mockobjects/doc/jdbc_testfirst.html,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** jdbc_testfirst.html 2001/08/11 20:45:33 1.8 --- jdbc_testfirst.html 2001/08/11 23:51:16 1.9 *************** *** 18,25 **** <p align="center">Steve Freeman <tt> st...@m3...</tt></p> <h2>Introduction</h2> ! <p>Our customers have commissioned us to write a mailing list system. Anyone can ! add and remove themselves from the list, but only the list owner can see the ! whole list and send messages to it. If we start by assuming that there's just ! one list, we have the following tasks:</p> <ul> <li>anyone can add their name and email address to the list;</li> --- 18,34 ---- <p align="center">Steve Freeman <tt> st...@m3...</tt></p> <h2>Introduction</h2> ! <p>Many developers find unit testing third-party components such as databases ! tricky to do. Usually the difficulties are because setting up the component ! to ensure no dependencies between unit tests is too complicated or slow. This ! paper uses JDBC, the Java database interface, to show how it is possible to ! avoid using a real database at all. 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> ! <h3>The stories</h3> ! <p>To help structure the examples, let's imagine that our customers have commissioned ! us to write a mailing list system. Anyone can add and remove themselves from ! the list, but only the list owner can see the whole list and send messages to ! it. If we start by assuming that there's just one list, we have the following ! tasks:</p> <ul> <li>anyone can add their name and email address to the list;</li> *************** *** 30,36 **** </ul> <h2>Add a member to the list</h2> ! <p>We assume that access control is managed by the surrounding system and start ! to develop a MailingList class to manage the list. For a succesful insertion, ! we would expect the certain things to happen:</p> <ul> <li>create a statement object with the appropriate insertion statement</li> --- 39,45 ---- </ul> <h2>Add a member to the list</h2> ! <p>We assume that access is controlled by the surrounding system and start to ! develop a <span class="inline_code">MailingList</span> class to manage the list. ! For a succesful insertion, we would expect the certain things to happen:</p> <ul> <li>create a statement object with the appropriate insertion statement</li> *************** *** 85,94 **** <pre> public class MailingList { public void addMember(Connection connection, String emailAddress, String name) throws SQLException { ! PreparedStatement statement = connection.prepareStatement(INSERT_SQL); ! statement.setString(1, emailAddress); ! statement.setString(2, name); ! ! statement.execute(); ! statement.close(); } }</pre> --- 94,102 ---- <pre> public class MailingList { public void addMember(Connection connection, String emailAddress, String name) throws SQLException { ! PreparedStatement statement = connection.prepareStatement(INSERT_SQL); ! statement.setString(1, emailAddress); ! statement.setString(2, name); ! statement.execute(); ! statement.close(); } }</pre> *************** *** 206,211 **** </p> <h2>Remove a member from the list</h2> ! <p>The next task is to remove someone from the list, based on their email address; ! the test for a succesful removal is:</p> <pre> public void testRemoveMember() throws MailingListException, SQLException { mockStatement.setupUpdateCount(1); --- 214,219 ---- </p> <h2>Remove a member from the list</h2> ! <p>The next task is to remove someone from the list, based on their email address. ! The test for a succesful removal is:</p> <pre> public void testRemoveMember() throws MailingListException, SQLException { mockStatement.setupUpdateCount(1); *************** *** 247,251 **** both these tests is:</p> <pre> public void removeMember(Connection connection, String emailAddress) ! throws MailingListException , SQLException<br> { PreparedStatement statement = connection.prepareStatement(DELETE_SQL); try { --- 255,259 ---- both these tests is:</p> <pre> public void removeMember(Connection connection, String emailAddress) ! throws MailingListException, SQLException<br> { PreparedStatement statement = connection.prepareStatement(DELETE_SQL); try { *************** *** 261,265 **** <p>At this point we should start to notice repetition in the unit tests. In particular, each action on the member list requires a particular setup for the mock sql ! objects, and we always verify the same two objects. We factor these into some helper methods:</p> <pre> private void setExpectationsForAddMember() { --- 269,273 ---- <p>At this point we should start to notice repetition in the unit tests. In particular, each action on the member list requires a particular setup for the mock sql ! objects, and we always verify the same two objects. We refactor these into some helper methods:</p> <pre> private void setExpectationsForAddMember() { *************** *** 309,313 **** altering what we already have; the next stage is to refactor the tests to remove duplication. Maintaining and refactoring tests turns out to be as important ! as maintaining the code they exercise; the tests must be agile enough to follow the code as it is grows and changes. </p> <p>That said, we must maintain a balance here and not refactor the tests until --- 317,321 ---- altering what we already have; the next stage is to refactor the tests to remove duplication. Maintaining and refactoring tests turns out to be as important ! as maintaining the code they exercise. The tests must be agile enough to follow the code as it is grows and changes. </p> <p>That said, we must maintain a balance here and not refactor the tests until *************** *** 362,368 **** Statement statement = connection.createStatement(); ResultSet results = statement.executeQuery(LIST_SQL); ! while (results.next()) { listMembers.member(results.getString("email_address"), results.getString("name")); ! } statement.close(); }</pre> --- 370,376 ---- Statement statement = connection.createStatement(); ResultSet results = statement.executeQuery(LIST_SQL); ! while (results.next()) { listMembers.member(results.getString("email_address"), results.getString("name")); ! } statement.close(); }</pre> *************** *** 376,381 **** object, we do not need to check again that the right values have been received. This makes tests more precise and orthogonal, and so easier to understand when ! they fail, which makes test cases and mock objects easier to write because each ! one does less.</p> <p>For example, the test for listing two members does not set any expectations for the list member name and email address. This version does set column names --- 384,389 ---- object, we do not need to check again that the right values have been received. This makes tests more precise and orthogonal, and so easier to understand when ! they fail. It also makes test cases and mock objects easier to write because ! each one does less.</p> <p>For example, the test for listing two members does not set any expectations for the list member name and email address. This version does set column names *************** *** 447,450 **** --- 455,463 ---- }</span> </pre> + <p>One significant point about this test is that it clearly defines the behaviour + of <span class="inline_code">applyToAllMembers</span> in the presence of failures. + We do not, for example, try to carry on should a record fail. Developing test-first + and publishing the tests gives users of the code a much clearer description + of how to use it than most conventional documentation.</p> <p>Our implementation will not pass this test because it has no <span class="inline_code">finally</span> clause, so we add it now.</p> *************** *** 468,472 **** <p>We can now ask a <span class="inline_code">MailingList</span> object to process all the members of the list by passing an object of type <span class="inline_code">ListMembers</span>. ! In a servlet, we might present the results by implementing an <span class="inline_code">MembersAsTableRow</span> class that writes out each member as a row in an HTML table; the <span class="inline_code">PrintWriter</span> would be passed through from the request's <span class="inline_code">ServletResponse</span>.</p> --- 481,485 ---- <p>We can now ask a <span class="inline_code">MailingList</span> object to process all the members of the list by passing an object of type <span class="inline_code">ListMembers</span>. ! In a servlet, we might present the results by implementing a <span class="inline_code">MembersAsTableRow</span> class that writes out each member as a row in an HTML table; the <span class="inline_code">PrintWriter</span> would be passed through from the request's <span class="inline_code">ServletResponse</span>.</p> *************** *** 475,479 **** writer = aPrintWriter; } ! public member(String email, String name) { writer.print("<TR><TD>"); writer.print(email); --- 488,492 ---- writer = aPrintWriter; } ! public void member(String email, String name) { writer.print("<TR><TD>"); writer.print(email); *************** *** 483,488 **** } }</pre> ! Of course this new class should have its own set of unit tests.<br> ! <h3>What have we learned</h3> <p>A common difficulty when testing networks of objects is the cost of setting up the test environment. These techniques show that we can manage this by being --- 496,501 ---- } }</pre> ! <p>Of course this new class should have its own set of unit tests. </p> ! <h3>What have we learned?</h3> <p>A common difficulty when testing networks of objects is the cost of setting up the test environment. These techniques show that we can manage this by being *************** *** 506,509 **** --- 519,586 ---- <li>we can force unusual conditions such as SQL exceptions.</li> </ul> + <h2>Send a message to all the members</h2> + <p>Our final requirement is to send a message to all the members of the list. + We can do this by providing another implementation of the <span class="inline_code">ListMembers</span> + interface, in this case a <span class="inline_code">AddMembersToMessage</span> + class. We have to make a design choice here about how to handle any messaging + exceptions: we can either stop immediately, or collect the failures and process + them at the end; for now, we shall stop processing immediately. The <span class="inline_code">Message</span> + object is set up by the calling code, which then sends it to all the recipients.</p> + <pre> + class AddMembersToMessage implements ListMembers { + Message message; + public AddMembersToMessage(Message aMessage) { + message = aMessage; + } + public void member(String email, String name) throws MailingListException { + try { + message.addRecipient(RecipientType.TO, + new InternetAddress(email, name)); + } catch (MessagingException ex) { + throw new MailingListException("Adding member to message", email, name, ex); + } + } + } + </pre> + <p>The <span class="inline_code">MessagingException</span> exception is checked, + so we have to handle it here or propagate it through the code. We want to keep + the <span class="inline_code">ListMembers</span> interface generic, so we translate + the <span class="inline_code">MessagingException</span> to a <span class="inline_code">MailingListException</span>, + and propagate that instead. Now we have a new failure mode, so we write an additional + unit test that ensures that we clean up properly after a <span class="inline_code">MailingListException</span>.</p> + <pre><span class="deemphasised"> public void testListmembersFailure() throws SQLException { + MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); + mockResultSet.setupRows(TWO_ROWS);</span> + mockListMembers.setupThrowExceptionOnMember(new MailingListException()); + + mockResultSet.setExpectedNextCalls(1); + <span class="deemphasised"> setExpectationsForListMembers(); + + try { + list.applyToAllMembers(mockConnection, mockListMembers); + fail("Should have thrown exception");</span> + } catch (MailingListException expected) { + <span class="deemphasised"> } + mockResultSet.verify(); + mockListMembers.verify(); + }</span> + </pre> + <h3>Tell, don't ask</h3> + <p>This approach to test-first development has led to a solution that may appear + needlessly complex, as against just returning a collection of members from the + <span class="inline_code">MailingList</span>. Our experience, however, is that + code written this way is much more flexible. For example, if we later decide + to ignore message errors and keep sending, we can do so by collecting them in + the <span class="inline_code">AddMembersToMessage</span> class and processing + them after the message has been sent. Similarly, if our mailing list becomes + very large, we can start to process recipients in small batches and do not have + to worry about creating excessive collections of list members. On the other + hand, if we do want to return a list of members, we can still write another + <span class="inline_code">ListMembers</span> implementation that adds each member + to a collection.</p> + <h2>Summary</h2> + <h3>Notes</h3> + All the code in these examples and the mock objects library are available for + download from <tt>http://www.mockobjects.com</tt><br> <hr> <p>© Steve Freeman, 2001</p> |
From: Steve F. <sm...@us...> - 2001-08-11 23:50:26
|
Update of /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist In directory usw-pr-cvs1:/tmp/cvs-serv12189 Modified Files: ListMembers.java MailingList.java MockListMembers.java TestMailingList.java Log Message: added MailingListException to ListMembers.member() Index: ListMembers.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist/ListMembers.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ListMembers.java 2001/08/05 23:46:33 1.1 --- ListMembers.java 2001/08/11 23:50:22 1.2 *************** *** 2,5 **** public interface ListMembers { ! public void member(String email, String name); } --- 2,5 ---- public interface ListMembers { ! public void member(String email, String name) throws MailingListException; } Index: MailingList.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist/MailingList.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** MailingList.java 2001/08/05 23:46:33 1.3 --- MailingList.java 2001/08/11 23:50:22 1.4 *************** *** 37,41 **** } ! public void applyToAllMembers(Connection connection, ListMembers listMembers) throws SQLException { Statement statement = connection.createStatement(); try { --- 37,41 ---- } ! public void applyToAllMembers(Connection connection, ListMembers listMembers) throws MailingListException, SQLException { Statement statement = connection.createStatement(); try { Index: MockListMembers.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist/MockListMembers.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** MockListMembers.java 2001/08/06 00:19:54 1.3 --- MockListMembers.java 2001/08/11 23:50:22 1.4 *************** *** 9,15 **** private ExpectationList members = new ExpectationList("MockListMembers.members"); private ExpectationCounter memberCount = new ExpectationCounter("MockListMembers.count"); ! public void member(String email, String name) { memberCount.inc(); members.addActual(constructEntry(email, name)); } --- 9,19 ---- private ExpectationList members = new ExpectationList("MockListMembers.members"); private ExpectationCounter memberCount = new ExpectationCounter("MockListMembers.count"); + private MailingListException memberException = null; ! public void member(String email, String name) throws MailingListException { memberCount.inc(); + if (null != memberException) { + throw memberException; + } members.addActual(constructEntry(email, name)); } *************** *** 26,29 **** --- 30,37 ---- memberCount.setExpectNothing(); members.setExpectNothing(); + } + + public void setupThrowExceptionOnMember(MailingListException exception) { + memberException = exception; } Index: TestMailingList.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist/TestMailingList.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** TestMailingList.java 2001/08/11 20:42:05 1.8 --- TestMailingList.java 2001/08/11 23:50:22 1.9 *************** *** 92,96 **** } ! public void testListNoMembers() throws SQLException { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); --- 92,96 ---- } ! public void testListNoMembers() throws MailingListException, SQLException { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); *************** *** 106,110 **** } ! public void testListOneMember() throws SQLException { MockSingleRowResultSet mockResultSet = new MockSingleRowResultSet(); mockStatement.setupResultSet(mockResultSet); --- 106,110 ---- } ! public void testListOneMember() throws MailingListException, SQLException { MockSingleRowResultSet mockResultSet = new MockSingleRowResultSet(); mockStatement.setupResultSet(mockResultSet); *************** *** 122,126 **** } ! public void testListTwoMembers() throws SQLException { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); mockResultSet.setupRows(TWO_ROWS); --- 122,126 ---- } ! public void testListTwoMembers() throws MailingListException, SQLException { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); mockResultSet.setupRows(TWO_ROWS); *************** *** 138,144 **** } ! public void testListResultSetFailure() { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); mockResultSet.setupRows(TWO_ROWS); mockResultSet.setupThrowExceptionOnGet(new SQLException("Mock Exception")); --- 138,161 ---- } ! public void testListmembersFailure() throws SQLException { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); mockResultSet.setupRows(TWO_ROWS); + mockListMembers.setupThrowExceptionOnMember(new MailingListException()); + + mockResultSet.setExpectedNextCalls(1); + setExpectationsForListMembers(); + + try { + list.applyToAllMembers(mockConnection, mockListMembers); + fail("Should have thrown exception"); + } catch (MailingListException expected) { + } + mockResultSet.verify(); + mockListMembers.verify(); + } + + public void testListResultSetFailure() throws MailingListException { + MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); + mockResultSet.setupRows(TWO_ROWS); mockResultSet.setupThrowExceptionOnGet(new SQLException("Mock Exception")); *************** *** 156,160 **** } ! public void testListStatementFailure() { mockStatement.setupThrowExceptionOnExecute(new SQLException("Mock exception")); mockListMembers.setExpectNoMembers(); --- 173,177 ---- } ! public void testListStatementFailure() throws MailingListException { mockStatement.setupThrowExceptionOnExecute(new SQLException("Mock exception")); mockListMembers.setExpectNoMembers(); *************** *** 169,173 **** } ! public void testListConnectionFailure() { mockConnection.setupThrowExceptionOnPrepareOrCreate(new SQLException("Mock Exception")); --- 186,190 ---- } ! public void testListConnectionFailure() throws MailingListException { mockConnection.setupThrowExceptionOnPrepareOrCreate(new SQLException("Mock Exception")); |
From: Steve F. <sm...@us...> - 2001-08-11 20:45:36
|
Update of /cvsroot/mockobjects/doc In directory usw-pr-cvs1:/tmp/cvs-serv2460 Modified Files: jdbc_testfirst.html Log Message: more Index: jdbc_testfirst.html =================================================================== RCS file: /cvsroot/mockobjects/doc/jdbc_testfirst.html,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** jdbc_testfirst.html 2001/08/09 22:06:49 1.7 --- jdbc_testfirst.html 2001/08/11 20:45:33 1.8 *************** *** 112,117 **** <p>What happens if someone tries to add an email address twice? After further discussion, our customers decide that we should not accept the change and show ! an error message. We decide to throw a <span class="inline_code">MailingListException</span> ! when this happens. First we write a test:</p> <pre> public void testAddExistingMember() throws SQLException { mockStatement.setupThrowExceptionOnExecute( --- 112,118 ---- <p>What happens if someone tries to add an email address twice? After further discussion, our customers decide that we should not accept the change and show ! an error message; we decide to throw a <span class="inline_code">MailingListException</span> ! when this happens. We can write a test to verify that such an exception is thrown ! if there is a duplicate record.</p> <pre> public void testAddExistingMember() throws SQLException { mockStatement.setupThrowExceptionOnExecute( *************** *** 119,126 **** DatabaseConstants.UNIQUE_CONSTRAINT_VIOLATED)); ! mockConnection.setExpectedPrepareStatementString(MailingList.INSERTION_SQL); mockStatement.addExpectedSetParameters(new Object[] {EMAIL, NAME}); mockStatement.setExpectedExecuteCalls(1); ! mockStatement.setExpectedCloseCalls(1); try { --- 120,127 ---- DatabaseConstants.UNIQUE_CONSTRAINT_VIOLATED)); ! <span class="deemphasised"> mockConnection.setExpectedPrepareStatementString(MailingList.INSERTION_SQL); mockStatement.addExpectedSetParameters(new Object[] {EMAIL, NAME}); mockStatement.setExpectedExecuteCalls(1); ! mockStatement.setExpectedCloseCalls(1);</span> try { *************** *** 130,146 **** } ! mockStatement.verify(); mockConnection.verify(); ! } </pre> ! <p>We still want to check that we pass the right parameters through to the database, ! but this time we want to emulate the effect of writing a duplicate record. The ! call <span class="inline_code">setupThrowExceptionOnExecute</span> stores an ! exception that will be thrown when we try to execute the statement; note that ! we still need to ensure that <span class="inline_code">execute</span> and <span class="inline_code">close</span> are each called once. Our test ensures that this exception is caught and translated into a <span class="inline_code">MailingListException</span>. If this doesn't happen, then the code will step through from <span class="inline_code">addMember</span> ! to the <span class="inline_code">fail</span> call and throw an assertion error.</p> <p>To pass this test, we change the implementation to:</p> <pre><span class="deemphasised"> public class MailingList { --- 131,149 ---- } ! <span class="deemphasised"> mockStatement.verify(); mockConnection.verify(); ! }</span> </pre> ! <p>The method <span class="inline_code">setupThrowExceptionOnExecute</span> stores ! an exception that the mock SQL statement will throw when <span class="inline_code">execute()</span> ! is called. We can force such events because our coding style allows us to pass ! a mock implementation through to the code that uses the statement. We still ! check that the right parameters are passed through to the connection and statement, ! and that <span class="inline_code">execute</span> and <span class="inline_code">close</span> are each called once. Our test ensures that this exception is caught and translated into a <span class="inline_code">MailingListException</span>. If this doesn't happen, then the code will step through from <span class="inline_code">addMember</span> ! to the <span class="inline_code">fail</span> call and throw an assertion error. ! Even with the extra complexity, the test is still precise and self-explanatory.</p> <p>To pass this test, we change the implementation to:</p> <pre><span class="deemphasised"> public class MailingList { *************** *** 164,170 **** <span class="deemphasised"> } }</span></pre> ! <p>At this point we add a <span class="inline_code">finally</span> block to make ! sure that the statement will always be closed, even if there are failures when ! using it. Interestingly, the code also passes this test:</p> <pre><span class="deemphasised"> public void testPrepareStatementFailsForAdd() throws MailingListException, SQLException {</span> mockConnection.setupThrowExceptionOnPrepare(new SQLException("MockConnection")); --- 167,173 ---- <span class="deemphasised"> } }</span></pre> ! <p>We have added a <span class="inline_code">finally</span> block to make sure ! that the statement will always be closed, even if there are failures when using ! it. Interestingly, the code now also passes another test:</p> <pre><span class="deemphasised"> public void testPrepareStatementFailsForAdd() throws MailingListException, SQLException {</span> mockConnection.setupThrowExceptionOnPrepare(new SQLException("MockConnection")); *************** *** 198,204 **** between mailing list exceptions (the system works, but was used incorrectly) and SQL exceptions (there was a system failure). As the application grows, we ! might want to translate those SQL exceptions into a generic system exception ! so that we can generalize the exception handling. So far, however, that isn't ! necessary. <br> </p> <h2>Remove a member from the list</h2> --- 201,207 ---- between mailing list exceptions (the system works, but was used incorrectly) and SQL exceptions (there was a system failure). As the application grows, we ! might want to translate those SQL exceptions into application-specific exceptions ! to help us manage exception handling. So far, however, that isn't necessary. ! <br> </p> <h2>Remove a member from the list</h2> *************** *** 222,227 **** methods called. A succesful removal should return an update count greater than 0, so we preload a return value in the statement object. </p> ! <p>Next we test removing someone who is not in the list by setting the update ! count to 0:</p> <pre> public void testRemoveMissingMember() throws SQLException { mockStatement.setupUpdateCount(0); --- 225,230 ---- methods called. A succesful removal should return an update count greater than 0, so we preload a return value in the statement object. </p> ! <p>We can also test removing someone who is not in the list by setting the update ! count to 0.</p> <pre> public void testRemoveMissingMember() throws SQLException { mockStatement.setupUpdateCount(0); *************** *** 241,245 **** mockStatement.verify(); }</span></pre> ! <p>The implementation of <span class="inline_code">removeMember</span> is:</p> <pre> public void removeMember(Connection connection, String emailAddress) throws MailingListException , SQLException<br> { --- 244,249 ---- mockStatement.verify(); }</span></pre> ! <p>The implementation of <span class="inline_code">removeMember</span> that supports ! both these tests is:</p> <pre> public void removeMember(Connection connection, String emailAddress) throws MailingListException , SQLException<br> { *************** *** 278,282 **** } </pre> ! <p>and our existing tests simplify to, for example:</p> <pre><span class="deemphasised"> public void testRemoveMember() throws MailingListException, SQLException { mockStatement.setupUpdateCount(1); --- 282,287 ---- } </pre> ! <p>This allows us to simplify our existing tests and make them easier to read, ! for example:</p> <pre><span class="deemphasised"> public void testRemoveMember() throws MailingListException, SQLException { mockStatement.setupUpdateCount(1); *************** *** 300,312 **** <h3> What have we learned?</h3> <p>As the application grows, we find that the incremental costs of adding new ! tests falls as we start to benefit from the unit tests we already have. At first, ! the benefit is intellectual, we can write a new test by altering what we have ! already done; the next stage is to refactor the tests to remove duplication. ! Maintaining and refactoring tests turns out to be as important as maintaining ! the code they exercise; the tests must be agile enough to follow the code as ! it is grows and changes. </p> <p>That said, we must maintain a balance here and not refactor the tests until ! they become too hard to read; this applies particularly to verifications. In ! our example, the two verifiable objects are obvious enough that we can move them into a method with a meangingful name. Elsewhere it may be better to leave the calls to <span class="inline_code">verify </span>in each test case to make --- 305,317 ---- <h3> What have we learned?</h3> <p>As the application grows, we find that the incremental costs of adding new ! tests falls as we start to benefit from the unit tests we have alread written. ! At first, the benefit is intellectual, we can write a new test by copying and ! altering what we already have; the next stage is to refactor the tests to remove ! duplication. Maintaining and refactoring tests turns out to be as important ! as maintaining the code they exercise; the tests must be agile enough to follow ! the code as it is grows and changes. </p> <p>That said, we must maintain a balance here and not refactor the tests until ! they become too obscure to read; this applies particularly to verifications. ! In our example, the two verifiable objects are obvious enough that we can move them into a method with a meangingful name. Elsewhere it may be better to leave the calls to <span class="inline_code">verify </span>in each test case to make *************** *** 362,396 **** statement.close(); }</pre> ! <h3>What have we learned?</h3> ! <p></p> ! <p>We can test quite complicated networks of objects by being clear about what ! we want to test and being ruthless in minimising the support we provide in our ! mock implementation. There are several excellent stub implementations of the ! JDBC library but these are not necessary where we have enough control to structure ! our code appropriately. </p> ! <p>We can also make such testing much easier by factoring out the complexities ! into common support libraries.</p> <p>This first test proves that we can extract the right values from a valid row ! in a <span class="inline_code">ResultSet</span>. With the test in place we can ! simplify our other tests to concentrate on other aspects, such as handling different ! numbers of valid rows. For example, the test for listing two members is:</p> <pre> public void testListTwoMembers() throws SQLException { MockMultiRowResultSet mockResultSet = new MockMultiRowResultSet(); mockStatement.setupResultSet(mockResultSet); mockResultSet.setupColumnNames(COLUMN_NAMES); mockResultSet.setupRows(TWO_ROWS); mockResultSet.setExpectedNextCalls(3); mockListMembers.setExpectedMemberCount(2); ! setExpectationsForListMembers(); list.applyToAllMembers(mockConnection, mockListMembers); ! <span class="deemphasised"> verifyJDBC(); mockResultSet.verify(); mockListMembers.verify();</span> }</pre> ! For this test, all we are concerned with is that <br> ! <br> <hr> <p>© Steve Freeman, 2001</p> --- 367,509 ---- statement.close(); }</pre> ! <h3>Extracting more than one member</h3> <p>This first test proves that we can extract the right values from a valid row ! in a <span class="inline_code">ResultSet</span>. Once we have a test for this, ! our other tests can concentrate on other aspects, such as handling different ! numbers of valid rows. We do not need to re-test extraction in every case. For ! example, when testing for different numbers of list members we only need to ! set expectations for the number of times we call the <span class="inline_code">listMembers</span> ! object, we do not need to check again that the right values have been received. ! This makes tests more precise and orthogonal, and so easier to understand when ! they fail, which makes test cases and mock objects easier to write because each ! one does less.</p> ! <p>For example, the test for listing two members does not set any expectations ! for the list member name and email address. This version does set column names ! and some dummy values, but these are only necessary to avoid type casting errors ! when returning values from the <span class="inline_code">ResultSet</span>; they ! are also used to define the number of rows to return. The expectations we do ! set are concerned with the number of times various methods are called.</p> <pre> public void testListTwoMembers() throws SQLException { MockMultiRowResultSet mockResultSet = new MockMultiRowResultSet(); mockStatement.setupResultSet(mockResultSet); mockResultSet.setupColumnNames(COLUMN_NAMES); + mockResultSet.setupRows(TWO_ROWS); + mockResultSet.setExpectedNextCalls(3); mockListMembers.setExpectedMemberCount(2); ! <span class="deemphasised"> setExpectationsForListMembers(); list.applyToAllMembers(mockConnection, mockListMembers); ! verifyJDBC(); mockResultSet.verify(); mockListMembers.verify();</span> }</pre> ! <p>The test for a <span class="inline_code">ResultSet</span> with no rows is even ! simpler, we set up no row values at all and we tell the mock <span class="inline_code">ListMembers</span> ! object to expect not to be called. At this point, we can also factor out setting ! up the mock <span class="inline_code">ResultSet</span> into a helper method.</p> ! <pre> public void testListNoMembers() throws SQLException { ! MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); ! ! mockResultSet.setExpectedNextCalls(1); ! mockListMembers.setExpectNoMembers(); ! <span class="deemphasised"> setExpectationsForListMembers(); ! ! list.applyToAllMembers(mockConnection, mockListMembers); ! ! verifyJDBC(); ! mockResultSet.verify(); ! mockListMembers.verify();</span> ! } ! </pre> ! <h3>Handling failures</h3> ! <p>Our simple implementation of <span class="inline_code">applyToAllMembers</span> ! can support all these tests, but we know that we still have to manage exceptions. ! We should write an additional test to confirm that we can cope if the <span class="inline_code">ResultSet</span> ! fails. As with the test for adding an existing member, we wrap the call to the ! <span class="inline_code">ListMembers</span> object in a <span class="inline_code">try</span> ! block and fail if the exception is not thrown. We also use the same technique ! as before to tell the mock <span class="inline_code">ResultSet</span> to throw ! an exception when anyone tries to get a value.</p> ! <pre><span class="deemphasised"> public void testListResultSetFailure() { ! MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); ! mockResultSet.setupRows(TWO_ROWS);</span> ! mockResultSet.setupThrowExceptionOnGet(new SQLException("Mock Exception")); ! ! mockResultSet.setExpectedNextCalls(1); ! mockListMembers.setExpectNoMembers(); ! <span class="deemphasised"> setExpectationsForListMembers();</span> ! ! try { ! list.applyToAllMembers(mockConnection, mockListMembers); ! fail("Should have thrown exception"); ! } catch (SQLException expected) { ! } ! <span class="deemphasised"> mockResultSet.verify(); ! mockListMembers.verify(); ! }</span> ! </pre> ! <p>Our implementation will not pass this test because it has no <span class="inline_code">finally</span> ! clause, so we add it now.</p> ! <pre><span class="deemphasised"> public void applyToAllMembers(Connection connection, ListMembers listMembers) throws SQLException { ! Statement statement = connection.createStatement();</span> ! try { ! <span class="deemphasised"> ResultSet results = statement.executeQuery(LIST_SQL); ! while (results.next()) { ! listMembers.member(results.getString("email_address"), results.getString("name")); ! }</span> ! } finally { ! statement.close(); ! } ! <span class="deemphasised"> }</span> ! </pre> ! <p>We might also add tests to check that we correctly handle failures when the ! connection cannot create a statement or the statement cannot execute the query. ! For a long-lived server, this sort of error handling avoids resource leakages ! that can be very difficult to find in production.</p> ! <h3>Presenting the results</h3> ! <p>We can now ask a <span class="inline_code">MailingList</span> object to process ! all the members of the list by passing an object of type <span class="inline_code">ListMembers</span>. ! In a servlet, we might present the results by implementing an <span class="inline_code">MembersAsTableRow</span> ! class that writes out each member as a row in an HTML table; the <span class="inline_code">PrintWriter</span> ! would be passed through from the request's <span class="inline_code">ServletResponse</span>.</p> ! <pre> class MembersAsTableRow implements ListMembers {<br> PrintWriter writer; ! public MembersAsTableRow(PrintWriter aPrintWriter) { ! writer = aPrintWriter; ! } ! public member(String email, String name) { ! writer.print("<TR><TD>"); ! writer.print(email); ! writer.print("</TD><TD>"); ! writer.print(name); ! writer.println("</TD></TR>"); ! } ! }</pre> ! Of course this new class should have its own set of unit tests.<br> ! <h3>What have we learned</h3> ! <p>A common difficulty when testing networks of objects is the cost of setting ! up the test environment. These techniques show that we can manage this by being ! very precise about what each test verifies, and by providing just enough mock ! implementation to get us through. Teasing out the different aspects of what ! we are testing to make the tests more orthogonal has several advantages: the ! tests are more precise, so errors are easier to find; smaller tests are easier ! to implement and easier to read; and, the mock implementations can be more specialised ! and so simpler to implement. </p> ! <p>An alternative approach is to use one of the available stub JDBC implementations, ! or even a scratch copy of a real database. This is a good technique when getting ! started with unit testing or when retrofitting tests to an existing code base, ! but the mock object approach still has some advantages: </p> ! <ul> ! <li>the setup is cheaper, which makes the tests easier to maintain and quicker ! to run; </li> ! <li>failures can happen as soon as something unexpected happens, rather than ! verifying the result afterwards; </li> ! <li>we can verify behaviour such as the number of times times <span class="inline_code">close()</span> ! is called; and, </li> ! <li>we can force unusual conditions such as SQL exceptions.</li> ! </ul> <hr> <p>© Steve Freeman, 2001</p> |
From: Steve F. <sm...@us...> - 2001-08-11 20:42:08
|
Update of /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/calcserver In directory usw-pr-cvs1:/tmp/cvs-serv1930/examples/com/mockobjects/examples/calcserver Modified Files: CalculatorServlet.java Log Message: more examples, plus some tidy up Index: CalculatorServlet.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/calcserver/CalculatorServlet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** CalculatorServlet.java 2001/07/29 19:50:25 1.1 --- CalculatorServlet.java 2001/08/11 20:42:05 1.2 *************** *** 14,52 **** ! /** ! * Process incoming HTTP GET requests ! * ! * @param request Object that encapsulates the request to the servlet ! * @param response Object that encapsulates the response from the servlet ! */ ! public void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { ! performTask(request, response); - } - - - /** - * Process incoming HTTP POST requests - * - * @param request Object that encapsulates the request to the servlet - * @param response Object that encapsulates the response from the servlet - */ - public void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { performTask(request, response); - } - - /** - * Returns the servlet info string. - */ public String getServletInfo() { - return super.getServletInfo(); - } - public void init() throws ServletException { --- 14,28 ---- ! public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { performTask(request, response); } + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { performTask(request, response); } public String getServletInfo() { return super.getServletInfo(); } public void init() throws ServletException { |
From: Steve F. <sm...@us...> - 2001-08-11 20:42:08
|
Update of /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist In directory usw-pr-cvs1:/tmp/cvs-serv1930/examples/com/mockobjects/examples/mailinglist Modified Files: TestMailingList.java Log Message: more examples, plus some tidy up Index: TestMailingList.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/examples/com/mockobjects/examples/mailinglist/TestMailingList.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** TestMailingList.java 2001/08/09 22:06:26 1.7 --- TestMailingList.java 2001/08/11 20:42:05 1.8 *************** *** 54,58 **** public void testPrepareStatementFailsForAdd() throws MailingListException { ! mockConnection.setupThrowExceptionOnPrepare(new SQLException("MockConnection")); mockConnection.setExpectedPrepareStatementString(MailingList.INSERT_SQL); --- 54,58 ---- public void testPrepareStatementFailsForAdd() throws MailingListException { ! mockConnection.setupThrowExceptionOnPrepareOrCreate(new SQLException("MockConnection")); mockConnection.setExpectedPrepareStatementString(MailingList.INSERT_SQL); *************** *** 138,142 **** } ! public void testResultSetFailure() { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); mockResultSet.setupRows(TWO_ROWS); --- 138,142 ---- } ! public void testListResultSetFailure() { MockMultiRowResultSet mockResultSet = makeMultiRowResultSet(); mockResultSet.setupRows(TWO_ROWS); *************** *** 153,156 **** --- 153,186 ---- } mockResultSet.verify(); + mockListMembers.verify(); + } + + public void testListStatementFailure() { + mockStatement.setupThrowExceptionOnExecute(new SQLException("Mock exception")); + mockListMembers.setExpectNoMembers(); + setExpectationsForListMembers(); + + try { + list.applyToAllMembers(mockConnection, mockListMembers); + fail("Should have thrown exception"); + } catch (SQLException expected) { + } + mockListMembers.verify(); + } + + public void testListConnectionFailure() { + mockConnection.setupThrowExceptionOnPrepareOrCreate(new SQLException("Mock Exception")); + + mockConnection.setExpectedCreateStatementCalls(1); + mockStatement.setExpectedCloseCalls(0); + mockStatement.setExpectedExecuteCalls(0); + + mockListMembers.setExpectNoMembers(); + + try { + list.applyToAllMembers(mockConnection, mockListMembers); + fail("Should have thrown exception"); + } catch (SQLException expected) { + } mockListMembers.verify(); } |
From: Steve F. <sm...@us...> - 2001-08-11 20:42:08
|
Update of /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/sql In directory usw-pr-cvs1:/tmp/cvs-serv1930/core/com/mockobjects/sql Modified Files: MockConnection.java Log Message: more examples, plus some tidy up Index: MockConnection.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/sql/MockConnection.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** MockConnection.java 2001/08/05 23:33:10 1.2 --- MockConnection.java 2001/08/11 20:42:05 1.3 *************** *** 14,18 **** private ExpectationValue myPrepareStatementString = new ExpectationValue("MockConnection.preparedStatementString"); private PreparedStatement myPreparedStatement; ! private SQLException myPrepareException = null; private ExpectationCounter myCreateStatementCalls = new ExpectationCounter("MockConnection.createStatement"); --- 14,18 ---- private ExpectationValue myPrepareStatementString = new ExpectationValue("MockConnection.preparedStatementString"); private PreparedStatement myPreparedStatement; ! private SQLException myStatementException = null; private ExpectationCounter myCreateStatementCalls = new ExpectationCounter("MockConnection.createStatement"); *************** *** 51,56 **** } ! public void setupThrowExceptionOnPrepare(SQLException exception) { ! myPrepareException = exception; } --- 51,56 ---- } ! public void setupThrowExceptionOnPrepareOrCreate(SQLException exception) { ! myStatementException = exception; } *************** *** 68,71 **** --- 68,72 ---- public Statement createStatement() throws SQLException { myCreateStatementCalls.inc(); + throwStatementExceptionIfAny(); return myStatement; } *************** *** 130,136 **** public PreparedStatement prepareStatement(String sql) throws SQLException { myPrepareStatementString.setActual(sql); ! if (null != myPrepareException) { ! throw myPrepareException; ! } return myPreparedStatement; } --- 131,135 ---- public PreparedStatement prepareStatement(String sql) throws SQLException { myPrepareStatementString.setActual(sql); ! throwStatementExceptionIfAny(); return myPreparedStatement; } *************** *** 168,171 **** --- 167,176 ---- public void setTypeMap(Map map) throws SQLException { throw new UnsupportedOperationException(); + } + + private void throwStatementExceptionIfAny() throws SQLException { + if (null != myStatementException) { + throw myStatementException; + } } |
From: Steve F. <st...@m3...> - 2001-08-11 15:19:20
|
Q29vbC4gDQoNCkkndmUgYmVlbiB0cnlpbmcgdG8gZ2V0IGVjbGlwc2UgdG8gd29yayB3aXRoIHNv dXJjZWZvcmdlLiBJdCdsbCBkbyB0aGUgZG93bmxvYWQsIGJ1dCBJIGNhbid0IGdldCBnZW5lcmlj IENWUy1iYXNlZCBwcm9qZWN0cyB0byBkbyB0aGUgamF2YSB0aGluZy4gSG1tbS4NCg0KLS0tLS0g T3JpZ2luYWwgTWVzc2FnZSAtLS0tLSANCkZyb206ICJWaW5jZW50IE1hc3NvbCIgPHZtYXNzb2xA b2N0by5jb20+DQpUbzogPG1vY2tvYmplY3RzLWphdmEtZGV2QGxpc3RzLnNvdXJjZWZvcmdlLm5l dD4NClNlbnQ6IFNhdHVyZGF5LCBBdWd1c3QgMTEsIDIwMDEgMzo1NyBQTQ0KU3ViamVjdDogW01v Y2tvYmplY3RzLWphdmEtZGV2XSBDVlMgbm90aWZpY2F0aW9ucyAhDQoNCg0KPiBJIGhhdmUgZmlu YWxseSBzdWNjZWVkZWQgaW4gY29uZmlndXJpbmcgQ1ZTIHNvIHRoYXQgaXQgc2VuZHMgbWVzc2Fn ZXMgdG8gdGhlDQo+IGRldiBtYWlsaW5nIGxpc3Qgd2hlbmV2ZXIgc29tZW9uZSBtYWtlcyBhIGNv bW1pdC4gVGhpcyBpcyBzbyB0aGF0IHdlIGNhbg0KPiB0cmFjayB3aGF0IGlzIGhhcHBlbmluZyBv biB0aGUgcmVwb3NpdG9yeS4gT3RoZXJ3aXNlLCBpdCBpcyBoYXJkIHRvIGtub3cNCj4gd2hlbiBz b21ldGhpbmcgaGFzIGNoYW5nZWQgLi4uDQo+IA0KPiBUaGFua3MNCj4gLVZpbmNlbnQNCj4gDQo+ IA0KPiBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KPiBN b2Nrb2JqZWN0cy1qYXZhLWRldiBtYWlsaW5nIGxpc3QNCj4gTW9ja29iamVjdHMtamF2YS1kZXZA bGlzdHMuc291cmNlZm9yZ2UubmV0DQo+IGh0dHA6Ly9saXN0cy5zb3VyY2Vmb3JnZS5uZXQvbGlz dHMvbGlzdGluZm8vbW9ja29iamVjdHMtamF2YS1kZXYNCj4gDQo= |
From: Vincent M. <vm...@oc...> - 2001-08-11 14:55:24
|
I have finally succeeded in configuring CVS so that it sends messages to the dev mailing list whenever someone makes a commit. This is so that we can track what is happening on the repository. Otherwise, it is hard to know when something has changed ... Thanks -Vincent |
From: Vincent M. <vm...@us...> - 2001-08-11 14:52:03
|
Update of /cvsroot/mockobjects/mockobjects-java/doc/xdocs In directory usw-pr-cvs1:/tmp/cvs-serv4299/doc/xdocs Modified Files: index.xml Log Message: test (this is to verify that upon CVS commit the notification of the commit is sent to the mockobjects-java-dev mailing list) ... Index: index.xml =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/doc/xdocs/index.xml,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** index.xml 2001/08/11 14:50:45 1.11 --- index.xml 2001/08/11 14:51:59 1.12 *************** *** 21,25 **** is a generic unit testing framework whose goal is to facilitate developing unit tests in the mock object style. The goal of this ! project is to provide : </p> <ul> --- 21,25 ---- is a generic unit testing framework whose goal is to facilitate developing unit tests in the mock object style. The goal of this ! project is to provide: </p> <ul> |
From: Vincent M. <vm...@oc...> - 2001-08-10 16:00:36
|
----- Original Message ----- From: "Tim Mackinnon" <tim...@po...> To: <moc...@li...> Cc: "Vincent Massol" <vm...@oc...> Sent: Thursday, August 09, 2001 7:40 PM Subject: [Mockobjects-java-dev] RE: Speed of Mock Objects project ... > Hey - Vincent, I admire your enthusiasm - but give us a chance to kick in > some effort. To be honest - I don't know how you find time to do all of the > things that you do (my time from 9:30 to 6 is basically spent at work doing I don't sleep ... :) No, just kidding of course ... To tell the truth I have the chance of having an understanding wife who let me work on that at night and during some parts of the week end ... ! > heavy duty programming with a lot of mock objects. It is hard to find time > to check newsgroups etc. becuase I am expected to do work that will > contribute to the companies end goal - however I am trying to do a once a ... welcome to the club :-) ... my open source participation is some after work activity ... However I have the benefit of having flexibility to organize my work. > day check. That said, the whole idea behind mock objects was based on this > extreme working pattern, and many new ideas which are just starting to > germinate are based on this as well. We are also putting a lot of work into > automated acceptance tests that iterate accross operating systems - > something which people are only just starting to get interested in now). I know the issues, I have been doing this on my last project. It is quite hard and usually there are few tools: you have to build your own mechanism, usually based on shell scripts and the like ... yuck .... :) > > Now I can understand that you want to move quick - and I agree that we need > a kick - but you have to balance this with actually spending time using > MockObjects in your own programming (not just in the periphery). It impacts > your coding style a lot (especially if you pair program with someone) and I > think this is an area you may want to devote some time on (I am not sure we > always talk from the same perspective). Then we can really harness your > programming knowledge and apply it to EJB's etc, instead of just raping your > ANT/OpenSource experience. That's true, I have not used Mock Objects yet ! Which is why I am thinking about a good project where I/we could do this and compare Cactus vs MO ... More in a future mail. > > We need to push on a bit as you have been pioneering - however I think we > will see a slowdown as we stop to learn about the next generation of > ideas/expectations. Obviously - if you are sick of trailblazing, I can > understand your frustration... hang in a bit though. no worry ... ! :) > > Tim -Vincent |
From: Vincent M. <vm...@oc...> - 2001-08-10 15:53:29
|
This is a reminder of the actions to do whenever we make changes to CVS : * Ensure that the change does not break anything. Please run 'ant all' to ensure this. Nothing should be committed that break something. If it is the case it should be discussed first on the mailing list * Try to respect the coding conventions (yes I know we have not published them - will do soon) * When you have finished something, ensure that you add it to the changes.xml file so that everyone knows what's new in the future version. It is a pain to try to remember retroactively what everyone has changed ... * Remove the item from the todo list when finished Thanks -Vincent |
From: Vincent M. <vm...@oc...> - 2001-08-10 15:51:48
|
Hi, I have added a new target to our build.xml file : "deploy-site". To use it type 'ant -Dusername=your_sf_user_name deploy-site' In order for it to work you must have : - a user account on SF with ssh access to mockobjects project - ssh in your path - scp in your path I don't know if it works if you are not using a public key (i.e. if you have to type in your password). I don't know how Ant handles reading characters from the keyboard ... it may not work ? Thanks -Vincent |
From: Tim M. <tim...@po...> - 2001-08-09 18:39:35
|
Hey - Vincent, I admire your enthusiasm - but give us a chance to kick in some effort. To be honest - I don't know how you find time to do all of the things that you do (my time from 9:30 to 6 is basically spent at work doing heavy duty programming with a lot of mock objects. It is hard to find time to check newsgroups etc. becuase I am expected to do work that will contribute to the companies end goal - however I am trying to do a once a day check. That said, the whole idea behind mock objects was based on this extreme working pattern, and many new ideas which are just starting to germinate are based on this as well. We are also putting a lot of work into automated acceptance tests that iterate accross operating systems - something which people are only just starting to get interested in now). Now I can understand that you want to move quick - and I agree that we need a kick - but you have to balance this with actually spending time using MockObjects in your own programming (not just in the periphery). It impacts your coding style a lot (especially if you pair program with someone) and I think this is an area you may want to devote some time on (I am not sure we always talk from the same perspective). Then we can really harness your programming knowledge and apply it to EJB's etc, instead of just raping your ANT/OpenSource experience. We need to push on a bit as you have been pioneering - however I think we will see a slowdown as we stop to learn about the next generation of ideas/expectations. Obviously - if you are sick of trailblazing, I can understand your frustration... hang in a bit though. Tim > -----Original Message----- > From: Vincent Massol [mailto:vm...@oc...] > Sent: 9 August 2001 10:24 am > To: Steve Freeman; Tim Mackinnon > Subject: Speed of Mock Objects project ... > > > Steve, Tim, > > Just a short note to tell you that I am going to drop speed on the > mockobjects project. My idea was to give it a momentum and to get > it out of > oblivion and up and thriving before other frameworks like it > (like EasyMock > or others). Apparently you cannot devote too much time on it, which is ok, > but it simply means the project will have to continue on its slow pace > (which may be just fine, it's just I like it a bit more dynamic ... :) ). > > I'll continue to participate of course, but just don't expect me to do it > all and to drive it. For example I can bet that the 0.01 release will not > happen before 2 months ... (whereas with very little work it can be > delivered in less than a week) ... > > Again, the biggest problem is lack of responsivness. > > Thanks > -Vincent > > |