lemon 0.8.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{lemon.gemspec → .gemspec} +0 -0
- data/.ruby +4 -11
- data/Assembly +5 -11
- data/HISTORY.rdoc +31 -0
- data/MANIFEST +45 -55
- data/PROFILE +6 -6
- data/README.md +113 -0
- data/Rakefile +12 -3
- data/VERSION +1 -1
- data/bin/lemonade +8 -0
- data/lib/lemon.rb +52 -2
- data/lib/lemon.yml +4 -11
- data/lib/lemon/{model/ae.rb → ae.rb} +0 -0
- data/lib/lemon/cli.rb +28 -279
- data/lib/lemon/cli/base.rb +139 -0
- data/lib/lemon/cli/coverage.rb +52 -0
- data/lib/lemon/cli/generate.rb +51 -0
- data/lib/lemon/cli/test.rb +50 -0
- data/lib/lemon/core_ext.rb +7 -0
- data/lib/lemon/core_ext/kernel.rb +20 -0
- data/lib/lemon/core_ext/omission.rb +18 -0
- data/lib/lemon/{controller/coverage_analyzer.rb → coverage/analyzer.rb} +41 -19
- data/lib/lemon/{model → coverage}/cover_unit.rb +0 -0
- data/lib/lemon/{view/cover_reports → coverage/formats}/abstract.rb +0 -0
- data/lib/lemon/{view/cover_reports → coverage/formats}/compact.rb +1 -1
- data/lib/lemon/{view/cover_reports → coverage/formats}/outline.rb +1 -1
- data/lib/lemon/{view/cover_reports → coverage/formats}/verbose.rb +1 -1
- data/lib/lemon/{view/cover_reports → coverage/formats}/yaml.rb +1 -1
- data/lib/lemon/{model → coverage}/snapshot.rb +0 -0
- data/lib/lemon/{model → coverage}/source_parser.rb +0 -0
- data/lib/lemon/{controller/scaffold_generator.rb → generator.rb} +53 -14
- data/lib/lemon/test_advice.rb +63 -0
- data/lib/lemon/test_case.rb +270 -0
- data/lib/lemon/test_class.rb +28 -0
- data/lib/lemon/test_method.rb +207 -0
- data/lib/lemon/test_module.rb +114 -0
- data/lib/lemon/test_proc.rb +140 -0
- data/lib/lemon/test_setup.rb +54 -0
- data/lib/lemon/test_world.rb +9 -0
- data/notes/{2010-05-06-files_not_classes.rdoc → 2010-05-06-files-not-classes.rdoc} +0 -0
- data/notes/{2010-07-11-acid_testing.rdoc → 2010-07-11-acid-testing.rdoc} +0 -0
- data/notes/2011-07-07-nailing-down-the-nomenclature.md +6 -0
- data/site/index.html +7 -6
- data/{qed → spec}/applique/fs.rb +0 -0
- data/{qed → spec}/coverage/01_complete.rdoc +26 -16
- data/{qed → spec}/coverage/02_incomplete.rdoc +10 -7
- data/{qed → spec}/coverage/03_extensions.rdoc +10 -6
- data/spec/coverage/applique/lemon.rb +1 -0
- data/try/.test +8 -0
- data/try/case_error.rb +18 -0
- data/try/case_fail.rb +19 -0
- data/try/case_pass.rb +42 -0
- data/try/case_pending.rb +18 -0
- data/try/case_singleton.rb +18 -0
- data/try/case_untested.rb +14 -0
- data/try/fixtures/calculator.rb +15 -0
- data/{demo/fixture → try/fixtures}/example-use.rb +0 -0
- data/{demo/fixture → try/fixtures}/example.rb +0 -0
- data/try/helpers/loadpath.rb +1 -0
- data/{.config → work/deprecated}/cucumber.yml +0 -0
- data/{features → work/deprecated/features}/coverage.feature +0 -0
- data/{features → work/deprecated/features}/generate.feature +0 -0
- data/{features → work/deprecated/features}/step_definitions/coverage_steps.rb +0 -0
- data/{features → work/deprecated/features}/support/ae.rb +0 -0
- data/{features → work/deprecated/features}/support/aruba.rb +0 -0
- data/{features → work/deprecated/features}/test.feature +0 -0
- data/work/deprecated/model/dsl/advice.rb +78 -0
- data/work/deprecated/model/dsl/subject.rb +40 -0
- data/{lib/lemon → work/deprecated}/model/main.rb +40 -29
- data/work/deprecated/model/test.rb +54 -0
- data/work/deprecated/model/test_base_dsl.rb +88 -0
- data/work/deprecated/model/test_clause.rb +112 -0
- data/{lib/lemon → work/deprecated}/model/test_context.rb +24 -24
- data/work/deprecated/model/test_feature.rb +128 -0
- data/work/deprecated/model/test_scenario.rb +137 -0
- data/{lib/lemon → work/deprecated}/model/test_suite.rb +113 -32
- data/work/deprecated/rake.rb +103 -0
- data/{test → work/deprecated/test}/case_coverage_analyzer.rb +0 -0
- data/{test → work/deprecated/test}/case_test_case_dsl.rb +2 -2
- data/{test → work/deprecated/test}/fixtures/case_complete.rb +0 -0
- data/{test → work/deprecated/test}/fixtures/case_inclusion.rb +0 -0
- data/{test → work/deprecated/test}/fixtures/case_incomplete.rb +0 -0
- data/{test → work/deprecated/test}/fixtures/example.rb +0 -0
- data/{test → work/deprecated/test}/fixtures/helper.rb +0 -0
- data/{test → work/deprecated/test}/runner +0 -0
- data/work/old-tests/case_example.rb +15 -0
- data/work/old-tests/feature_example.rb +40 -0
- data/work/reference/dsl2.rb +4 -0
- metadata +101 -98
- data/README.rdoc +0 -103
- data/bin/lemon +0 -4
- data/demo/case_example_error.rb +0 -10
- data/demo/case_example_fail.rb +0 -15
- data/demo/case_example_pass.rb +0 -32
- data/demo/case_example_pending.rb +0 -14
- data/demo/case_example_untested.rb +0 -10
- data/lib/lemon/controller/test_runner.rb +0 -299
- data/lib/lemon/model/pending.rb +0 -10
- data/lib/lemon/model/test_case.rb +0 -305
- data/lib/lemon/model/test_unit.rb +0 -147
- data/lib/lemon/view/test_reports/abstract.rb +0 -256
- data/lib/lemon/view/test_reports/dotprogress.rb +0 -73
- data/lib/lemon/view/test_reports/html.rb +0 -146
- data/lib/lemon/view/test_reports/outline.rb +0 -118
- data/lib/lemon/view/test_reports/summary.rb +0 -131
- data/lib/lemon/view/test_reports/tap.rb +0 -49
- data/lib/lemon/view/test_reports/tapj.rb +0 -130
- data/lib/lemon/view/test_reports/tapy.rb +0 -141
- data/lib/lemon/view/test_reports/verbose.rb +0 -197
- data/work/sandbox/lib/sample.rb +0 -13
- data/work/sandbox/test/sample_case.rb +0 -12
- data/work/trash/example-cover.rb +0 -5
- data/work/trash/example.rb +0 -16
@@ -0,0 +1,114 @@
|
|
1
|
+
module Lemon
|
2
|
+
|
3
|
+
require 'lemon/test_case'
|
4
|
+
require 'lemon/test_method'
|
5
|
+
|
6
|
+
# The nomenclature of a TestModule limts the focus of testing
|
7
|
+
# the methods of a module.
|
8
|
+
#
|
9
|
+
class TestModule < TestCase
|
10
|
+
|
11
|
+
# New unit test.
|
12
|
+
def initialize(settings={}, &block)
|
13
|
+
@tested = false
|
14
|
+
super(settings)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Make sure the target is a module.
|
18
|
+
def validate_settings
|
19
|
+
raise "#{@target} is not a module" unless Module === @target
|
20
|
+
end
|
21
|
+
|
22
|
+
# The type of test case.
|
23
|
+
def type
|
24
|
+
'Module'
|
25
|
+
end
|
26
|
+
|
27
|
+
# Gives the name of the target module.
|
28
|
+
def to_s
|
29
|
+
target.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
# Evaluation scope for TestModule.
|
33
|
+
class Scope < TestCase::Scope
|
34
|
+
|
35
|
+
# Define a method/unit subcase for the class/module testcase.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# unit :puts do
|
39
|
+
# test "print message with new line to stdout" do
|
40
|
+
# puts "Hello"
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
def unit(method, &block)
|
45
|
+
meth = TestMethod.new(
|
46
|
+
:context => @_testcase,
|
47
|
+
:setup => @_setup,
|
48
|
+
:skip => @_skip,
|
49
|
+
:target => method.to_sym,
|
50
|
+
:function => false,
|
51
|
+
&block
|
52
|
+
)
|
53
|
+
@_testcase.tests << meth
|
54
|
+
meth
|
55
|
+
end
|
56
|
+
alias :Unit :unit
|
57
|
+
|
58
|
+
# More specific nomencalture for `#unit`.
|
59
|
+
alias :method :unit
|
60
|
+
alias :Method :unit
|
61
|
+
|
62
|
+
# Define a class-method unit test for this case.
|
63
|
+
#
|
64
|
+
def class_unit(method, &block)
|
65
|
+
meth = TestMethod.new(
|
66
|
+
:context => @_testcase,
|
67
|
+
:setup => @_setup,
|
68
|
+
:skip => @_skip,
|
69
|
+
:target => method.to_sym,
|
70
|
+
:function => true,
|
71
|
+
&block
|
72
|
+
)
|
73
|
+
@_testcase.tests << meth
|
74
|
+
meth
|
75
|
+
end
|
76
|
+
alias :ClassUnit :class_unit
|
77
|
+
|
78
|
+
# More specific nomencalture for `#class_unit`.
|
79
|
+
alias :class_method :class_unit
|
80
|
+
alias :ClassMethod :class_unit
|
81
|
+
|
82
|
+
# Alternate nomenclature for class_unit.
|
83
|
+
alias :Function :ClassMethod
|
84
|
+
alias :function :ClassMethod
|
85
|
+
|
86
|
+
#--
|
87
|
+
# TODO: Allow sub-cases?
|
88
|
+
#++
|
89
|
+
|
90
|
+
# Create a subcase of module testcase.
|
91
|
+
def context(label, &block)
|
92
|
+
@_testcase.tests << TestModule.new(
|
93
|
+
:context => @_testcase,
|
94
|
+
:target => @_testcase.target,
|
95
|
+
:setup => @_setup,
|
96
|
+
:skip => @_skip,
|
97
|
+
:label => label,
|
98
|
+
&block
|
99
|
+
)
|
100
|
+
end
|
101
|
+
alias :Context :context
|
102
|
+
|
103
|
+
#
|
104
|
+
def skip(reason=true, &block)
|
105
|
+
@_skip = reason
|
106
|
+
block.call
|
107
|
+
@_skip = nil
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Lemon
|
2
|
+
|
3
|
+
# Test procedure.
|
4
|
+
#
|
5
|
+
class TestProc
|
6
|
+
|
7
|
+
# New test procedure.
|
8
|
+
#
|
9
|
+
def initialize(settings={}, &procedure)
|
10
|
+
@context = settings[:context]
|
11
|
+
@setup = settings[:setup]
|
12
|
+
@label = settings[:label]
|
13
|
+
@skip = settings[:skip]
|
14
|
+
|
15
|
+
@procedure = procedure
|
16
|
+
|
17
|
+
@tested = false
|
18
|
+
end
|
19
|
+
|
20
|
+
public
|
21
|
+
|
22
|
+
# The parent case to which this test belongs.
|
23
|
+
attr :context
|
24
|
+
|
25
|
+
# Setup and teardown procedures.
|
26
|
+
attr :setup
|
27
|
+
|
28
|
+
# Description of test.
|
29
|
+
attr :label
|
30
|
+
|
31
|
+
# Test procedure, in which test assertions should be made.
|
32
|
+
attr :procedure
|
33
|
+
|
34
|
+
#
|
35
|
+
#attr :caller
|
36
|
+
|
37
|
+
# Target method of context.
|
38
|
+
def target
|
39
|
+
context.target
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
attr_accessor :skip
|
44
|
+
|
45
|
+
# Don't run test?
|
46
|
+
def skip?
|
47
|
+
@skip
|
48
|
+
end
|
49
|
+
|
50
|
+
# Has this test been executed?
|
51
|
+
attr_accessor :tested
|
52
|
+
|
53
|
+
# Test label.
|
54
|
+
def to_s
|
55
|
+
label.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method :name, :to_s
|
59
|
+
|
60
|
+
# Ruby Test looks for #topic as the description of test setup.
|
61
|
+
def topic
|
62
|
+
setup.to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
#def description
|
67
|
+
# if function?
|
68
|
+
# #"#{test_case} .#{target} #{aspect}"
|
69
|
+
# "#{test_case}.#{target} #{context} #{aspect}".strip
|
70
|
+
# else
|
71
|
+
# a = /^[aeiou]/i =~ test_case.to_s ? 'An' : 'A'
|
72
|
+
# #"#{a} #{test_case} receiving ##{target} #{aspect}"
|
73
|
+
# "#{test_case}##{target} #{context} #{aspect}".strip
|
74
|
+
# end
|
75
|
+
#end
|
76
|
+
|
77
|
+
#
|
78
|
+
#def name
|
79
|
+
# if function?
|
80
|
+
# "#{test_case}.#{target}"
|
81
|
+
# else
|
82
|
+
# "#{test_case}##{target}"
|
83
|
+
# end
|
84
|
+
#end
|
85
|
+
|
86
|
+
# TODO: handle parameterized tests
|
87
|
+
def arguments
|
88
|
+
[]
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
def to_proc
|
93
|
+
lambda do
|
94
|
+
call
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
def match?(match)
|
100
|
+
match == target || match === description
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
def call
|
105
|
+
context.run(self) do
|
106
|
+
setup.run_setup(scope) if setup
|
107
|
+
scope.instance_exec(*arguments, &procedure)
|
108
|
+
setup.run_teardown(scope) if setup
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
def scope
|
114
|
+
context.scope
|
115
|
+
end
|
116
|
+
|
117
|
+
=begin
|
118
|
+
# The file_and_line method returns the file name and line number of
|
119
|
+
# the caller created upon initialization of this object.
|
120
|
+
#
|
121
|
+
# This method is cached.
|
122
|
+
#
|
123
|
+
# Examples
|
124
|
+
# file_and_line #=> ['foo_test.rb', 123]
|
125
|
+
#
|
126
|
+
# Returns Array of file name and line number of caller.
|
127
|
+
def source_location
|
128
|
+
@file_and_line ||= (
|
129
|
+
line = caller[0]
|
130
|
+
i = line.rindex(':in')
|
131
|
+
line = i ? line[0...i] : line
|
132
|
+
f, l = File.basename(line).split(':')
|
133
|
+
[f, l]
|
134
|
+
)
|
135
|
+
end
|
136
|
+
=end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Lemon
|
2
|
+
|
3
|
+
# Test Subject - Setup and Teardown code.
|
4
|
+
class TestSetup
|
5
|
+
|
6
|
+
# The test case to which this advice belong.
|
7
|
+
attr :context
|
8
|
+
|
9
|
+
# The description of this concern. Make this
|
10
|
+
# as detailed as you wish.
|
11
|
+
attr :description
|
12
|
+
|
13
|
+
# Setup procedure.
|
14
|
+
attr :setup
|
15
|
+
|
16
|
+
# Teardown procedure.
|
17
|
+
attr :teardown
|
18
|
+
|
19
|
+
# New case instance.
|
20
|
+
def initialize(context, description, options={}, &setup)
|
21
|
+
@context = context
|
22
|
+
@description = description.to_s
|
23
|
+
#@function = options[:function] || options[:singleton]
|
24
|
+
#@type = options[:type] || :context
|
25
|
+
@setup = [setup].flatten
|
26
|
+
@teardown = []
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
def teardown=(procedure)
|
31
|
+
@teardown = [procedure]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Setup.
|
35
|
+
def run_setup(scope)
|
36
|
+
setup.each do |proc|
|
37
|
+
scope.instance_eval(&proc)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Teardown.
|
42
|
+
def run_teardown(scope)
|
43
|
+
teardown.each do |proc|
|
44
|
+
scope.instance_eval(&proc)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the description with newlines removed.
|
49
|
+
def to_s
|
50
|
+
description.gsub(/\n/, ' ')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,6 @@
|
|
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/index.html
CHANGED
@@ -66,12 +66,13 @@
|
|
66
66
|
TestCase HelloWorld do
|
67
67
|
Concern "String output works as expected."
|
68
68
|
|
69
|
-
Unit :to_s
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
75
76
|
end
|
76
77
|
end
|
77
78
|
</pre>
|
data/{qed → spec}/applique/fs.rb
RENAMED
File without changes
|
@@ -20,19 +20,23 @@ Given an example script in 'lib/complete_example.rb' as follows:
|
|
20
20
|
|
21
21
|
And given a test case in 'test/complete_example_case.rb' as follows:
|
22
22
|
|
23
|
-
|
23
|
+
Covers 'complete_example.rb'
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
TestCase C1 do
|
26
|
+
method :f1 do
|
27
|
+
test "Returns a String"
|
27
28
|
end
|
28
|
-
|
29
|
+
method :f2 do
|
30
|
+
test "Returns a String"
|
29
31
|
end
|
30
|
-
|
32
|
+
method :f3 do
|
33
|
+
test "Returns a String"
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
|
-
|
35
|
-
|
37
|
+
TestCase C2 do
|
38
|
+
method :g1 do
|
39
|
+
test "Returns a String"
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
@@ -78,23 +82,29 @@ We will use the same example classes as above, but in this case we will
|
|
78
82
|
add coverage for private and protected methods as well, given a test case
|
79
83
|
in 'test/complete_example_case.rb' as follows:
|
80
84
|
|
81
|
-
|
85
|
+
Covers 'complete_example.rb'
|
82
86
|
|
83
|
-
|
84
|
-
|
87
|
+
TestCase C1 do
|
88
|
+
method :f1 do
|
89
|
+
test "Returns a String"
|
85
90
|
end
|
86
|
-
|
91
|
+
method :f2 do
|
92
|
+
test "Returns a String"
|
87
93
|
end
|
88
|
-
|
94
|
+
method :f3 do
|
95
|
+
test "Returns a String"
|
89
96
|
end
|
90
97
|
end
|
91
98
|
|
92
|
-
|
93
|
-
|
99
|
+
TestCase C2 do
|
100
|
+
method :g1 do
|
101
|
+
test "Returns a String"
|
94
102
|
end
|
95
|
-
|
103
|
+
method :g2 do
|
104
|
+
test "Returns a String"
|
96
105
|
end
|
97
|
-
|
106
|
+
method :g3 do
|
107
|
+
test "Returns a String"
|
98
108
|
end
|
99
109
|
end
|
100
110
|
|
@@ -24,17 +24,20 @@ Given an example script in 'lib/incomplete_example.rb' as follows:
|
|
24
24
|
|
25
25
|
And given a test case in 'test/incomplete_example_case.rb' as follows:
|
26
26
|
|
27
|
-
|
27
|
+
Covers 'incomplete_example.rb'
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
TestCase I1 do
|
30
|
+
method :f1 do
|
31
|
+
test "Returns a String"
|
31
32
|
end
|
32
|
-
|
33
|
+
method :f2 do
|
34
|
+
test "Returns a String"
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
+
TestCase I2 do
|
39
|
+
method :x1 do
|
40
|
+
test "Does not exist"
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
@@ -68,7 +71,7 @@ But I3 will be listed in the uncovered cases list.
|
|
68
71
|
coverage.uncovered_cases == [I3]
|
69
72
|
|
70
73
|
Note that uncovered case methods can be included in the uncovered units list
|
71
|
-
by setting the +zealous+ option, which we will
|
74
|
+
by setting the +zealous+ option, which we will demonstrated later.
|
72
75
|
|
73
76
|
There should still be 3 covered units, I1#f1, I1#f2 and I2#x1.
|
74
77
|
|