lemon 0.8.4 → 0.8.5
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/.config/cucumber.yml +3 -0
- data/.gitignore +8 -0
- data/.reap/digest +678 -0
- data/.reap/test.reap +7 -0
- data/.ruby +42 -45
- data/Assembly +43 -0
- data/HISTORY.rdoc +10 -0
- data/MANIFEST +65 -0
- data/PROFILE +9 -6
- data/Rakefile +14 -0
- data/VERSION +1 -1
- data/lemon.gemspec +152 -0
- data/lib/lemon.yml +42 -45
- data/lib/lemon/cli.rb +4 -2
- data/lib/lemon/controller/test_runner.rb +4 -0
- data/lib/lemon/model/test_case.rb +122 -40
- data/notes/2010-05-05-coverage.rdoc +47 -0
- data/notes/2010-05-06-files_not_classes.rdoc +19 -0
- data/notes/2010-07-11-acid_testing.rdoc +52 -0
- data/notes/2010-08-02-enforcing-the-unit.md +68 -0
- data/notes/2010-08-03-new-api.md +37 -0
- data/site/.rsync-filter +8 -0
- 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 +39 -0
- 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 +6 -0
- data/site/assets/styles/reset.css +17 -0
- data/site/assets/styles/site.css +33 -0
- data/site/index.html +217 -0
- data/work/deprecated/command/abstract.rb +29 -0
- data/work/deprecated/command/coverage.rb +115 -0
- data/work/deprecated/command/generate.rb +124 -0
- data/work/deprecated/command/test.rb +112 -0
- data/work/reference/dsl2.rb +136 -0
- data/work/reference/dynamic_constant_lookup.rb +76 -0
- data/work/sandbox/lib/sample.rb +13 -0
- data/work/sandbox/test/sample_case.rb +12 -0
- data/work/trash/example-cover.rb +5 -0
- data/work/trash/example.rb +16 -0
- metadata +134 -101
- data/.yardopts +0 -7
- data/QED.rdoc +0 -1
@@ -0,0 +1,124 @@
|
|
1
|
+
module Lemon
|
2
|
+
module Command
|
3
|
+
require 'lemon/command/abstract'
|
4
|
+
|
5
|
+
# Lemon Generate Command-line tool.
|
6
|
+
class Generate < Abstract
|
7
|
+
require 'lemon/coverage'
|
8
|
+
|
9
|
+
#
|
10
|
+
def self.subcommand
|
11
|
+
'generate' #['-g', '--generate']
|
12
|
+
end
|
13
|
+
|
14
|
+
# Initialize and run.
|
15
|
+
def self.run
|
16
|
+
new.run
|
17
|
+
end
|
18
|
+
|
19
|
+
# New Command instance.
|
20
|
+
def initialize
|
21
|
+
@requires = []
|
22
|
+
@includes = []
|
23
|
+
@namespaces = []
|
24
|
+
@public_only = false
|
25
|
+
@uncovered = false
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: Support output ? perhaps complex scaffolding
|
29
|
+
#attr_accessor :output
|
30
|
+
|
31
|
+
#
|
32
|
+
attr_accessor :public_only
|
33
|
+
|
34
|
+
#
|
35
|
+
attr_accessor :uncovered
|
36
|
+
|
37
|
+
#
|
38
|
+
def public_only?
|
39
|
+
@public_only
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
def uncovered_only?
|
44
|
+
@uncovered
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get or set librarires to pre-require.
|
48
|
+
def requires(*paths)
|
49
|
+
@requires.concat(paths) unless paths.empty?
|
50
|
+
@requires
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get or set paths to include in $LOAD_PATH.
|
54
|
+
def includes(*paths)
|
55
|
+
@includes.concat(paths) unless paths.empty?
|
56
|
+
@includes
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
def namespaces(*names)
|
61
|
+
@namespaces.concat(names) unless names.empty?
|
62
|
+
@namespaces
|
63
|
+
end
|
64
|
+
|
65
|
+
# Instance of OptionParser.
|
66
|
+
def parser
|
67
|
+
@parser ||= OptionParser.new do |opt|
|
68
|
+
opt.banner = "lemon generate [OPTIONS]"
|
69
|
+
opt.separator("Generate unit test scaffolding.")
|
70
|
+
opt.on("--namespace", "-n [NAME]", "limit tests to this namespace") do |name|
|
71
|
+
namespaces(name)
|
72
|
+
end
|
73
|
+
opt.on("--public", "-p", "only include public methods") do
|
74
|
+
self.public_only = true
|
75
|
+
end
|
76
|
+
opt.on("--uncovered", "-u", "only include uncovered methods") do
|
77
|
+
self.uncovered = true
|
78
|
+
end
|
79
|
+
#opt.on("--output", "-o [PATH]", "output directory") do |path|
|
80
|
+
# self.output = path
|
81
|
+
#end
|
82
|
+
opt.on("-r [FILES]" , "library files to require") do |files|
|
83
|
+
files = files.split(/[:;]/)
|
84
|
+
requires(*files)
|
85
|
+
end
|
86
|
+
opt.on("-I [PATH]" , "include in $LOAD_PATH") do |path|
|
87
|
+
path = path.split(/[:;]/)
|
88
|
+
includes(*path)
|
89
|
+
end
|
90
|
+
opt.on("--debug" , "turn on debugging mode") do
|
91
|
+
$DEBUG = true
|
92
|
+
end
|
93
|
+
opt.on_tail("--help", "-h", "show this help message") do
|
94
|
+
puts opt
|
95
|
+
exit
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Generate test skeletons.
|
101
|
+
def run
|
102
|
+
parser.parse!
|
103
|
+
|
104
|
+
test_files = ARGV.dup
|
105
|
+
|
106
|
+
includes.each{ |path| $LOAD_PATH.unshift(path) }
|
107
|
+
requires.each{ |path| require(path) }
|
108
|
+
|
109
|
+
suite = Lemon::Test::Suite.new(test_files, :cover=>true)
|
110
|
+
cover = Lemon::Coverage.new(suite, namespaces, :public=>public_only?)
|
111
|
+
#cover = Lemon::Coverage.new([], namespaces, :public=>public_only?, :uncovered=>uncovered_only?)
|
112
|
+
|
113
|
+
if uncovered_only?
|
114
|
+
puts cover.generate_uncovered #(output)
|
115
|
+
else
|
116
|
+
puts cover.generate #(output)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Lemon
|
2
|
+
module Command
|
3
|
+
require 'lemon/command/abstract'
|
4
|
+
|
5
|
+
# Lemon Test Command-line tool.
|
6
|
+
class Test < Abstract
|
7
|
+
require 'lemon/runner'
|
8
|
+
|
9
|
+
def self.subcommand
|
10
|
+
'test'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Initialize and run.
|
14
|
+
def self.run
|
15
|
+
new.run
|
16
|
+
end
|
17
|
+
|
18
|
+
# New Command instance.
|
19
|
+
def initialize
|
20
|
+
@format = nil
|
21
|
+
@cover = false
|
22
|
+
@requires = []
|
23
|
+
@includes = []
|
24
|
+
@namespaces = []
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
attr_accessor :format
|
29
|
+
|
30
|
+
#
|
31
|
+
attr_accessor :cover
|
32
|
+
|
33
|
+
# Get or set librarires to pre-require.
|
34
|
+
def requires(*paths)
|
35
|
+
@requires.concat(paths) unless paths.empty?
|
36
|
+
@requires
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get or set paths to include in $LOAD_PATH.
|
40
|
+
def includes(*paths)
|
41
|
+
@includes.concat(paths) unless paths.empty?
|
42
|
+
@includes
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
def namespaces(*names)
|
47
|
+
@namespaces.concat(names) unless names.empty?
|
48
|
+
@namespaces
|
49
|
+
end
|
50
|
+
|
51
|
+
# Instance of OptionParser.
|
52
|
+
def parser
|
53
|
+
@parser ||= OptionParser.new do |opt|
|
54
|
+
opt.banner = "lemon [options] [test-files ...]"
|
55
|
+
opt.separator("Run unit tests.")
|
56
|
+
opt.separator("OPTIONS:")
|
57
|
+
#opt.on('--coverage', '-c', "include coverage informarton") do
|
58
|
+
# self.cover = true
|
59
|
+
#end
|
60
|
+
opt.on('--verbose', '-v', "select verbose report format") do |type|
|
61
|
+
self.format = :verbose
|
62
|
+
end
|
63
|
+
opt.on('--outline', '-o', "select outline report format") do |type|
|
64
|
+
self.format = :outline
|
65
|
+
end
|
66
|
+
opt.on('--format', '-f [TYPE]', "select report format") do |type|
|
67
|
+
self.format = type
|
68
|
+
end
|
69
|
+
opt.on("--namespace", "-n [NAME]", "limit testing to this namespace") do |name|
|
70
|
+
namespaces(name)
|
71
|
+
end
|
72
|
+
opt.on("-r [FILES]" , 'library files to require') do |files|
|
73
|
+
files = files.split(/[:;]/)
|
74
|
+
requires(*files)
|
75
|
+
end
|
76
|
+
opt.on("-I [PATH]" , 'include in $LOAD_PATH') do |path|
|
77
|
+
paths = path.split(/[:;]/)
|
78
|
+
includes(*paths)
|
79
|
+
end
|
80
|
+
opt.on("--debug" , 'turn on debugging mode') do
|
81
|
+
$DEBUG = true
|
82
|
+
end
|
83
|
+
opt.on_tail('--help', '-h', 'show this help message') do
|
84
|
+
puts opt
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Run unit tests.
|
91
|
+
def run
|
92
|
+
parser.parse!
|
93
|
+
|
94
|
+
files = ARGV.dup
|
95
|
+
|
96
|
+
includes.each{ |path| $LOAD_PATH.unshift(path) }
|
97
|
+
requires.each{ |path| require(path) }
|
98
|
+
|
99
|
+
#suite = Lemon::Test::Suite.new(files, :cover=>cover)
|
100
|
+
#runner = Lemon::Runner.new(suite, :format=>format, :cover=>cover, :namespaces=>namespaces)
|
101
|
+
|
102
|
+
suite = Lemon::Test::Suite.new(files)
|
103
|
+
runner = Lemon::Runner.new(suite, :format=>format, :namespaces=>namespaces)
|
104
|
+
|
105
|
+
runner.run
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'ae'
|
2
|
+
|
3
|
+
module Lemon
|
4
|
+
|
5
|
+
def self.suite
|
6
|
+
@suite ||= Suite.new(Runner.new(Reporter.new))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.suite=(suite)
|
10
|
+
@suite = suite
|
11
|
+
end
|
12
|
+
|
13
|
+
class Context
|
14
|
+
def initialize(desc=nil)
|
15
|
+
@desc = desc
|
16
|
+
@before = {}
|
17
|
+
@after = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
@desc
|
22
|
+
end
|
23
|
+
|
24
|
+
def before(which, &block)
|
25
|
+
@before[which] = block if block
|
26
|
+
@before[which]
|
27
|
+
end
|
28
|
+
|
29
|
+
def after(which, &block)
|
30
|
+
@after[which] = block if block
|
31
|
+
@after[which]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Suite
|
36
|
+
def initialize(runner)
|
37
|
+
@runner = runner
|
38
|
+
end
|
39
|
+
|
40
|
+
def before(which, &block)
|
41
|
+
@runner.before(which, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def after(which, &block)
|
45
|
+
@runner.after(which, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def unit(mod, meth, desc=nil, &block)
|
49
|
+
@runner.unit(mod, meth, desc, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def context(desc, &block)
|
53
|
+
@runner.context(desc, &block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Runner is a listner.
|
58
|
+
class Runner
|
59
|
+
#
|
60
|
+
def initialize(*reporters)
|
61
|
+
@reporters = reporters
|
62
|
+
#@before = {} #Hash.new{|h,k| h[k]=[]}
|
63
|
+
#@after = {} #Hash.new{|h,k| h[k]=[]}
|
64
|
+
@context_stack = [Context.new]
|
65
|
+
end
|
66
|
+
|
67
|
+
def before(which, &block)
|
68
|
+
@context_stack.last.before(which, &block)
|
69
|
+
@reporters.each do |reporter|
|
70
|
+
reporter.before(which, &block)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def after(which, &block)
|
75
|
+
@context_stack.last.after(which, &block)
|
76
|
+
@reporters.each do |reporter|
|
77
|
+
reporter.after(which, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def instance(desc, &block)
|
82
|
+
@instance = Context.new(desc, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def unit(mod, meth, desc=nil, &block)
|
86
|
+
@reporters.each do |reporter|
|
87
|
+
reporter.unit(mod, meth, desc, &block)
|
88
|
+
end
|
89
|
+
|
90
|
+
if @instance && block.arity != 0
|
91
|
+
block.call(@instance.call)
|
92
|
+
else
|
93
|
+
block.call
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Reporter
|
100
|
+
#
|
101
|
+
def initialize
|
102
|
+
end
|
103
|
+
|
104
|
+
def before(which, &block)
|
105
|
+
end
|
106
|
+
|
107
|
+
def after(which, &block)
|
108
|
+
end
|
109
|
+
|
110
|
+
def unit(mod, meth, desc=nil, &block)
|
111
|
+
puts "%s#%s %s" % [mod.name, meth.to_s, desc]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
#
|
119
|
+
def before(which, &block)
|
120
|
+
Lemon.suite.before(which, &block)
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
def after(which, &block)
|
125
|
+
Lemon.suite.after(which, &block)
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
def unit(mod, meth, desc=nil, &blk)
|
130
|
+
Lemon.suite.unit(mod, meth, desc, &blk)
|
131
|
+
end
|
132
|
+
|
133
|
+
def context(desc, &block)
|
134
|
+
Lemon.suite.context(desc, &block)
|
135
|
+
end
|
136
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
module M
|
3
|
+
def m1; "m1"; end
|
4
|
+
module N
|
5
|
+
def self.n1; "n1"; end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class X
|
10
|
+
class << self
|
11
|
+
alias _new new
|
12
|
+
def new(&block)
|
13
|
+
klass = Class.new(self)
|
14
|
+
klass.module_eval(&block)
|
15
|
+
klass._new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def m ; m1 ; end
|
20
|
+
def n ; N.n1 ; end
|
21
|
+
end
|
22
|
+
|
23
|
+
x = X.new do
|
24
|
+
include M
|
25
|
+
end
|
26
|
+
|
27
|
+
p x.m
|
28
|
+
p x.n
|
29
|
+
|
30
|
+
|
31
|
+
exit
|
32
|
+
|
33
|
+
class X
|
34
|
+
attr :set
|
35
|
+
def initialize(&block)
|
36
|
+
@set = {}
|
37
|
+
instance_eval(&block)
|
38
|
+
end
|
39
|
+
def defset(name, &block)
|
40
|
+
@set[name] = block
|
41
|
+
end
|
42
|
+
def include(*mods)
|
43
|
+
(class << self; self; end).class_eval do
|
44
|
+
include *mods
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
module M
|
51
|
+
def m1; "m1"; end
|
52
|
+
module N
|
53
|
+
def self.n1; "n1"; end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
x = X.new do
|
58
|
+
|
59
|
+
include M
|
60
|
+
|
61
|
+
#Before /returns/ do |unit|
|
62
|
+
# puts "returns something"
|
63
|
+
#end
|
64
|
+
|
65
|
+
defset :m do
|
66
|
+
m1 == "m1"
|
67
|
+
end
|
68
|
+
|
69
|
+
defset :n do
|
70
|
+
N.n1 == "n1"
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
x.set[:m].call
|
76
|
+
x.set[:n].call
|