-
Notifications
You must be signed in to change notification settings - Fork 0
/
dsls.html
378 lines (299 loc) · 11.5 KB
/
dsls.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
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
<!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">Domain Specific Language specifications of easyb</h2>
<div class="entry">
<p>A <a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language">Domain Specific Language</a> (or DSL, which is much easier to write and say) is a programming language designed for a specific task-- that is, it's a special purpose syntax. For example, <a href="http://ant.apache.org/">Ant</a>'s XML build files are DSLs for building software. </p>
<p>Not surprisingly, easyb makes heavy use of DSLs for defining a behavior focused language-- in this case, easyb actually has two main DSLs-- one for defining stories and another for defining basic RSpec-like behaviors. </p>
<h2>Story DSL</h2>
<p>Stories in easyb are files which contain scenarios; consequently, by convention, easyb story file names end in <code>.story</code>. For example, if you have a create account story, the file would be <code>CreateAccount.story</code>.</p>
<p>Story files have 0..N <code>scenario</code>s in them. Scenarios then have a mixture of 0..N <code>given</code>s, <code>when</code>s, and <code>then</code>s, with <code>and</code>s linking them (if you desire).</p>
<p>Consequently, the definition of an easyb scenario is:</p>
<pre><code>scenario "text", {
given "text", {}
when "text", {}
then "text", {}
}
</code></pre>
<p>The body of any phrase (<code>given</code>, <code>when</code>, <code>then</code>) is optional as well (meaning <code>given "text"</code> without the trailing <code>, {}</code> implementation code is completely valid syntax)-- easyb will mark such an event as a pending one.</p>
<p>Remember, you can have as many <code>given</code>s, <code>when</code>s, and <code>then</code>s, with <code>and</code>s linking them; therefore, the DSL supports</p>
<pre><code>scenario "text",{
given "text", {}
and
given "text", {}
when "text", {}
then "text", {}
and
then "text", {}
}
</code></pre>
<p>The DSL also permits chaining <code>and</code>s -- for instance, after a <code>given</code>, the next <code>and</code> is assumed to also imply <code>given</code>. The same would be true of any <code>when</code>'s or <code>then</code>'s that had proceeding <code>and</code>'s. Accordingly, the following syntax is also valid:</p>
<pre><code>scenario "text",{
given "text", {}
and "given text", {}
when "text", {}
then "text", {}
and "then text", {}
}
</code></pre>
<p>Don't forget that <code>when</code>s are not required. Accordingly, the following variation works too.</p>
<pre><code>scenario "text", {
given "text", {}
then "text", {}
}
</code></pre>
<h3>Further documenting stories</h3>
<p>easyb supports capturing additional information regarding stories, such as a story's description and some detail regarding the features, benefits, and roles of a persona related to a story. For instance, the DSL supports a description syntax that takes a String value -- single quote or Groovy's triple quote trick. </p>
<pre><code>description "some description"
scenario "text"
</code></pre>
or
<pre><code>description """some long description that requires
multiple lines, etc
"""
scenario "text"
</code></pre>
<p>What's more, you can provide additional details of a story via the <code>narrative</code> syntax:</p>
<pre><code>description "text"
narrative "description", {
as_a "role"
i_want "feature"
so_that "benefit"
}
scenario "text"
</code></pre>
<p>Both the <code>narrative</code> and <code>description</code> keywords are optional and they don't have to be used together-- i.e. you can use the <code>narrative</code> one without providing a <code>description</code>. These aspects will be captured in the output (i.e. story report) of an easyb run too.</p>
<h3>Running non-implemented stories</h3>
<p>easyb permits running stories that are not implemented yet-- thus, you can execute your documentation and see which stories are still <i>pending</i>. For instance, the closure (i.e. <code>{}</code>'s following a <code>scenario</code> or <code>given</code>/<code>when</code>/<code>then</code> phrase) is optional. Thus, the following story with two scenarios could be run:</p>
<pre><code>
scenario "this is a pending scenario", {
given "something"
when "something is done"
then "there is a way to handle it"
}
scenario "this is also pending"
</code></pre>
<p>Both scenarios will be executed and easyb will consider them pending and thus report that-- in this case, easyb will have run one story with two scenarios, each in a pending state:</p>
<pre><code>
Running pending example story (PendingExample.story)
Scenarios run: 2, Failures: 0, Pending: 2, Time Elapsed: 0.444 sec
2 total behaviors run (including 2 pending behaviors) with no failures
</code></pre>
<h2>Behavior DSL</h2>
<p>easyb supports an RSpec-like DSL for defining simple behaviors. Along with supporting <code>it</code>, you can create a fixture using the <code>before</code> syntax.
<pre><code>
before "", {}
it "", {}
</code></pre>
</p>
<p>
Of course, you can have as many <code>it</code>'s as you'd like. The contract of easyb is that the code in <code>before</code> will be run before <i>each</i> <code>it</code>. If you'd only like a one time setup, then place that logic above the first <code>it</code> and that code will be run <i>once</i>.
</p>
<h2>easyb should syntax</h2>
<p>easyb auto-magically wires all objects within the confines of a story or behavior to respond to a series of <code>should</code> calls. That means you can easily verify the state of things by writing phrases like :</p>
<pre><code>
var.shouldNotBe null
and
var.length().shouldEqual 6
</code></pre>
<p>Currently, easyb supports the following phrases, where the phrase is attached to <i>any</i> object and the phrase takes a value to be verified against. </p>
<pre><code>
shouldBe
shouldEqual
shouldBeEqual
shouldBeEqualTo
</code></pre>
<p>easyb supports the negative of the above phrases as follows (same rules apply as above):</p>
<pre><code>
shouldNotBe
shouldNotEqual
shouldntBe
shouldntEqual
</code></pre>
<p>What's more, easyb allows you to verify object types, such as <code>value.shouldBeAn Integer</code>. Both positive and negative phrases are supported:</p>
<pre><code>
shouldBeA
shouldBeAn
shouldNotBeA
shouldNotBeAn
</code></pre>
<p>You can compare values with the <code>should</code> syntax as well:</p>
<pre><code>
shouldBeGreaterThan
shouldBeLessThan
</code></pre>
<p>Lastly, easyb supports verifying objects in a collection or properties of objects via the <code>shouldHave</code> method.</p>
<pre><code>
shouldHave
shouldNotHave
</code></pre>
<p>To see all of the above verifications in action, look at some of the stories and behaviors in easyb's source.</p>
<h2>easyb ensure syntax</h2>
<p>easyb has an expressive <code>ensure</code> syntax that is similar in nature to Java's <code>assert</code> but a bit more readable.</p>
<p>Whenever you want to verify the state of a particular object, use easyb's <code>ensure</code> closure, which supports the following syntax: </p>
<pre><code>
ensure(object or expression){
expression
}
</code></pre>
<p>That is, the <code>ensure</code> closure takes a value, which could be a normal object or an expression itself. For instance, you could ensure that some value was <code>false</code> by writing:</p>
<pre><code>
ensure(!value)
</code></pre>
<p>You could alternatively write:</p>
<pre><code>
ensure(value){
isFalse
}
</code></pre>
<p>As you can see, inside the <code>ensure</code> clause you can do some cool things, such as:</p>
<pre><code>
isNull
isNotNull
isA<class type>
isEqualTo(value)
isEqualTo<value>
isNotEqualTo<value>
isTrue
isFalse
</code></pre>
<p>You can chain clauses too:</p>
<pre><code>
ensure(value){
isNotNull
and
isAString
}
</code></pre>
<p>The <code>ensure</code> DSL is quite forgiving-- for instance, check out these code examples:</p>
<pre><code>
mVal = "Test"
ensure(mVal){
isEqualToTest
and
isEqualTo "Test"
}
</code></pre>
<pre><code>
mVal = 23
ensure(mVal){
isEqualTo23
and
isEqualTo 23
}
</code></pre>
<p>You can work with collections and even ensure fields on objects too:</p>
<pre><code>
ensure("test"){
contains("est")
}
</code></pre>
<pre><code>
ensure([1,2,3]){
contains(3)
and
contains([2,3])
}
</code></pre>
<pre><code>
def person = new Person("Andy", 11)
ensure(person){
contains(firstName:"Andy")
and
contains(age:11)
}
</code></pre>
<p>Flexibility is key, hence you can use <code>has</code> instead of <code>contains</code> if you wish:</p>
<pre><code>
def person = new Person("Jill", 11)
ensure(person){
has([firstName:"Jill", age:11])
}
</code></pre>
<p>You can also check that an exception is thrown using the <code>ensureThrows</code> variant of the <code>ensure</code> closure:</p>
<pre><code>
ensureThrows(RuntimeException) {
throw new RuntimeException("Test")
}
</code></pre>
</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>