-
Notifications
You must be signed in to change notification settings - Fork 0
/
dbunit.html
343 lines (283 loc) · 12.5 KB
/
dbunit.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>easyb makes it easy, man</title>
<meta name="keywords" content="BDD, behavior driven development, java, java bdd, groovy, groovy bdd,
groovy behavior driven development, java behavior driven development, ruby, rspec, easyb, easy bdd" />
<meta name="description" content="easyb is story verification framework built in the spirit of behavior driven development." />
<link href="default.css" rel="stylesheet" type="text/css" />
</head>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-3500051-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
<body>
<!-- start header -->
<div id="header">
<h1><a href="http://www.easyb.org"><span>easyb</span></a></h1>
<h2> -- BDD in java can't get any easier</h2>
</div>
<!-- end header -->
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<h2 class="title">Dealing with databases with easyb</h2>
<div class="entry">
<p>easyb supports plug-in development-- for instance, the dbunit-plug-in supports database management via <a href="http://dbunit.sourceforge.net/">DbUnit</a>-- if you find that a particular story requires some prerequisite data, you can put that data in a database via the <code>database_model</code> call, which takes standard JDBC connection information (URL, user name, driver, etc) and then a <code>String</code> representation of DbUnit's standard <code>FlatXmlDataSet</code> type. So for example, in a <code>given</code> clause you can seed a database like so:
</p>
<pre><code>
given "the database is properly seeded", {
database_model("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
return new File("./src/conf/seed.xml").text
}
}
</code></pre>
<p>Using Groovy's <code>MarkupBuilder</code> is easy and lacks XML syntax: </p>
<pre><code>
given "the database is properly seeded", {
database_model("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
def writer = new StringWriter();
def builder = new MarkupBuilder(writer);
builder.dataset(){
word(word_id:1, spelling:"bellicose", part_of_speech:"Adjective")
definition(definition_id:10, definition:"demonstrating willingness \
and willingness to fight",
word_id:1, example_sentence:"The pugnacious youth had no friends \
left to pick on." )
synonym(synonym_id:20, word_id:1, spelling:"belligerent")
synonym(synonym_id:21, word_id:1, spelling:"aggressive")
}
return writer.toString()
}
}
</code></pre>
<p>Or just create the XML using <code>"""</code>.</p>
<pre><code>
given "the database is properly seeded", {
database_model("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
"""<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<word WORD_ID="1" SPELLING="pugnacious" PART_OF_SPEECH="Adjective"/>
<definition DEFINITION_ID="10" DEFINITION="Combative in nature; belligerent."
WORD_ID="1"
EXAMPLE_SENTENCE="The pugnacious youth had no friends left to pick on."/>
<synonym SYNONYM_ID="20" WORD_ID="1" SPELLING="belligerent"/>
<synonym SYNONYM_ID="21" WORD_ID="1" SPELLING="aggressive"/>
</dataset>
"""
}
}
</code></pre>
<p> That makes integration testing easy, doesn't it? The DbUnit plug-in is a <a href="http://code.google.com/p/easyb/downloads/list">separate jar file</a> you can download from the <a href="http://code.google.com/p/easyb/downloads/list">easyb Google code website</a>-- just ensure you have that jar in your classpath and easyb will find it if you invoke the <code>database_model</code> call.
</p>
<h3>The plug-in in action</h3>
<p>The easiest way to demonstrate the plug-in is to look at its own story-- in this case, the dbunit-plug-in uses easyb to verify itself. </p>
<p>
Using easyb itself, it is rather easy to describe what the plug-in does and how to use it. A story to validate the database plug-in sounds a bit like this:
<ul>
<li>given that database has an initialized data model (i.e. tables to hold stuff) </li>
<li>and given the plug-in’s method is invoked with a dataset (i.e. rows for tables) </li>
<li>when a select statement is issued for a value only found in the dataset inserted by the plug-in </li>
<li> then the desired item (i.e. column value) should be returned </li>
</ul>
</p>
<p>
In essence, this story is the use case for the plug-in– reading it you can most likely ascertain that the plug-in puts rows in database tables. Reading this story, it is also evident that at some point, it may be helpful to start and stop a database instance during the course of the story– i.e. start it up at the commencement of the story and stop it at the end.
</p>
<p>
Using easyb’s story format, you can sketch out the body of the story as follows (note, the story includes starting and stopping a database):
</p>
<pre><code>
given "a database is up and running", {}
and
given "the database has an initialized data model", {}
and
given "the database_model method is invoked with a dataset", {}
when "a select statement is issued for a value that could
only be present if the database_model call worked", {}
then "the word bellicose should be returned", {}
and
then "shut down the database", {}
</code></pre>
<p>Making the story executable entails adding some logic– in the course of doing so, the story demonstrates how to use the database plug-in (minus the first and last steps, right?)!
</p>
<p>
The first given can be coded as follows (in Groovy, that is):
</p>
<pre><code>
given "a database is up and running", {
Server.main(["-no_system_exit", "true"] as String[])
}
</code></pre>
<p>
The Server instance in the above code is HSQLDB’s <code>org.hsqldb.Server</code> type. This is, by the way, a handy database that is easily controlled programatically and easy to install (it’s a jar file!).
</p>
<p>
The next <code>given</code> is a bit more complicated– the database needs an empty schema– one can’t assume one is present, so the story just creates it. This also happens to validate the story quite nicely– no assumptions are made about the underlying database!
</p>
<pre><code>
and
given "the database has an initalized data model", {
sql = Sql.newInstance("jdbc:hsqldb:hsql://127.0.0.1",
"sa", "", "org.hsqldb.jdbcDriver")
ddl = """DROP TABLE definition IF EXISTS;
DROP TABLE synonym IF EXISTS;
DROP TABLE word IF EXISTS;
CREATE TABLE word (
WORD_ID bigint default '0' NOT NULL,
PART_OF_SPEECH varchar(100) default '' NOT NULL,
SPELLING varchar(100) default '' NOT NULL,
PRIMARY KEY (WORD_ID),
UNIQUE (SPELLING));
CREATE TABLE definition (
DEFINITION_ID bigint default '0' NOT NULL,
DEFINITION varchar(500) NOT NULL,
WORD_ID bigint default '0' NOT NULL,
EXAMPLE_SENTENCE varchar(1000),
FOREIGN KEY (WORD_ID) REFERENCES word(WORD_ID)
ON DELETE CASCADE
ON UPDATE CASCADE,
PRIMARY KEY (DEFINITION_ID));
CREATE TABLE synonym (
SYNONYM_ID bigint default '0' NOT NULL ,
WORD_ID bigint default '0' NOT NULL ,
SPELLING varchar(100) default '' NOT NULL ,
FOREIGN KEY (WORD_ID) REFERENCES word(WORD_ID)
ON DELETE CASCADE
ON UPDATE CASCADE,
PRIMARY KEY (SYNONYM_ID));
commit;"""
sql.execute(ddl);
}
</code></pre>
<p>
The data model here is quite simple– three tables and a bit of GroovySQL to jam it into the database.
</p>
<p>
Next, you need to actually use the plug-in to seed the database with data! The core API of the plug-in is the <code>database_model</code> closure, which takes standard JDBC connection information (URL, user name, driver, etc) and a <code>String</code> representing the dataset. In this case, the story uses Groovy’s <code>MarkupBuilder</code> to to create an XML representation of the data.
</p>
<pre><code>
and
given "the database_model method is invoked with a dataset", {
database_model("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
def writer = new StringWriter();
def builder = new MarkupBuilder(writer);
builder.dataset(){
word(word_id:1, spelling:"bellicose", part_of_speech:"Adjective")
definition(definition_id:10, definition:"demonstrating willingness and \
willingness to fight ",
word_id:1, example_sentence:"The pugnacious youth had no friends left \
to pick on." )
synonym(synonym_id:20, word_id:1, spelling:"belligerent")
synonym(synonym_id:21, word_id:1, spelling:"aggressive")
}
return writer.toString()
}
}
</code></pre>
<p>
Note, the <code>and</code> clauses– in truth they’re noops but they serve to make the story read more nicely. Notice how the <code>MarkupBuilder</code> instance creates data that matches the data model found in the 2nd <code>given</code>. For instance, the word “bellicose” is inserted with an id of 1.
That right there is the heart of the plug-in– inserting data into the database so that a high level story can play out. Now, using easyb, it’s time to validate that the call to <code>database_model</code> worked.
</p>
<p>
Validating the <code>database_model</code> call means querying the database for the data that the <code>database_model</code> call should have inserted– in my case, the story verifies the word bellicose is present!
</p>
<pre><code>
when "a select statement is issued for a value that could
only be present if the database_model call worked", {
value = null
sql.eachRow("select word.spelling from word where word.word_id = 1"){
value = it.spelling
}
}
</code></pre>
<p>
Note how the story still uses GroovySQL to talk to the database. Once the word (stored in the value variable) is obtained, it’s time to verify it is there.
</p>
<pre><code>
then "the word bellicose should be returned", {
value.shouldBe "bellicose"
}
</code></pre>
<p>
Lastly, stopping the database is as easy as sending a shutdown command (via SQL) to the instance of HSQLDB.
</p>
<pre><code>
and
then "shut down the database", {
sql.execute("SHUTDOWN")
}
</code></pre>
</p>
<p>BDD with databases in Java can't get any easier!</p>
<h3></h3>
<p>Plug-in resources:
<ul>
<li><a href="http://www.onjava.com/pub/a/onjava/2004/01/21/dbunit.html">Effective Unit Testing with DbUnit</a>- Curious about DbUnit or how to create DbUnit XML files? Read this article and you'll be set.</li>
</ul>
</p>
</div>
</div>
</div>
<!-- end content -->
<!-- start sidebar -->
<div id="sidebar">
<ul>
<li>
<h2>Overview</h2>
<ul>
<li><a href="./index.html">Home</a></li>
<li><a href="./howtos.html">Stories</a></li>
<li><a href="./howtobb.html">Specifications</a></li>
<li><a href="./download.html">Download</a></li>
</ul>
</li>
<li>
<h2>Details</h2>
<ul>
<li><a href="./running.html">Running easyb</a></li>
<li><a href="./tutorialstack.html">An in-depth tutorial</a></li>
<li><a href="./dsls.html">easyb syntax specification</a></li>
<li><a href="./lic.html">License</a></li>
<li><a href="./source.html">Source code</a></li>
<li><a href="./contact.html">Contact</a></li>
</ul>
</li>
<li>
<h2>Plug-ins</h2>
<ul>
<li><a href="./dbunit.html">DbUnit plug-in</a></li>
</ul>
</li>
<li>
<h2>Resources</h2>
<ul>
<li><a href="http://dannorth.net/introducing-bdd/">Introducing BDD</a> (DanNorth.net)</li>
<li><a href="http://rspec.rubyforge.org/">RSpec</a></li>
<li><a href="http://groovy.codehaus.org/">Groovy</a></li>
<li><a href="http://code.google.com/p/easyb/w/list">easyb wiki</a></li>
<li><a href="./articles.html">Additional resources</a></li>
</ul>
</li>
</ul>
<div style="clear: both;"> </div>
</div>
<!-- end sidebar -->
</div>
<!-- end page -->
<div id="footer">
</div>
</body>
</html>