lemon 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|