lemon 0.9.0 → 0.9.1
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.
- data/.ruby +23 -14
- data/.yardopts +6 -0
- data/Config.rb +14 -0
- data/{HISTORY.rdoc → HISTORY.md} +26 -11
- data/LICENSE.txt +27 -0
- data/README.md +42 -28
- data/SPECSHEET.md +314 -0
- data/bin/{lemonade → lemons} +0 -0
- data/lib/lemon.yml +23 -14
- data/lib/lemon/cli.rb +19 -8
- data/lib/lemon/cli/base.rb +50 -20
- data/lib/lemon/cli/generate.rb +51 -16
- data/lib/lemon/cli/lemon.ascii +84 -0
- data/lib/lemon/cli/obrother.rb +35 -0
- data/lib/lemon/cli/scaffold.rb +116 -0
- data/lib/lemon/core_ext.rb +2 -2
- data/lib/lemon/core_ext/module.rb +9 -0
- data/lib/lemon/coverage/analyzer.rb +76 -5
- data/lib/lemon/coverage/cover_unit.rb +38 -14
- data/lib/lemon/coverage/formats/verbose.rb +1 -1
- data/lib/lemon/coverage/generator.rb +196 -0
- data/lib/lemon/coverage/snapshot.rb +16 -16
- data/lib/lemon/coverage/source_parser.rb +103 -37
- data/lib/lemon/ignore_callers.rb +19 -0
- data/lib/lemon/test_case.rb +135 -26
- data/lib/lemon/test_class.rb +16 -3
- data/lib/lemon/test_class_method.rb +58 -0
- data/lib/lemon/test_method.rb +57 -68
- data/lib/lemon/test_module.rb +47 -44
- data/lib/lemon/test_proc.rb +28 -2
- data/lib/lemon/test_scope.rb +14 -0
- data/lib/lemon/test_setup.rb +1 -1
- data/lib/lemon/test_world.rb +7 -0
- data/{work/deprecated/features/support → spec/applique}/ae.rb +0 -0
- data/spec/coverage/{01_complete.rdoc → 01_complete.md} +3 -3
- data/spec/coverage/{02_incomplete.rdoc → 02_incomplete.md} +2 -2
- data/spec/coverage/{03_extensions.rdoc → 03_extensions.md} +2 -2
- data/try/case_scope.rb +19 -0
- metadata +50 -102
- data/.gemspec +0 -152
- data/.gitignore +0 -8
- data/.reap/digest +0 -678
- data/.reap/test.reap +0 -7
- data/Assembly +0 -37
- data/COPYING.rdoc +0 -33
- data/MANIFEST +0 -55
- data/PROFILE +0 -30
- data/Rakefile +0 -23
- data/VERSION +0 -1
- data/lib/lemon/core_ext/omission.rb +0 -18
- data/lib/lemon/generator.rb +0 -149
- data/notes/2010-05-05-coverage.rdoc +0 -47
- data/notes/2010-05-06-files-not-classes.rdoc +0 -19
- data/notes/2010-07-11-acid-testing.rdoc +0 -52
- data/notes/2010-08-02-enforcing-the-unit.md +0 -68
- data/notes/2010-08-03-new-api.md +0 -37
- data/notes/2011-07-07-nailing-down-the-nomenclature.md +0 -6
- data/site/.rsync-filter +0 -8
- data/site/assets/images/cut-lemon.png +0 -0
- data/site/assets/images/forkme.png +0 -0
- data/site/assets/images/github-logo.png +0 -0
- data/site/assets/images/lemon.jpg +0 -0
- data/site/assets/images/lemon.svg +0 -39
- data/site/assets/images/lemons-are-good.png +0 -0
- data/site/assets/images/opensource.png +0 -0
- data/site/assets/images/ruby-logo.png +0 -0
- data/site/assets/images/skin.jpg +0 -0
- data/site/assets/images/skin1.jpg +0 -0
- data/site/assets/images/tap.png +0 -0
- data/site/assets/images/title.png +0 -0
- data/site/assets/styles/class.css +0 -6
- data/site/assets/styles/reset.css +0 -17
- data/site/assets/styles/site.css +0 -33
- data/site/index.html +0 -218
- data/work/deprecated/command/abstract.rb +0 -29
- data/work/deprecated/command/coverage.rb +0 -115
- data/work/deprecated/command/generate.rb +0 -124
- data/work/deprecated/command/test.rb +0 -112
- data/work/deprecated/cucumber.yml +0 -3
- data/work/deprecated/features/coverage.feature +0 -65
- data/work/deprecated/features/generate.feature +0 -66
- data/work/deprecated/features/step_definitions/coverage_steps.rb +0 -1
- data/work/deprecated/features/support/aruba.rb +0 -1
- data/work/deprecated/features/test.feature +0 -67
- data/work/deprecated/model/dsl/advice.rb +0 -78
- data/work/deprecated/model/dsl/subject.rb +0 -40
- data/work/deprecated/model/main.rb +0 -87
- data/work/deprecated/model/test.rb +0 -54
- data/work/deprecated/model/test_base_dsl.rb +0 -88
- data/work/deprecated/model/test_clause.rb +0 -112
- data/work/deprecated/model/test_context.rb +0 -90
- data/work/deprecated/model/test_feature.rb +0 -128
- data/work/deprecated/model/test_scenario.rb +0 -137
- data/work/deprecated/model/test_suite.rb +0 -297
- data/work/deprecated/rake.rb +0 -103
- data/work/deprecated/test/case_coverage_analyzer.rb +0 -25
- data/work/deprecated/test/case_test_case_dsl.rb +0 -46
- data/work/deprecated/test/fixtures/case_complete.rb +0 -25
- data/work/deprecated/test/fixtures/case_inclusion.rb +0 -18
- data/work/deprecated/test/fixtures/case_incomplete.rb +0 -12
- data/work/deprecated/test/fixtures/example.rb +0 -13
- data/work/deprecated/test/fixtures/helper.rb +0 -13
- data/work/deprecated/test/runner +0 -2
- data/work/old-tests/case_example.rb +0 -15
- data/work/old-tests/feature_example.rb +0 -40
- data/work/reference/dsl2.rb +0 -140
- data/work/reference/dynamic_constant_lookup.rb +0 -76
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
2010-08-02 | Enforcing the Unit
|
|
2
|
-
|
|
3
|
-
The current API for creating a Lemon unit testcase looks like this:
|
|
4
|
-
|
|
5
|
-
covers 'someclass'
|
|
6
|
-
|
|
7
|
-
testcase SomeClass do
|
|
8
|
-
|
|
9
|
-
unit :some_method => "does something or another" do
|
|
10
|
-
# ...
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
As it currentlt standa the current design is little more than a means of
|
|
16
|
-
organization, orienting the developer to think in terms of test units.
|
|
17
|
-
What is does not do is enforce the actual testing the the unit referenced.
|
|
18
|
-
We could put any old mess in the unit block and as long as it did not raise
|
|
19
|
-
an exception, it would get a *pass*.
|
|
20
|
-
|
|
21
|
-
Taking some time to consider this in depth, I've concieved of a way in which
|
|
22
|
-
that use of the method could in fact be enforced.
|
|
23
|
-
|
|
24
|
-
covers 'someclass'
|
|
25
|
-
|
|
26
|
-
testcase SomeClass do
|
|
27
|
-
|
|
28
|
-
setup do
|
|
29
|
-
SomeClass.new
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
unit :some_method => "does something or another" do |unit|
|
|
33
|
-
unit.object # object from setup
|
|
34
|
-
unit.call(...) # calls #some_method on unit.object
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
What is intersting about this, beyond that fact that it enforces the use of
|
|
40
|
-
the class or module and method involved, but that it also does so in
|
|
41
|
-
a way naturally suited to mocking --the `unit` delegator could even have
|
|
42
|
-
mocking methods built-in.
|
|
43
|
-
|
|
44
|
-
unit :some_method => "does something or another" do |unit|
|
|
45
|
-
unit.receives.foo(:bar) # object from setup would receive this call
|
|
46
|
-
unit.returns(:baz) # the subsequent #call will return this
|
|
47
|
-
unit.call(...) # calls #some_method on unit.object
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
On the downside this approach limits what can be done in the unit block.
|
|
51
|
-
One _has_ to utilize the object as defined in `setup` and one _has_ to invoke
|
|
52
|
-
the unit method via the `#call` interface. Though, I suppose one could argue
|
|
53
|
-
that these limitations are a good thing, as they help the unit stay narrowly
|
|
54
|
-
focused on that goal at hand.
|
|
55
|
-
|
|
56
|
-
I think this approach is worth considering for a possible furture version.
|
|
57
|
-
Perhaps a "Lemon 2.0". For the time being I believe we can enforce the unit
|
|
58
|
-
without resorting this major API change.
|
|
59
|
-
|
|
60
|
-
The next release of Lemon will temporarily override the unit method on the
|
|
61
|
-
target class for each unit execution. If the unit method gets called within
|
|
62
|
-
the unit block, then it will be noted by the overridden method before passing
|
|
63
|
-
off to the original definition. The approach is perhaps a bit draconian, and
|
|
64
|
-
is certainly only possible thanks to the remarkable dynamicism of Ruby, but
|
|
65
|
-
it should work perfectly well. So now, if the target method is not called within
|
|
66
|
-
the taget block, the unit will raise a Pending exception, regardless of the
|
|
67
|
-
code in the block. Unit Enforced!
|
|
68
|
-
|
data/notes/2010-08-03-new-api.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# 2010-08-03 | A New API
|
|
2
|
-
|
|
3
|
-
Simplified API. There is one main method.
|
|
4
|
-
|
|
5
|
-
unit_test SomeClass, :some_method, "description" do
|
|
6
|
-
# test ...
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
It will be a global method. The block notations would still work, but
|
|
10
|
-
they would simple become wrappers for the main method.
|
|
11
|
-
|
|
12
|
-
testcase SomeClass do
|
|
13
|
-
|
|
14
|
-
unit :some_method, "description" do
|
|
15
|
-
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
If I can make it backward compatible, I may also allow something like:
|
|
21
|
-
|
|
22
|
-
testcase SomeClass do
|
|
23
|
-
|
|
24
|
-
unit :some_method do
|
|
25
|
-
|
|
26
|
-
concern "description" do
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
By using this global method, I should be able to simplify the underlying
|
|
35
|
-
implementation a great deal, which has been major concern about Lemon
|
|
36
|
-
as of late.
|
|
37
|
-
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
# 2011-07-07 | Nailing Down the Nomenclature
|
|
2
|
-
|
|
3
|
-
I have finally settled on `test_class` and `test_module` as thew new toplevel method for defining Lemon test cases. I decided against reusing `test_case` from Citron b/c I determined it is best that these types of test cases not be mixed together, but rather stay cleanly separated.
|
|
4
|
-
|
|
5
|
-
I also decided against the original KO inspired nomenclature of `Test.case`. Though it looks very cool at first glance, in the end it goes against the grain. For instance, would one design an RSpec-stlye nomenclature as `Test.describe`, or a Cucumber-style nomenclature using `Test.feature`? While one could do so, it's completely uneccessry.
|
|
6
|
-
|
data/site/.rsync-filter
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
-
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
3
|
-
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
4
|
-
<svg id="svg1" sodipodi:version="0.32" inkscape:version="0.38.1" width="400.00000pt" height="400.00000pt" sodipodi:docbase="/var/www/html/svg_gallery/svg/fruits" sodipodi:docname="lemon.svg" xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
5
|
-
<defs id="defs3">
|
|
6
|
-
<linearGradient id="linearGradient831">
|
|
7
|
-
<stop style="stop-color: rgb(255, 255, 0); stop-opacity: 1;" offset="0.0000000" id="stop832"/>
|
|
8
|
-
<stop style="stop-color: rgb(255, 227, 0); stop-opacity: 1;" offset="1.0000000" id="stop833"/>
|
|
9
|
-
</linearGradient>
|
|
10
|
-
<radialGradient xlink:href="#linearGradient831" id="radialGradient834" cx="0.33703703" cy="0.28358209" r="0.38183698" fx="0.33703703" fy="0.28358209"/>
|
|
11
|
-
</defs>
|
|
12
|
-
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.3195079" inkscape:cx="120.13018" inkscape:cy="204.09312" inkscape:window-width="910" inkscape:window-height="775" inkscape:window-x="119" inkscape:window-y="24"/>
|
|
13
|
-
<g id="g838">
|
|
14
|
-
<path style="fill: url(#radialGradient834) rgb(0, 0, 0); fill-rule: evenodd; stroke: rgb(0, 0, 0); stroke-width: 10; stroke-linejoin: round; stroke-dasharray: none;" d="M 68.708186,148.12939 C 228.69852,9.5810597 474.45687,146.15839 471.15810,289.65487 C 497.54826,315.22034 467.85933,343.25988 451.36548,350.68211 C 309.51838,525.51691 17.577254,382.02043 34.895796,237.69925 C 12.847026,174.32754 32.421718,155.55162 68.708186,148.12939 z " id="path827" sodipodi:nodetypes="ccccc"/>
|
|
15
|
-
<path style="fill-opacity: 0.133333; fill-rule: evenodd; stroke-width: 1pt;" d="M 44.330330,267.99099 C 65.580330,246.74099 68.080330,411.74099 378.08033,350.49099 C 371.83033,344.24099 338.08033,201.74099 458.08033,249.24099 C 504.95533,263.61599 358.70533,239.55349 410.58033,339.24099 C 418.62433,352.33698 416.20533,352.36599 438.08033,357.99099 C 305.58033,500.49099 46.830330,390.49099 44.330330,267.99099 z " id="path828" sodipodi:nodetypes="cccccc"/>
|
|
16
|
-
<path style="fill: rgb(255, 255, 255); fill-opacity: 0.7; fill-rule: evenodd; stroke-width: 1pt;" d="M 68.080330,155.83295 C 124.36962,90.490990 313.68568,43.977604 438.08033,203.33295 C 395.58033,249.58295 275.58033,49.582958 68.080330,155.83295 z " id="path829" sodipodi:nodetypes="ccc"/>
|
|
17
|
-
<path style="fill: rgb(255, 255, 255); fill-opacity: 0.7; fill-rule: evenodd; stroke-width: 1pt;" d="M 469.33033,295.49099 C 483.64639,312.99099 470.58033,332.99099 460.58033,330.49099 C 381.83033,309.24099 424.33033,287.99099 469.33033,295.49099 z " id="path830" sodipodi:nodetypes="ccc"/>
|
|
18
|
-
</g>
|
|
19
|
-
|
|
20
|
-
<rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
21
|
-
<Work rdf:about="">
|
|
22
|
-
<dc:title>Clipart by Nicu Buculei - pear</dc:title>
|
|
23
|
-
<dc:rights>
|
|
24
|
-
<Agent>
|
|
25
|
-
<dc:title>Nicu Buculei</dc:title>
|
|
26
|
-
</Agent>
|
|
27
|
-
</dc:rights>
|
|
28
|
-
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
|
29
|
-
<license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
|
|
30
|
-
</Work>
|
|
31
|
-
|
|
32
|
-
<License rdf:about="http://web.resource.org/cc/PublicDomain">
|
|
33
|
-
<permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
|
|
34
|
-
<permits rdf:resource="http://web.resource.org/cc/Distribution"/>
|
|
35
|
-
<permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
|
|
36
|
-
</License>
|
|
37
|
-
|
|
38
|
-
</rdf:RDF>
|
|
39
|
-
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/site/assets/images/skin.jpg
DELETED
|
Binary file
|
|
Binary file
|
data/site/assets/images/tap.png
DELETED
|
Binary file
|
|
Binary file
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
html { font-family: sans-serif; font-size: 16px; color: black; }
|
|
2
|
-
body { padding: 0; margin: 0; font-family: sans-serif; font-size: 12px; background: #fff; }
|
|
3
|
-
|
|
4
|
-
h1 { font-size: 90px; margin: 20px; }
|
|
5
|
-
|
|
6
|
-
p { font-size: 110%; text-align: justify; margin: 20px 0; line-height: 150%; }
|
|
7
|
-
|
|
8
|
-
a { text-decoration: none; font-size: 100%; }
|
|
9
|
-
a:hover { text-decoration: underline; }
|
|
10
|
-
|
|
11
|
-
ul { margin: 0 auto; list-style-type: none; width: 300px; }
|
|
12
|
-
li { float: left; padding: 10px; text-align: center; }
|
|
13
|
-
|
|
14
|
-
pre { font-size: 130%; padding: 10px 0 0 0; -moz-border-radius: 10px; font-family: courier, monospace; color: #000; }
|
|
15
|
-
code { font-family: courier, monospace; }
|
|
16
|
-
|
|
17
|
-
img { border: none; }
|
data/site/assets/styles/site.css
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
h1 { font-family: times; font-size: 400%; margin: 20px 0; color: #f7d901; }
|
|
2
|
-
h2 { font-size: 220%; margin-top: 30px; color: #444; }
|
|
3
|
-
h3 { font-size: 190%; color: orange; }
|
|
4
|
-
|
|
5
|
-
p { color: #222; font-weight: normal; font-size: 120%; }
|
|
6
|
-
a { color: #262; }
|
|
7
|
-
a:hover { text-decoration: underline; }
|
|
8
|
-
|
|
9
|
-
pre { background: #ffffff; -moz-border-radius: 10px; line-height: 140%; }
|
|
10
|
-
code { color: #222; font-weight: bold; }
|
|
11
|
-
tt { color: #222; font-weight: bold; }
|
|
12
|
-
|
|
13
|
-
#nav { padding: 0 30px 20px 60px; text-align: left; color: pink; float: right; }
|
|
14
|
-
#nav a { font-size: 160%; font-weight: bold; line-height: 150%; }
|
|
15
|
-
#nav a:hover { color: #0C0; text-decoration: none; }
|
|
16
|
-
|
|
17
|
-
#header { height: 250px; text-align: left; }
|
|
18
|
-
#header h1 { font-size: 100px; padding: 40px 0 0 0; color: #f7d901; margin-left: -10px; }
|
|
19
|
-
|
|
20
|
-
#main { color: white; padding: 20px 0 30px 0; background: url(../images/skin.jpg) #f7e931; }
|
|
21
|
-
#main p { font-weight: bold; font-family: times; font-size: 150%; }
|
|
22
|
-
#main h2 { color: #333333; }
|
|
23
|
-
#main h3 { color: #333333; }
|
|
24
|
-
|
|
25
|
-
#footer { margin-top: 40px; padding: 40px 0; text-align: center; background: url(../images/skin.jpg) #f7e931; }
|
|
26
|
-
#footer .copyright { padding-top: 0; }
|
|
27
|
-
#footer .copyright p { color: #222; font-weight: normal; font-size: 80%; line-height: 150%; }
|
|
28
|
-
|
|
29
|
-
#forkme {
|
|
30
|
-
position: absolute;
|
|
31
|
-
top: 0; right: 0;
|
|
32
|
-
width: 150px;
|
|
33
|
-
}
|
data/site/index.html
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
<html>
|
|
2
|
-
<head>
|
|
3
|
-
<title>Lemon</title>
|
|
4
|
-
<link href="assets/styles/reset.css" rel="stylesheet" type="text/css"/>
|
|
5
|
-
<link href="assets/styles/class.css" rel="stylesheet" type="text/css"/>
|
|
6
|
-
<link href="assets/styles/site.css" rel="stylesheet" type="text/css"/>
|
|
7
|
-
<link href="assets/images/lemon.jpg" rel="shortcut icon"/>
|
|
8
|
-
|
|
9
|
-
<!-- syntax highlighing -->
|
|
10
|
-
<script src="http://rubyworks.github.com/assets/includes/shjs/sh_main.min.js"></script>
|
|
11
|
-
<script src="http://rubyworks.github.com/assets/includes/shjs/lang/sh_ruby.min.js"></script>
|
|
12
|
-
<script src="http://rubyworks.github.com/assets/includes/shjs/lang/sh_sh.min.js"></script>
|
|
13
|
-
<link href="http://rubyworks.github.com/assets/includes/shjs/css/sh_acid.min.css" rel="stylesheet" type="text/css" />
|
|
14
|
-
</head>
|
|
15
|
-
<body onload="sh_highlightDocument();">
|
|
16
|
-
|
|
17
|
-
<div id="forkme">
|
|
18
|
-
<a href="http://github.com/rubyworks/lemon"><img src="assets/images/forkme.png" /></a>
|
|
19
|
-
</div>
|
|
20
|
-
|
|
21
|
-
<div id="header">
|
|
22
|
-
<div class="page">
|
|
23
|
-
<img src="assets/images/cut-lemon.png" height="200px" align="right" style="padding-top: 15px;"/>
|
|
24
|
-
<h1><img src="assets/images/title.png"/></h1>
|
|
25
|
-
<h2>Pucker-Strength Unit Testing</h2>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<div id="main" class="bordered">
|
|
30
|
-
<div class="page">
|
|
31
|
-
|
|
32
|
-
<div id="nav">
|
|
33
|
-
<!-- <a href="guide/doc.en/index.html">English Manual</a> · -->
|
|
34
|
-
<a href="http://wiki.github.com/rubyworks/lemon">Wiki</a> <br/>
|
|
35
|
-
<a href="http://rubydoc.info/gems/lemon/frames">API</a> <br/>
|
|
36
|
-
<a href="http://googlegroups.com/group/rubyworks-mailinglist">Email</a> <br/>
|
|
37
|
-
<a href="http://github.com/rubyworks/lemon/issues">Issue</a> <br/>
|
|
38
|
-
<a href="http://github.com/rubyworks/lemon">Code</a>
|
|
39
|
-
</div>
|
|
40
|
-
|
|
41
|
-
<p>Lemon is a unit testing framework which enforces highly formal
|
|
42
|
-
case-to-class and unit-to-method test construction.
|
|
43
|
-
This strict approach is arguably a more proper technique for unit
|
|
44
|
-
testing because it helps focus concern on individual units of
|
|
45
|
-
behavior and thus helps promote good test coverage. This is unlike
|
|
46
|
-
functional and integration testing which rightly focus on more
|
|
47
|
-
holistic issues.</p>
|
|
48
|
-
|
|
49
|
-
<!--
|
|
50
|
-
<h3>Writing Tests</h3>
|
|
51
|
-
|
|
52
|
-
<p>Let's say we have a library that consists of the class <code>HelloWorld</code>
|
|
53
|
-
with method <code>#to_s</code>:<p>
|
|
54
|
-
|
|
55
|
-
<pre class="sh_ruby">
|
|
56
|
-
class HelloWorld
|
|
57
|
-
def to_s
|
|
58
|
-
"Hello, World!"
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
</pre>
|
|
62
|
-
|
|
63
|
-
<p>We would write a Lemon test case along the following lines:</p>
|
|
64
|
-
|
|
65
|
-
<pre class="sh_ruby">
|
|
66
|
-
TestCase HelloWorld do
|
|
67
|
-
Concern "String output works as expected."
|
|
68
|
-
|
|
69
|
-
Unit :to_s do
|
|
70
|
-
Test "returns a string" do
|
|
71
|
-
HelloWorld.new.to_s.assert.is_a?(String)
|
|
72
|
-
end
|
|
73
|
-
Test "returns the world famous phrase" do
|
|
74
|
-
HelloWorld.new.to_s.assert == "Hello, World!"
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
</pre>
|
|
79
|
-
|
|
80
|
-
<p>Clearly an overly simplistic example, but it demonstrates well enough the overall design of Lemon
|
|
81
|
-
tests. Notice that the <code>#TestCase</code> method references a class (this can also be a module) and the units each
|
|
82
|
-
refer to a method of the class.</p>
|
|
83
|
-
|
|
84
|
-
<p>Lemon uses the <a href="http://rubyworks.github.com/ae">Assertive Expressive</a>
|
|
85
|
-
assertions framework. This is the same verstile framework used by <a href="http://rubyworks.github.com/qed">Q.E.D.</a>.
|
|
86
|
-
By default Lemon test support the standard <code>#assert</code> and <code>#expect</code> assertion methods.
|
|
87
|
-
If you wish to use subjunctive terms, either <code>#should</code> or <code>#must</code>, you can load these
|
|
88
|
-
via a helper script (eg. <code>require 'ae/should'</code>).</p>
|
|
89
|
-
|
|
90
|
-
<h3>Running Tests</h3>
|
|
91
|
-
|
|
92
|
-
<p>The <tt>lemon</tt> command-line tool is used to run tests. Simply provide the name of the test files as arguments:</p>
|
|
93
|
-
|
|
94
|
-
<pre class="sh_sh">
|
|
95
|
-
> lemon test/cases/*.rb
|
|
96
|
-
</pre>
|
|
97
|
-
|
|
98
|
-
<p>By default the <tt>lemon</tt> command outputs the traditional dot-progress format. The <tt>--verbose</tt>
|
|
99
|
-
or <tt>-v</tt> option provides additional information about each unit test and concern
|
|
100
|
-
as they are executed.</p>
|
|
101
|
-
|
|
102
|
-
<h3>Test Coverage</h3>
|
|
103
|
-
|
|
104
|
-
<p>The <tt>lemon</tt> command can also be used to check test coverage. For this use the <tt>--coverage</tt>
|
|
105
|
-
or <tt>-c</tt> option.</p>
|
|
106
|
-
|
|
107
|
-
<pre class="sh_sh">
|
|
108
|
-
> lemon -c test/cases/*.rb
|
|
109
|
-
</pre>
|
|
110
|
-
|
|
111
|
-
<p>To enusre only the code you are interested in is checked, you can either use <tt>-r</tt> to pre-require
|
|
112
|
-
support libraries you wish not to include in the output. Or more conveniently, supply specific namespaces
|
|
113
|
-
to include via the <tt>--namespace</tt> or <tt>-n</tt> option.
|
|
114
|
-
|
|
115
|
-
<pre class="sh_sh">
|
|
116
|
-
> lemon -c -n HelloWorld test/cases/*.rb
|
|
117
|
-
</pre>
|
|
118
|
-
|
|
119
|
-
<p>For more information on Lemon and how to use it please see the Lemon <a href="http://wiki.github.com/rubyworks/lemon">Wiki</a>.</p>
|
|
120
|
-
|
|
121
|
-
<h2>Development</h2>
|
|
122
|
-
|
|
123
|
-
<p>Lemon is a RubyWorks project. Development is hosted on GitHub at:</p>
|
|
124
|
-
|
|
125
|
-
<pre>
|
|
126
|
-
<a href="http://github.com/rubyworks/lemon">http://github.com/rubyworks/lemon</a>
|
|
127
|
-
</pre>
|
|
128
|
-
|
|
129
|
-
<h3>License</h3>
|
|
130
|
-
|
|
131
|
-
<p>Lemon is an open-source project licensed under the terms of <b>Lesser General Public License</b>.</p>
|
|
132
|
-
|
|
133
|
-
-->
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
|
|
137
|
-
<div>
|
|
138
|
-
<div class="page">
|
|
139
|
-
<h3>Example</h3>
|
|
140
|
-
|
|
141
|
-
<p>To give you a taste of what a lemon testcase looks like, let's say we have a library
|
|
142
|
-
that consists of the class <code>HelloWorld</code> with method <code>#to_s</code>:<p>
|
|
143
|
-
|
|
144
|
-
<pre class="sh_ruby">
|
|
145
|
-
class HelloWorld
|
|
146
|
-
def to_s
|
|
147
|
-
"Hello, World!"
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
</pre>
|
|
151
|
-
|
|
152
|
-
<p>We would write a Lemon test case along the following lines:</p>
|
|
153
|
-
|
|
154
|
-
<pre class="sh_ruby">
|
|
155
|
-
TestCase HelloWorld do
|
|
156
|
-
Concern "String output works as expected."
|
|
157
|
-
|
|
158
|
-
Unit :to_s => "returns a string" do
|
|
159
|
-
HelloWorld.new.to_s.assert.is_a?(String)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
Unit :to_s => "returns a 13 character phrase" do
|
|
163
|
-
HelloWorld.new.to_s.size.assert == 13
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
</pre>
|
|
167
|
-
|
|
168
|
-
<p>A silly example to be sure, but one we can all easily understand.</p>
|
|
169
|
-
|
|
170
|
-
</div>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
<div id="footer" class="bordered">
|
|
174
|
-
<div class="page">
|
|
175
|
-
<script type="text/javascript"><!--
|
|
176
|
-
google_ad_client = "ca-pub-1126154564663472";
|
|
177
|
-
/* RUBYWORKS 09-10-02 728x90 */
|
|
178
|
-
google_ad_slot = "0788888658";
|
|
179
|
-
google_ad_width = 728;
|
|
180
|
-
google_ad_height = 90;
|
|
181
|
-
//-->
|
|
182
|
-
</script>
|
|
183
|
-
<script type="text/javascript"
|
|
184
|
-
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
|
185
|
-
</script>
|
|
186
|
-
|
|
187
|
-
<br/><br/><br/>
|
|
188
|
-
|
|
189
|
-
<div class="copyright" width="100%">
|
|
190
|
-
<a href="http://rubyworks.github.com/">
|
|
191
|
-
<img src="assets/images/ruby-logo.png" height="110px" align="left" style="margin: 0 5px; padding: 0 10px" />
|
|
192
|
-
</a>
|
|
193
|
-
<a href="http://www.apache.org/licenses/LICENSE-2.0.html">
|
|
194
|
-
<img src="assets/images/opensource.png" height="120px" align="left" style="padding: 0 10px;" />
|
|
195
|
-
</a>
|
|
196
|
-
<a href="github.com/rubyworks/lemon">
|
|
197
|
-
<img src="assets/images/github-logo.png" height="115px" align="left" style="margin: 0; padding: 0 10px;" />
|
|
198
|
-
</a>
|
|
199
|
-
<a href="http://testanything.org/wiki/index.php/Main_Page">
|
|
200
|
-
<img src="assets/images/tap.png" height="113px" align="left" style="margin: 0; padding: 0 20px;" />
|
|
201
|
-
</a>
|
|
202
|
-
<a href="">
|
|
203
|
-
<img src="assets/images/lemons-are-good.png" height="117px" align="left" style="margin: 0; padding: 0 10px;" />
|
|
204
|
-
</a>
|
|
205
|
-
</div>
|
|
206
|
-
|
|
207
|
-
<br style="clear: both;" />
|
|
208
|
-
|
|
209
|
-
<div style="margin-top: 30px;">
|
|
210
|
-
<b>Lemon</b>, Copyright © 2009 Thomas Sawyer ·
|
|
211
|
-
<b>Contact:</b> transfire @ gmail.com
|
|
212
|
-
</div>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
|
|
216
|
-
</body>
|
|
217
|
-
</html>
|
|
218
|
-
|