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.
Files changed (51) hide show
  1. data/.config/cucumber.yml +3 -0
  2. data/.gitignore +8 -0
  3. data/.reap/digest +678 -0
  4. data/.reap/test.reap +7 -0
  5. data/.ruby +42 -45
  6. data/Assembly +43 -0
  7. data/HISTORY.rdoc +10 -0
  8. data/MANIFEST +65 -0
  9. data/PROFILE +9 -6
  10. data/Rakefile +14 -0
  11. data/VERSION +1 -1
  12. data/lemon.gemspec +152 -0
  13. data/lib/lemon.yml +42 -45
  14. data/lib/lemon/cli.rb +4 -2
  15. data/lib/lemon/controller/test_runner.rb +4 -0
  16. data/lib/lemon/model/test_case.rb +122 -40
  17. data/notes/2010-05-05-coverage.rdoc +47 -0
  18. data/notes/2010-05-06-files_not_classes.rdoc +19 -0
  19. data/notes/2010-07-11-acid_testing.rdoc +52 -0
  20. data/notes/2010-08-02-enforcing-the-unit.md +68 -0
  21. data/notes/2010-08-03-new-api.md +37 -0
  22. data/site/.rsync-filter +8 -0
  23. data/site/assets/images/cut-lemon.png +0 -0
  24. data/site/assets/images/forkme.png +0 -0
  25. data/site/assets/images/github-logo.png +0 -0
  26. data/site/assets/images/lemon.jpg +0 -0
  27. data/site/assets/images/lemon.svg +39 -0
  28. data/site/assets/images/lemons-are-good.png +0 -0
  29. data/site/assets/images/opensource.png +0 -0
  30. data/site/assets/images/ruby-logo.png +0 -0
  31. data/site/assets/images/skin.jpg +0 -0
  32. data/site/assets/images/skin1.jpg +0 -0
  33. data/site/assets/images/tap.png +0 -0
  34. data/site/assets/images/title.png +0 -0
  35. data/site/assets/styles/class.css +6 -0
  36. data/site/assets/styles/reset.css +17 -0
  37. data/site/assets/styles/site.css +33 -0
  38. data/site/index.html +217 -0
  39. data/work/deprecated/command/abstract.rb +29 -0
  40. data/work/deprecated/command/coverage.rb +115 -0
  41. data/work/deprecated/command/generate.rb +124 -0
  42. data/work/deprecated/command/test.rb +112 -0
  43. data/work/reference/dsl2.rb +136 -0
  44. data/work/reference/dynamic_constant_lookup.rb +76 -0
  45. data/work/sandbox/lib/sample.rb +13 -0
  46. data/work/sandbox/test/sample_case.rb +12 -0
  47. data/work/trash/example-cover.rb +5 -0
  48. data/work/trash/example.rb +16 -0
  49. metadata +134 -101
  50. data/.yardopts +0 -7
  51. 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