lemon 0.9.0 → 0.9.2
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.
- checksums.yaml +7 -0
- data/{HISTORY.rdoc → HISTORY.md} +42 -11
- data/LICENSE.txt +27 -0
- data/README.md +48 -34
- data/{spec/coverage/01_complete.rdoc → demo/coverage/01_complete.md} +3 -3
- data/{spec/coverage/02_incomplete.rdoc → demo/coverage/02_incomplete.md} +2 -2
- data/{spec/coverage/03_extensions.rdoc → demo/coverage/03_extensions.md} +2 -2
- 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/cli.rb +19 -8
- data/lib/lemon/core_ext/module.rb +9 -0
- data/lib/lemon/core_ext.rb +2 -2
- 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/lib/lemon.rb +1 -15
- metadata +71 -147
- data/.gemspec +0 -152
- data/.gitignore +0 -8
- data/.reap/digest +0 -678
- data/.reap/test.reap +0 -7
- data/.ruby +0 -49
- 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/lib/lemon.yml +0 -49
- 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/try/.test +0 -8
- data/try/case_error.rb +0 -18
- data/try/case_fail.rb +0 -19
- data/try/case_pass.rb +0 -42
- data/try/case_pending.rb +0 -18
- data/try/case_singleton.rb +0 -18
- data/try/case_untested.rb +0 -14
- data/try/fixtures/calculator.rb +0 -15
- data/try/fixtures/example-use.rb +0 -5
- data/try/fixtures/example.rb +0 -20
- data/try/helpers/loadpath.rb +0 -1
- 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
- /data/bin/{lemonade → lemons} +0 -0
- /data/{work/deprecated/features/support → demo/applique}/ae.rb +0 -0
- /data/{spec → demo}/applique/fs.rb +0 -0
- /data/{spec → demo}/coverage/applique/lemon.rb +0 -0
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# NOTE: This code is not being used. It is here for the time being
|
|
2
|
-
# on the outseide change that I decide to go back to a toplevel design.
|
|
3
|
-
|
|
4
|
-
require 'lemon/model/test_suite'
|
|
5
|
-
|
|
6
|
-
class << self
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
def Covers(script)
|
|
10
|
-
Lemon.suite.dsl.covers(script)
|
|
11
|
-
end
|
|
12
|
-
alias :Coverage :Covers
|
|
13
|
-
|
|
14
|
-
# Define a general test case.
|
|
15
|
-
def Case(target, &block)
|
|
16
|
-
Lemon.suite.dsl.test_case(target, &block)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Define a class test.
|
|
20
|
-
def Class(target_class, &block)
|
|
21
|
-
Lemon.suite.dsl.test_class(target_class, &block)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Define a module test.
|
|
25
|
-
def Module(target_module, &block)
|
|
26
|
-
Lemon.suite.dsl.test_module(target_module, &block)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Define a test feature.
|
|
30
|
-
def Feature(target, &block)
|
|
31
|
-
Lemon.suite.dsl.test_feature(target, &block)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
#def Before(match=nil, &block)
|
|
36
|
-
# Lemon.suite.Before(match, &block)
|
|
37
|
-
#end
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
#def After(match=nil, &block)
|
|
41
|
-
# Lemon.suite.After(match, &block)
|
|
42
|
-
#end
|
|
43
|
-
|
|
44
|
-
#
|
|
45
|
-
#def Helper(script)
|
|
46
|
-
# Lemon.suite.Helper(script)
|
|
47
|
-
#end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
=begin
|
|
51
|
-
# FIXME: This is a BIG FAT HACK! For the life of me I cannot find
|
|
52
|
-
# a way to resolve module constants included in the test cases.
|
|
53
|
-
# Because of closure, the constant lookup goes through here, and not
|
|
54
|
-
# the Case singleton class. So to work around we must note each test
|
|
55
|
-
# before it is run, and reroute the missing constants.
|
|
56
|
-
#
|
|
57
|
-
# This sucks and it is not thread safe. If anyone know how to fix,
|
|
58
|
-
# please let me know. See Unit#call for the other end of this hack.
|
|
59
|
-
#
|
|
60
|
-
def Object.const_missing(name)
|
|
61
|
-
if unit = Lemon.test_stack.last
|
|
62
|
-
begin
|
|
63
|
-
(class << unit.test_case; self; end).const_get(name)
|
|
64
|
-
rescue NameError
|
|
65
|
-
super(name)
|
|
66
|
-
end
|
|
67
|
-
else
|
|
68
|
-
super(name)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
#def Object.const_missing(name)
|
|
73
|
-
# if unit = Lemon.test_stack.last
|
|
74
|
-
# klass = (class << unit.test_case; self; end)
|
|
75
|
-
# if klass.const_defined?(name)
|
|
76
|
-
# return klass.const_get(name)
|
|
77
|
-
# end
|
|
78
|
-
# end
|
|
79
|
-
# super(name)
|
|
80
|
-
#end
|
|
81
|
-
|
|
82
|
-
# Get current running test. Used for the BIG FAT HACK.
|
|
83
|
-
def Lemon.test_stack
|
|
84
|
-
@@test_stack ||= []
|
|
85
|
-
end
|
|
86
|
-
=end
|
|
87
|
-
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
require 'lemon/model/test_suite'
|
|
2
|
-
|
|
3
|
-
module Test
|
|
4
|
-
extend self
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
def covers(script)
|
|
8
|
-
Lemon.suite.dsl.covers(script)
|
|
9
|
-
end
|
|
10
|
-
alias :Covers :covers
|
|
11
|
-
|
|
12
|
-
alias :coverage :covers
|
|
13
|
-
alias :Coverage :covers
|
|
14
|
-
|
|
15
|
-
# Define a general test case.
|
|
16
|
-
def case(target, &block)
|
|
17
|
-
Lemon.suite.dsl.test_case(target, &block)
|
|
18
|
-
end
|
|
19
|
-
alias :Case :case
|
|
20
|
-
|
|
21
|
-
# Define a class test.
|
|
22
|
-
def class(target_class, &block)
|
|
23
|
-
Lemon.suite.dsl.test_class(target_class, &block)
|
|
24
|
-
end
|
|
25
|
-
alias :Class :class
|
|
26
|
-
|
|
27
|
-
# Define a module test.
|
|
28
|
-
def module(target_module, &block)
|
|
29
|
-
Lemon.suite.dsl.test_module(target_module, &block)
|
|
30
|
-
end
|
|
31
|
-
alias :Module :module
|
|
32
|
-
|
|
33
|
-
# Define a test feature.
|
|
34
|
-
def feature(target, &block)
|
|
35
|
-
Lemon.suite.dsl.test_feature(target, &block)
|
|
36
|
-
end
|
|
37
|
-
alias :Feature :feature
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
#def Before(match=nil, &block)
|
|
41
|
-
# Lemon.suite.Before(match, &block)
|
|
42
|
-
#end
|
|
43
|
-
|
|
44
|
-
#
|
|
45
|
-
#def After(match=nil, &block)
|
|
46
|
-
# Lemon.suite.After(match, &block)
|
|
47
|
-
#end
|
|
48
|
-
|
|
49
|
-
#
|
|
50
|
-
#def Helper(script)
|
|
51
|
-
# Lemon.suite.Helper(script)
|
|
52
|
-
#end
|
|
53
|
-
|
|
54
|
-
end
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
module Lemon
|
|
2
|
-
|
|
3
|
-
# Base class for TestCase DSLs.
|
|
4
|
-
class BaseDSL < Module
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
def initialize(context, &code)
|
|
8
|
-
@context = context
|
|
9
|
-
@subject = context.subject
|
|
10
|
-
|
|
11
|
-
module_eval(&code)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
def context(description, &block)
|
|
16
|
-
@context.tests << TestCase.new(@context, description, &block)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
def test(description, &procedure)
|
|
21
|
-
test = TestProc.new(
|
|
22
|
-
@context,
|
|
23
|
-
:description => description,
|
|
24
|
-
:subject => subject,
|
|
25
|
-
&procedure
|
|
26
|
-
)
|
|
27
|
-
@context.tests << test
|
|
28
|
-
test
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Omit a test or test case from being run.
|
|
32
|
-
#
|
|
33
|
-
# omit test "something or other" do
|
|
34
|
-
# # ...
|
|
35
|
-
# end
|
|
36
|
-
#
|
|
37
|
-
def omit(test_or_case)
|
|
38
|
-
test_or_case.omit = true
|
|
39
|
-
end
|
|
40
|
-
alias_method :Omit, :omit
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# Load a helper script applicable to this test case. Unlike requiring
|
|
46
|
-
# a helper script, the #helper method will eval the file's contents
|
|
47
|
-
# directly into the test context (using instance_eval).
|
|
48
|
-
#
|
|
49
|
-
# @param [String] file
|
|
50
|
-
# File to eval into test context.
|
|
51
|
-
#
|
|
52
|
-
# FIXME: This is at odds with loading helpers automatically. How
|
|
53
|
-
# to handle?
|
|
54
|
-
def helper(file)
|
|
55
|
-
instance_eval(File.read(file), file)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
alias_method :Helper, :helper
|
|
59
|
-
|
|
60
|
-
#def include(*mods)
|
|
61
|
-
# extend *mods
|
|
62
|
-
#end
|
|
63
|
-
|
|
64
|
-
#def pending(message=nil)
|
|
65
|
-
# raise Pending.new(message)
|
|
66
|
-
#end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# Before All and After All advice are bad form.
|
|
70
|
-
#
|
|
71
|
-
# # Define a "before all" procedure.
|
|
72
|
-
# def prepare(&procedure)
|
|
73
|
-
# before(&procedure)
|
|
74
|
-
# end
|
|
75
|
-
#
|
|
76
|
-
# alias_method :Prepare, :prepare
|
|
77
|
-
#
|
|
78
|
-
# # Define an "after all" procedure.
|
|
79
|
-
# def cleanup(&procedure)
|
|
80
|
-
# after(&procedure)
|
|
81
|
-
# end
|
|
82
|
-
#
|
|
83
|
-
# alias_method :Cleanup, :cleanup
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
end
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
module Lemon
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
class TestClause
|
|
5
|
-
|
|
6
|
-
# New unit test procedure.
|
|
7
|
-
#
|
|
8
|
-
def initialize(scenario, description, options={}) #, &procedure)
|
|
9
|
-
@context = scenario
|
|
10
|
-
@description = description
|
|
11
|
-
|
|
12
|
-
@type = options[:type]
|
|
13
|
-
|
|
14
|
-
#@subject = options[:subject]
|
|
15
|
-
#@aspect = options[:aspect]
|
|
16
|
-
#@omit = options[:omit]
|
|
17
|
-
|
|
18
|
-
#@procedure = procedure
|
|
19
|
-
|
|
20
|
-
@tested = false
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
attr :type
|
|
24
|
-
|
|
25
|
-
public
|
|
26
|
-
|
|
27
|
-
# The case to which this test belongs.
|
|
28
|
-
attr :context
|
|
29
|
-
|
|
30
|
-
# Setup and teardown procedures.
|
|
31
|
-
#attr :subject
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
#def target
|
|
35
|
-
# context.
|
|
36
|
-
#end
|
|
37
|
-
|
|
38
|
-
# Description of test.
|
|
39
|
-
attr :description
|
|
40
|
-
|
|
41
|
-
# Test procedure, in which test assertions should be made.
|
|
42
|
-
#attr :procedure
|
|
43
|
-
|
|
44
|
-
# The before and after advice from the context.
|
|
45
|
-
#def advice
|
|
46
|
-
# context.advice
|
|
47
|
-
#end
|
|
48
|
-
|
|
49
|
-
#
|
|
50
|
-
#def name ; @target ; end
|
|
51
|
-
|
|
52
|
-
# Is this unit test for a class or module level method?
|
|
53
|
-
#def function?
|
|
54
|
-
# context.function?
|
|
55
|
-
#end
|
|
56
|
-
|
|
57
|
-
#
|
|
58
|
-
attr_accessor :omit
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
def omit?
|
|
62
|
-
@omit
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
#
|
|
66
|
-
#attr_accessor :tested
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
#def to_s
|
|
70
|
-
# if function?
|
|
71
|
-
# "#{test_case}.#{target}"
|
|
72
|
-
# else
|
|
73
|
-
# "#{test_case}##{target}"
|
|
74
|
-
# end
|
|
75
|
-
#end
|
|
76
|
-
|
|
77
|
-
#
|
|
78
|
-
def to_s
|
|
79
|
-
"#{type.to_s.capitalize} #{description}"
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
#
|
|
83
|
-
def subject
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
#
|
|
87
|
-
def scope
|
|
88
|
-
context.scope
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
#
|
|
92
|
-
def to_proc
|
|
93
|
-
lambda{ call }
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
#
|
|
97
|
-
#def match?(match)
|
|
98
|
-
# match == target || match === aspect
|
|
99
|
-
#end
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
def call
|
|
103
|
-
context.run(self) do
|
|
104
|
-
#subject.run_setup(scope) if subject
|
|
105
|
-
scope.instance_exec(*arguments, &procedure)
|
|
106
|
-
#subject.run_teardown(scope) if subject
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
end
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
=begin
|
|
2
|
-
module Lemon
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
class TestContext
|
|
6
|
-
|
|
7
|
-
# The test case to which this concern belongs.
|
|
8
|
-
attr :test_case
|
|
9
|
-
|
|
10
|
-
# The description of this concern. Make this
|
|
11
|
-
# as detailed as you wish.
|
|
12
|
-
attr :description
|
|
13
|
-
|
|
14
|
-
# New case instance.
|
|
15
|
-
def initialize(test_case, description, options={}, &block)
|
|
16
|
-
@test_case = test_case
|
|
17
|
-
@description = description.to_s
|
|
18
|
-
@function = options[:function] || options[:singleton]
|
|
19
|
-
@type = options[:type] || :context
|
|
20
|
-
@block = block
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
def teardown=(procedure)
|
|
25
|
-
@teardown = procedure
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Teardown instance.
|
|
29
|
-
def teardown(scope=nil)
|
|
30
|
-
if scope
|
|
31
|
-
scope.instance_eval(&@teardown) if @teardown
|
|
32
|
-
else
|
|
33
|
-
@teardown
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Create instance.
|
|
38
|
-
def setup(scope)
|
|
39
|
-
if @block
|
|
40
|
-
scope.instance_eval(&@block)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def function? ; false ; end
|
|
45
|
-
alias_method :meta?, :function?
|
|
46
|
-
|
|
47
|
-
# Returns the description with newlines removed.
|
|
48
|
-
def to_s
|
|
49
|
-
description.gsub(/\n/, ' ')
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
end
|
|
54
|
-
=end
|
|
55
|
-
|
|
56
|
-
=begin
|
|
57
|
-
#
|
|
58
|
-
class TestInstance < TestContext
|
|
59
|
-
|
|
60
|
-
# Create instance.
|
|
61
|
-
def setup(scope)
|
|
62
|
-
if @block
|
|
63
|
-
ins = scope.instance_eval(&@block)
|
|
64
|
-
raise "target type mismatch" unless test_case.target === ins
|
|
65
|
-
end
|
|
66
|
-
ins
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
class TestSingleton < TestContext
|
|
73
|
-
|
|
74
|
-
# Create instance.
|
|
75
|
-
def setup(scope)
|
|
76
|
-
if @block
|
|
77
|
-
ins = scope.instance_eval(&@block)
|
|
78
|
-
raise "target type mismatch" unless test_case.target == ins
|
|
79
|
-
else
|
|
80
|
-
ins = @test_case.target
|
|
81
|
-
end
|
|
82
|
-
ins
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def function? ; true ; end
|
|
86
|
-
alias_method :meta?, :function?
|
|
87
|
-
|
|
88
|
-
end
|
|
89
|
-
=end
|
|
90
|
-
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
require 'lemon/model/pending'
|
|
2
|
-
require 'lemon/model/test_context'
|
|
3
|
-
require 'lemon/model/test_advice'
|
|
4
|
-
require 'lemon/model/test_scenario'
|
|
5
|
-
|
|
6
|
-
module Lemon
|
|
7
|
-
|
|
8
|
-
# The TestFeature ...
|
|
9
|
-
#
|
|
10
|
-
# * `tests` are _scenarios_,
|
|
11
|
-
# * `advice` are _given_, _when_ and _then_ rules.
|
|
12
|
-
#
|
|
13
|
-
class TestFeature < TestCase
|
|
14
|
-
|
|
15
|
-
#
|
|
16
|
-
def initialize(context, settings={}, &block)
|
|
17
|
-
@story = []
|
|
18
|
-
super(context, settings, &block)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
## This has to be redefined in each subclass to pick
|
|
22
|
-
## up there respective DSL classes.
|
|
23
|
-
#def evaluate(&block)
|
|
24
|
-
# @dsl = DSL.new(self, &block)
|
|
25
|
-
#end
|
|
26
|
-
|
|
27
|
-
attr :story
|
|
28
|
-
|
|
29
|
-
# Feature scenarios are tests.
|
|
30
|
-
alias_method :scenarios, :tests
|
|
31
|
-
|
|
32
|
-
#
|
|
33
|
-
def to_s
|
|
34
|
-
"Feature #{target}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
def to_s #description
|
|
39
|
-
(["Feature: #{target}"] + story).join("\n ")
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Run test in the context of this case.
|
|
43
|
-
#
|
|
44
|
-
# @param [TestProc] test
|
|
45
|
-
# The test procedure instance to run.
|
|
46
|
-
#
|
|
47
|
-
def run(&block)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
#
|
|
51
|
-
class DSL < Module
|
|
52
|
-
|
|
53
|
-
#
|
|
54
|
-
def initialize(feature, &code)
|
|
55
|
-
@feature = feature
|
|
56
|
-
|
|
57
|
-
module_eval(&code)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
def To(description)
|
|
62
|
-
@feature.story << "To " + description
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
#
|
|
66
|
-
def As(description)
|
|
67
|
-
@feature.story << "As " + description
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
#
|
|
71
|
-
def We(description)
|
|
72
|
-
@feature.story << "We " + description
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
#
|
|
76
|
-
def Scenario(description, &procedure)
|
|
77
|
-
scenario = TestScenario.new(@feature, description, &procedure)
|
|
78
|
-
@feature.scenarios << scenario
|
|
79
|
-
scenario
|
|
80
|
-
end
|
|
81
|
-
alias_method :scenario, :Scenario
|
|
82
|
-
|
|
83
|
-
# Omit a scenario from test runs.
|
|
84
|
-
#
|
|
85
|
-
# omit unit :foo do
|
|
86
|
-
# # ...
|
|
87
|
-
# end
|
|
88
|
-
#
|
|
89
|
-
def Omit(scenario)
|
|
90
|
-
scenario.omit = true
|
|
91
|
-
end
|
|
92
|
-
alias_method :omit, :Omit
|
|
93
|
-
|
|
94
|
-
# Given ...
|
|
95
|
-
#
|
|
96
|
-
# @param [String] description
|
|
97
|
-
# A brief description of the _given_ criteria.
|
|
98
|
-
#
|
|
99
|
-
def Given(description, &procedure)
|
|
100
|
-
@feature.advice[:given][description] = procedure
|
|
101
|
-
end
|
|
102
|
-
alias_method :given, :Given
|
|
103
|
-
|
|
104
|
-
# When ...
|
|
105
|
-
#
|
|
106
|
-
# @param [String] description
|
|
107
|
-
# A brief description of the _when_ criteria.
|
|
108
|
-
#
|
|
109
|
-
def When(description, &procedure)
|
|
110
|
-
@feature.advice[:when][description] = procedure
|
|
111
|
-
end
|
|
112
|
-
alias_method :wence, :When
|
|
113
|
-
|
|
114
|
-
# Then ...
|
|
115
|
-
#
|
|
116
|
-
# @param [String] description
|
|
117
|
-
# A brief description of the _then_ criteria.
|
|
118
|
-
#
|
|
119
|
-
def Then(description, &procedure)
|
|
120
|
-
@feature.advice[:then][description] = procedure
|
|
121
|
-
end
|
|
122
|
-
alias_method :hence, :Then
|
|
123
|
-
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
end
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
require 'lemon/model/test_clause'
|
|
2
|
-
|
|
3
|
-
module Lemon
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
class TestScenario < TestCase
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
def initialize(feature, summary, options={}, &block)
|
|
10
|
-
@feature = feature
|
|
11
|
-
@summary = summary
|
|
12
|
-
|
|
13
|
-
@tests = []
|
|
14
|
-
|
|
15
|
-
evaluate(&block)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
def evaluate(&procedure)
|
|
20
|
-
@dsl = DSL.new(self, &procedure)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
attr :feature
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
attr :dsl
|
|
28
|
-
|
|
29
|
-
attr_accessor :omit
|
|
30
|
-
|
|
31
|
-
#
|
|
32
|
-
def omit?
|
|
33
|
-
@omit
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
#
|
|
37
|
-
def to_s
|
|
38
|
-
"Scenario: #{@summary}"
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def subject
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
def run(clause)
|
|
47
|
-
type = clause.type
|
|
48
|
-
desc = clause.description
|
|
49
|
-
feature.advice[type].each do |mask, proc|
|
|
50
|
-
if md = match_regexp(mask).match(desc)
|
|
51
|
-
scope.instance_exec(*md[1..-1], &proc)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
#
|
|
57
|
-
#--
|
|
58
|
-
# TODO: Change so that the scope is the DSL
|
|
59
|
-
# and includes the DSL of the context?
|
|
60
|
-
#++
|
|
61
|
-
def scope
|
|
62
|
-
@scope ||= (
|
|
63
|
-
#if feature
|
|
64
|
-
# scope = feature.scope || Object.new
|
|
65
|
-
# scope.extend(dsl)
|
|
66
|
-
#else
|
|
67
|
-
scope = Object.new
|
|
68
|
-
scope.extend(dsl)
|
|
69
|
-
#end
|
|
70
|
-
)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
#
|
|
74
|
-
#def find
|
|
75
|
-
# features.clauses[@type].find{ |c| c =~ @description }
|
|
76
|
-
#end
|
|
77
|
-
|
|
78
|
-
# Convert matching string into a regular expression. If the string
|
|
79
|
-
# contains double parenthesis, such as ((.*?)), then the text within
|
|
80
|
-
# them is treated as in regular expression and kept verbatium.
|
|
81
|
-
#
|
|
82
|
-
# TODO: Better way to isolate regexp. Maybe ?:(.*?) or /(.*?)/.
|
|
83
|
-
#
|
|
84
|
-
def match_regexp(str)
|
|
85
|
-
str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
|
|
86
|
-
x =~ /\A\(\((.*)\)\)\Z/ ? $1 : Regexp.escape(x)
|
|
87
|
-
}.join
|
|
88
|
-
str = str.gsub(/\\\s+/, '\s+')
|
|
89
|
-
Regexp.new(str, Regexp::IGNORECASE)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# TODO: Need to ensure the correct order of Given, When, Then.
|
|
94
|
-
class DSL < Module
|
|
95
|
-
|
|
96
|
-
#
|
|
97
|
-
def initialize(scenario, &code)
|
|
98
|
-
@scenario = scenario
|
|
99
|
-
|
|
100
|
-
module_eval(&code)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Given ...
|
|
104
|
-
#
|
|
105
|
-
# @param [String] description
|
|
106
|
-
# A brief description of what the setup procedure sets-up.
|
|
107
|
-
#
|
|
108
|
-
def Given(description)
|
|
109
|
-
@scenario.tests << TestClause.new(@scenario, description, :type=>:given)
|
|
110
|
-
end
|
|
111
|
-
alias_method :given, :Given
|
|
112
|
-
|
|
113
|
-
# When ...
|
|
114
|
-
#
|
|
115
|
-
# @param [String] description
|
|
116
|
-
# A brief description of what the setup procedure sets-up.
|
|
117
|
-
#
|
|
118
|
-
def When(description)
|
|
119
|
-
@scenario.tests << TestClause.new(@scenario, description, :type=>:when)
|
|
120
|
-
end
|
|
121
|
-
alias_method :wence, :When
|
|
122
|
-
|
|
123
|
-
# Then ...
|
|
124
|
-
#
|
|
125
|
-
# @param [String] description
|
|
126
|
-
# A brief description of what the setup procedure sets-up.
|
|
127
|
-
#
|
|
128
|
-
def Then(description)
|
|
129
|
-
@scenario.tests << TestClause.new(@scenario, description, :type=>:then)
|
|
130
|
-
end
|
|
131
|
-
alias_method :hence, :Then
|
|
132
|
-
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
end
|