java_testing_guff 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>