java_testing_guff 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ desc 'Release the website and new gem version'
2
+ task :deploy => [:check_version, :website, :release] do
3
+ puts "Remember to create SVN tag:"
4
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
5
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
6
+ puts "Suggested comment:"
7
+ puts "Tagging release #{CHANGES}"
8
+ end
9
+
10
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
11
+ task :local_deploy => [:website_generate, :install_gem]
12
+
13
+ task :check_version do
14
+ unless ENV['VERSION']
15
+ puts 'Must pass a VERSION=x.y.z release version'
16
+ exit
17
+ end
18
+ unless ENV['VERSION'] == VERS
19
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
20
+ exit
21
+ end
22
+ end
23
+
24
+ desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
+ task :install_gem_no_doc => [:clean, :package] do
26
+ sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
27
+ end
28
+
29
+ namespace :manifest do
30
+ desc 'Recreate Manifest.txt to include ALL files'
31
+ task :refresh do
32
+ `rake check_manifest | patch -p0 > Manifest.txt`
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ task :ruby_env do
2
+ RUBY_APP = if RUBY_PLATFORM =~ /java/
3
+ "jruby"
4
+ else
5
+ "ruby"
6
+ end unless defined? RUBY_APP
7
+ end
@@ -0,0 +1,17 @@
1
+ desc 'Generate website files'
2
+ task :website_generate => :ruby_env do
3
+ (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
4
+ sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
5
+ end
6
+ end
7
+
8
+ desc 'Upload website files to rubyforge'
9
+ task :website_upload do
10
+ host = "#{rubyforge_username}@rubyforge.org"
11
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
12
+ local_dir = 'website'
13
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
14
+ end
15
+
16
+ desc 'Generate and upload website files'
17
+ task :website => [:website_generate, :website_upload, :publish_docs]
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestBuildersGeneration < AbstractGuffTestCase
4
+
5
+ def test_can_generate_concrete_builder_selector
6
+
7
+ generator(JavaTestingGuff::RealBuilderGuffGenerator).generate_selector_foreach(['org.rubyforge.Customer','org.rubyforge.Address'])
8
+
9
+ assert expected('GeneratedBuilderSelector').same_as(generated('GeneratedBuilderSelector'))
10
+ end
11
+
12
+ def test_can_generate_jmock_builder_selector
13
+
14
+ generator(JavaTestingGuff::JMockGuffGenerator).generate_selector_foreach(['org.rubyforge.Customer','org.rubyforge.Address'])
15
+
16
+ assert expected('GeneratedJMockBuilderSelector').same_as(generated('GeneratedJMockBuilderSelector'))
17
+ end
18
+
19
+ end
@@ -0,0 +1,91 @@
1
+ require 'test/unit'
2
+
3
+ class JavaFileForTests
4
+ def initialize(testcase,path)
5
+ @testcase = testcase
6
+ @path = path
7
+ end
8
+
9
+ def same_as(path)
10
+ me = File.new(@path,"r")
11
+ other_lines = read_lines(path)
12
+ line_count=0
13
+ me.each_line do |line|
14
+ @testcase.assert_equal(line, other_lines[line_count],"#{path}:#{line_count.to_s}")
15
+ line_count = line_count + 1
16
+ end
17
+ me.close
18
+ true
19
+ end
20
+
21
+ def read_lines(path)
22
+ result = []
23
+ f = File.new(path,"r")
24
+ f.each_line do |line|
25
+ result << line
26
+ end
27
+ f.close
28
+ result
29
+ end
30
+
31
+ end
32
+
33
+ class AbstractGuffTestCase < Test::Unit::TestCase
34
+ def test_default
35
+
36
+ end
37
+
38
+ def setup
39
+ FileUtils::rm_rf(generated_dir)
40
+ end
41
+
42
+ def expected_files_dir
43
+ relative_dir('/src/expected_files')
44
+ end
45
+
46
+ def generated_dir
47
+ relative_dir('/src/generated')
48
+ end
49
+
50
+ def generated_package
51
+ 'org.rubyforge.generated'
52
+ end
53
+
54
+ def relative_dir(p)
55
+ File.dirname(__FILE__) + p
56
+ end
57
+
58
+ def expected(class_name)
59
+ JavaFileForTests.new(self,expected_files_dir + "/" + generated_package.gsub(".","/") + "/" + class_name + ".java")
60
+ end
61
+
62
+ def generated(class_name)
63
+ generated_dir + "/" + generated_package.gsub(".","/") + "/" + class_name + ".java"
64
+ end
65
+
66
+ def generator(generator_type)
67
+ javadocBuilder = JavaDocBuilder.new
68
+ javadocBuilder.add_source_tree(JFile.new(relative_dir("/src/java")))
69
+
70
+ generator_type.new(javadocBuilder).save_in(generated_dir).use_package(generated_package)
71
+ end
72
+
73
+
74
+ end
75
+
76
+ module JavaSourceTestHelper
77
+ def tmp_dir
78
+ '.'
79
+ end
80
+
81
+ def prepared_file_for_tests(name)
82
+ JavaFileForTests.new(self,File.dirname(__FILE__) + "/files/#{name}.java")
83
+ end
84
+
85
+ def assert_source_file_equals(source, expected)
86
+ file_path = source.save_in(tmp_dir)
87
+ assert expected.same_as(file_path)
88
+ end
89
+ end
90
+
91
+ require File.dirname(__FILE__) + '/../lib/java_testing_guff'
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestJavaTestingGuff < AbstractGuffTestCase
4
+
5
+ def test_can_generate_concrete_builder
6
+
7
+ generator(JavaTestingGuff::RealBuilderGuffGenerator).generate_guff_foreach(['org.rubyforge.Customer'])
8
+
9
+ assert expected('GeneratedCustomerBuilder').same_as(generated('GeneratedCustomerBuilder'))
10
+ end
11
+
12
+ def test_can_generate_eazymock_builder
13
+
14
+ generator(JavaTestingGuff::EasyMockGuffGenerator).generate_guff_foreach(['org.rubyforge.Customer'])
15
+
16
+ assert expected('GeneratedCustomerMockBuilder').same_as(generated('GeneratedCustomerMockBuilder'))
17
+ end
18
+
19
+ def test_can_generate_jmock_builder
20
+
21
+ generator(JavaTestingGuff::JMockGuffGenerator).generate_guff_foreach(['org.rubyforge.Customer'])
22
+
23
+ assert expected('GeneratedCustomerJMockBuilder').same_as(generated('GeneratedCustomerJMockBuilder'))
24
+ end
25
+ end
@@ -0,0 +1,294 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ Generate Java test classes
9
+ </title>
10
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
+ <style>
12
+
13
+ </style>
14
+ <script type="text/javascript">
15
+ window.onload = function() {
16
+ settings = {
17
+ tl: { radius: 10 },
18
+ tr: { radius: 10 },
19
+ bl: { radius: 10 },
20
+ br: { radius: 10 },
21
+ antiAlias: true,
22
+ autoPad: true,
23
+ validTags: ["div"]
24
+ }
25
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
+ versionBox.applyCornersToAll();
27
+ }
28
+ </script>
29
+ </head>
30
+ <body>
31
+ <div id="main">
32
+
33
+ <h1>Generate Java test classes</h1>
34
+ <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/java_testing_guff"; return false'>
35
+ <p>Get Version</p>
36
+ <a href="http://rubyforge.org/projects/java_testing_guff" class="numbers">0.0.1</a>
37
+ </div>
38
+ <h1>&#x2192; &#8216;java_testing_guff&#8217;</h1>
39
+
40
+
41
+ <h2>What</h2>
42
+
43
+
44
+ <p>java_testing_guff consists of a number of Ruby classes that generate Java classes that enable
45
+ a fluent interface style specification of mock behaviours in tests. It also generates fluent interfaces for setting
46
+ up java objects in particular states. For example:</p>
47
+
48
+
49
+ <p><pre class='syntax'>mock().customer().withId(10).notLoggedIn().expectingNewAddress().build()</pre>
50
+ <pre class='syntax'>real().order().withId(2).withOrderLine(line).withCustomer(customer).build()</pre></p>
51
+
52
+
53
+ <p>It does this by parsing your production code and creating java classes that implement a sensible fluent interface.</p>
54
+
55
+
56
+ <p>Both JMock and EasyMock are supported.</p>
57
+
58
+
59
+ <p>The gem works only with JRuby.</p>
60
+
61
+
62
+ <h2>Installing</h2>
63
+
64
+
65
+ <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">java_testing_guff</span></pre></p>
66
+
67
+
68
+ <p>java_guff_builder makes use of the gem &#8216;guff&#8217; to generate nicely formatted java code. &#8216;guff&#8217; will be installed as a dependent
69
+ gem while installing java_guff_builder.</p>
70
+
71
+
72
+ <p>Also, QDox
73
+ (currently qdox-1.7-20070527.154641-2.jar) is needed on the JRuby classpath, to parse your production java source
74
+ files. So make sure you download <a href="http://qdox.codehaus.org">QDox</a> and install it:</p>
75
+
76
+
77
+ <p><pre class='syntax'>cp qdox-1.7-20070527.154641-2.jar $JRUBY_HOME/lib</pre></p>
78
+
79
+
80
+ <h2>The basics</h2>
81
+
82
+
83
+ <p>To generate one of these fluent interfaces, write a jruby script that does the following:</p>
84
+
85
+
86
+ <ol>
87
+ <li>instantiates a QDox JavaDocBuilder</li>
88
+ <li>configures the builder with the path(s) that contain your production code</li>
89
+ <li>instantiate and configure a particular generator (EasyMock, JMock, Concrete object)</li>
90
+ <li>tell the generate to go to work on an array of class names</li>
91
+ </ol>
92
+
93
+
94
+ <p>Optionally bind the generated classes into a subclass of TestCase so the syntax flows naturally (see below).</p>
95
+
96
+
97
+ <h2>Demonstration of usage</h2>
98
+
99
+
100
+ <p>Lets say you have two production classes, Customer and Order, that you want to generate EasyMock builders and a &#8216;real&#8217;
101
+ builder for. And the source code for these classes sits in &#8216;src/java&#8217;.</p>
102
+
103
+
104
+ <p>All builders require a configured JavaDocBuilder. JavaDocBuilder may seem like a weird name in terms of what we are
105
+ trying to do here, but thats what QDox calls it, so pretend its called &#8216;ProductionCodeParser&#8217; :-)</p>
106
+
107
+
108
+ <p><pre class='syntax'>
109
+ require 'rubygems'
110
+ require 'java_testing_guff'
111
+
112
+ javadocBuilder = JavaDocBuilder.new
113
+ javadocBuilder.add_source_tree(JFile.new('src/java'))
114
+ javadocBuilder.add_source_tree(JFile.new('maybe some other paths?'))
115
+ </pre></p>
116
+
117
+
118
+ <p>No we go ahead and use the EasyMockGuffGenerator combined with that JavaDocBuilder:</p>
119
+
120
+
121
+ <p><pre class='syntax'>
122
+ easyMockGuffGenerator=JavaTestingGuff::EasyMockGuffGenerator.new(javadocBuilder)
123
+ .save_in('src/test')
124
+ .use_package('org.rubyforge.generated.mockbuilders')
125
+
126
+ easyMockGuffGenerator.generate_guff_foreach(['org.rubyforge.Customer','org.rubyforge.Order'])
127
+ </pre></p>
128
+
129
+
130
+ <p>This will generate org.rubyforge.generated.mockbuilders.GeneratedCustomerMockBuilder.java
131
+ and org.rubyforge.generated.mockbuilders.GeneratedOrderMockBuilder.java in the directory src/test.</p>
132
+
133
+
134
+ <p>The same kind of thing works for JMock and &#8220;real&#8221; builders:</p>
135
+
136
+
137
+ <p><pre class='syntax'>
138
+ jMockGuffGenerator=JavaTestingGuff::JMockGuffGenerator.new(javadocBuilder)
139
+ .save_in('src/test')
140
+ .use_package('org.rubyforge.generated.mockbuilders')
141
+
142
+ jMockGuffGenerator.generate_guff_foreach(['org.rubyforge.Customer','org.rubyforge.Order'])
143
+ </pre></p>
144
+
145
+
146
+ <p><pre class='syntax'>
147
+ realMockGuffGenerator=JavaTestingGuff::RealBuilderGuffGenerator.new(javadocBuilder)
148
+ .save_in('src/test')
149
+ .use_package('org.rubyforge.generated.realbuilders')
150
+
151
+ realMockGuffGenerator.generate_guff_foreach(['org.rubyforge.Customer','org.rubyforge.Order'])
152
+ </pre></p>
153
+
154
+
155
+ <p>One hint: if you want to use more than one generator on your project, use the same JavaDocBuilder instance,
156
+ because it takes quite some time to build this class as it parses all your production code.</p>
157
+
158
+
159
+ <h3>A word about EasyMock and MockCreator</h3>
160
+
161
+
162
+ <p>EasyMock provides two ways of creating mock instances:</p>
163
+
164
+
165
+ <p><pre class='syntax'>Customer customer = EasyMock.createMock(Customer.class)</pre></p>
166
+
167
+
168
+ <p>and</p>
169
+
170
+
171
+ <p><pre class='syntax'>
172
+ IMocksControl strictControl = EasyMock.createStrictControl();
173
+ Customer customer = strictControl.createMock(Customer.class)
174
+ </pre></p>
175
+
176
+
177
+ <p>Strict controls allow you to be explicit about ordering of method calls on mocks. The generated classes support
178
+ strict and nice (non-strick) mock construction as follows:</p>
179
+
180
+
181
+ <p><pre class='syntax'>
182
+ Customer niceCustomer = new GeneratedCustomerMockBuilder(new NiceMockCreator()).build();
183
+
184
+ IMocksControl strictControl = EasyMock.createStrictControl();
185
+ Customer strictCustomer = new GeneratedCustomerMockBuilder(new StrictMockCreator(strictControl)).build();
186
+ Customer anotherStrictCustomer = new GeneratedCustomerMockBuilder(new StrictMockCreator(strictControl)).build();
187
+ </pre></p>
188
+
189
+
190
+ <h3>java_testing_guff Java classes</h3>
191
+
192
+
193
+ <p>Some of the generated code makes use of Java classes that are distributed as part of this gem. You will find
194
+ the jar (java_testing_guff-x.y.z.jar) in the lib of this gem. You will need to include this jar on your classpath
195
+ to use the generated classes.</p>
196
+
197
+
198
+ <h3>Integration of generated classes</h3>
199
+
200
+
201
+ <p>You can use the generated classes like this if you please:</p>
202
+
203
+
204
+ <p><pre class='syntax'>
205
+ Customer customer = new GeneratedCustomerBuilder().withId(10).notLoggedIn().expectingNewAddress().build()
206
+ </pre></p>
207
+
208
+
209
+ <p>But personally I find that increases the noise in a test, taking away from clarity of intent. So I prefer to integrate
210
+ the generated classes into my own testing super class and provide more fluency:</p>
211
+
212
+
213
+ <p><pre class='syntax'>
214
+ public class MyTestCase extends TestCase {
215
+ public RealBuilders real() {
216
+ return new RealBuilders();
217
+ }
218
+
219
+ public MockBuilders mock() {
220
+ return new MockBuilders(new NiceMockCreator());
221
+ }
222
+
223
+ public MockBuilders mock(IMocksControl control) {
224
+ return new MockBuilders(new StrictMockCreator(control));
225
+ }
226
+
227
+ public class RealBuilders {
228
+ public GeneratedCustomerBuilder customer() {
229
+ return new GeneratedCustomerBuilder();
230
+ }
231
+ }
232
+
233
+ public class MockBuilders {
234
+ private final MockCreator mockCreator;
235
+
236
+ public MockBuilders(MockCreator mockCreator) {
237
+ this.mockCreator = mockCreator;
238
+ }
239
+
240
+ public GeneratedCustomerMockBuilder customer() {
241
+ return new GeneratedCustomerMockBuilder(mockCreator);
242
+ }
243
+ }
244
+ }
245
+ </pre></p>
246
+
247
+
248
+ <p>and now anything that inherits from MyTestCase can do</p>
249
+
250
+
251
+ <p><pre class='syntax'>
252
+ Customer customer = real().customer().withId(10).notLoggedIn().build();
253
+ Customer mockCustomer = mock().customer().withId(10).notLoggedIn().expectingNewAddress().build();
254
+ </pre></p>
255
+
256
+
257
+ <p>Suits me!</p>
258
+
259
+
260
+ <h2>Forum</h2>
261
+
262
+
263
+ <p><a href="http://groups.google.com/group/java-testing-guff">http://groups.google.com/group/java-testing-guff</a></p>
264
+
265
+
266
+ <h2>How to submit patches</h2>
267
+
268
+
269
+ <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
270
+
271
+
272
+ <p>The trunk repository is <code>svn://rubyforge.org/var/svn/jbuilder-guff</code> for anonymous access.</p>
273
+
274
+
275
+ <h2>License</h2>
276
+
277
+
278
+ <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
279
+
280
+
281
+ <h2>Contact</h2>
282
+
283
+
284
+ <p>Comments are welcome. Send a suggestion/question to the <a href="http://groups.google.com/group/java-testing-guff">forum</a></p>
285
+ <p class="coda">
286
+ <a href="me@mikehogan.net">Mike Hogan</a>, 7th February 2008<br>
287
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
288
+ </p>
289
+ </div>
290
+
291
+ <!-- insert site tracking codes here, like Google Urchin -->
292
+
293
+ </body>
294
+ </html>