lemon 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/HISTORY.rdoc +15 -0
  2. data/README.rdoc +32 -14
  3. data/bin/lemon +3 -2
  4. data/demo/case_example_fail.rb +15 -0
  5. data/demo/case_example_pass.rb +32 -0
  6. data/demo/case_example_pending.rb +14 -0
  7. data/demo/case_example_untested.rb +10 -0
  8. data/demo/fixture/example-use.rb +5 -0
  9. data/demo/fixture/example.rb +20 -0
  10. data/lib/lemon.rb +2 -2
  11. data/lib/lemon/cli.rb +281 -0
  12. data/lib/lemon/controller/coverage_analyzer.rb +343 -0
  13. data/lib/lemon/controller/scaffold_generator.rb +110 -0
  14. data/lib/lemon/controller/test_runner.rb +284 -0
  15. data/lib/lemon/meta/data.rb +29 -0
  16. data/lib/lemon/meta/gemfile +24 -0
  17. data/{PROFILE → lib/lemon/meta/profile} +6 -5
  18. data/lib/lemon/model/ae.rb +4 -0
  19. data/lib/lemon/model/cover_unit.rb +75 -0
  20. data/lib/lemon/{dsl.rb → model/main.rb} +22 -28
  21. data/lib/lemon/model/pending.rb +10 -0
  22. data/lib/lemon/model/snapshot.rb +203 -0
  23. data/lib/lemon/model/source_parser.rb +198 -0
  24. data/lib/lemon/model/test_case.rb +221 -0
  25. data/lib/lemon/model/test_context.rb +90 -0
  26. data/lib/lemon/model/test_suite.rb +216 -0
  27. data/lib/lemon/{test/unit.rb → model/test_unit.rb} +40 -28
  28. data/lib/lemon/{coversheet → view/cover_reports}/abstract.rb +19 -20
  29. data/lib/lemon/view/cover_reports/compact.rb +37 -0
  30. data/lib/lemon/view/cover_reports/outline.rb +45 -0
  31. data/lib/lemon/view/cover_reports/verbose.rb +51 -0
  32. data/lib/lemon/view/cover_reports/yaml.rb +15 -0
  33. data/lib/lemon/view/test_reports/abstract.rb +149 -0
  34. data/lib/lemon/view/test_reports/dotprogress.rb +73 -0
  35. data/lib/lemon/view/test_reports/html.rb +146 -0
  36. data/lib/lemon/view/test_reports/outline.rb +118 -0
  37. data/lib/lemon/view/test_reports/summary.rb +131 -0
  38. data/lib/lemon/view/test_reports/tap.rb +49 -0
  39. data/lib/lemon/view/test_reports/verbose.rb +197 -0
  40. data/meta/data.rb +29 -0
  41. data/meta/gemfile +24 -0
  42. data/meta/profile +17 -0
  43. data/test/api/applique/fs.rb +18 -0
  44. data/test/api/coverage/complete.rdoc +136 -0
  45. data/test/api/coverage/extensions.rdoc +61 -0
  46. data/test/api/coverage/incomplete.rdoc +97 -0
  47. data/{features → test/cli}/coverage.feature +4 -4
  48. data/{features → test/cli}/generate.feature +2 -2
  49. data/{features → test/cli}/step_definitions/coverage_steps.rb +0 -0
  50. data/{features → test/cli}/support/ae.rb +0 -0
  51. data/{features → test/cli}/support/aruba.rb +0 -0
  52. data/{features → test/cli}/test.feature +0 -0
  53. data/test/fixtures/case_complete.rb +17 -4
  54. data/test/fixtures/case_inclusion.rb +18 -0
  55. data/test/fixtures/case_incomplete.rb +4 -4
  56. data/test/fixtures/example.rb +5 -0
  57. data/test/fixtures/helper.rb +13 -0
  58. data/test/runner +3 -0
  59. data/test/unit/case_coverage_analyzer.rb +25 -0
  60. data/test/unit/case_test_case_dsl.rb +46 -0
  61. metadata +87 -42
  62. data/REQUIRE +0 -9
  63. data/VERSION +0 -6
  64. data/lib/lemon/command.rb +0 -184
  65. data/lib/lemon/coverage.rb +0 -260
  66. data/lib/lemon/coversheet/outline.rb +0 -47
  67. data/lib/lemon/kernel.rb +0 -24
  68. data/lib/lemon/reporter.rb +0 -22
  69. data/lib/lemon/reporter/abstract.rb +0 -97
  70. data/lib/lemon/reporter/dotprogress.rb +0 -68
  71. data/lib/lemon/reporter/outline.rb +0 -105
  72. data/lib/lemon/reporter/verbose.rb +0 -143
  73. data/lib/lemon/runner.rb +0 -308
  74. data/lib/lemon/snapshot.rb +0 -185
  75. data/lib/lemon/test/case.rb +0 -139
  76. data/lib/lemon/test/concern.rb +0 -52
  77. data/lib/lemon/test/suite.rb +0 -229
  78. data/test/case_coverage.rb +0 -26
  79. data/test/case_testcase.rb +0 -58
@@ -0,0 +1,37 @@
1
+ require 'lemon/view/cover_reports/abstract'
2
+
3
+ module Lemon::CoverReports
4
+
5
+ class Compact < Abstract
6
+
7
+ #
8
+ def render
9
+
10
+ unless covered_units.empty?
11
+ puts "\nCovered Units: "
12
+ puts covered_units.map{ |u| u.to_s.ansi(:green) }.sort.join(', ')
13
+ end
14
+
15
+ unless undefined_units.empty?
16
+ puts "\nOvercovered Units:"
17
+ puts undefined_units.map{ |u| u.to_s.ansi(:cyan) }.sort.join(', ')
18
+ end
19
+
20
+ unless uncovered_units.empty?
21
+ puts "\nUncovered Units: "
22
+ puts uncovered_units.map{ |u| u.to_s.ansi(:yellow) }.sort.join(', ')
23
+ end
24
+
25
+ unless uncovered_cases.empty?
26
+ puts "\nUncovered Cases: "
27
+ puts uncovered_cases.map{ |m| m.name.ansi(:red) }.sort.join(', ')
28
+ end
29
+
30
+ puts
31
+ puts tally
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,45 @@
1
+ require 'lemon/view/cover_reports/abstract'
2
+
3
+ module Lemon::CoverReports
4
+
5
+ class Outline < Abstract
6
+
7
+ #
8
+ def render
9
+
10
+ unless covered_units.empty?
11
+ puts "\nCovered Units:"
12
+ covered_units.map do |unit|
13
+ puts "* #{unit.to_s.ansi(:green)}"
14
+ end.join(", ")
15
+ end
16
+
17
+ unless uncovered_units.empty?
18
+ puts "\nUncovered Units:"
19
+ uncovered_units.map do |unit|
20
+ puts "* #{unit.to_s.ansi(:yellow)}"
21
+ end
22
+ end
23
+
24
+ unless undefined_units.empty?
25
+ puts "\nUndefined Units:"
26
+ unc = undefined_units.map do |unit|
27
+ puts "* #{unit.to_s.ansi(:red)}"
28
+ end
29
+ end
30
+
31
+ unless uncovered_cases.empty?
32
+ puts "\nUncovered Cases:"
33
+ uncovered_cases.map do |mod|
34
+ puts "* #{mod.name.ansi(:cyan)}"
35
+ end
36
+ end
37
+
38
+ puts
39
+ puts tally
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
@@ -0,0 +1,51 @@
1
+ require 'lemon/view/cover_reports/abstract'
2
+
3
+ module Lemon::CoverReports
4
+
5
+ class Verbose < Abstract
6
+
7
+ #
8
+ def render
9
+
10
+ unless covered_units.empty?
11
+ puts "\nCovered Cases: "
12
+ covered_units.map do |unit|
13
+ puts unit_line(unit, :green)
14
+ end
15
+ end
16
+
17
+ unless uncovered_units.empty?
18
+ puts "\nUncovered Units: "
19
+ uncovered_units.map do |unit|
20
+ puts unit_line(unit, :yellow)
21
+ end
22
+ end
23
+
24
+ unless undefined_units.empty?
25
+ puts "\nUndefined Units: "
26
+ undefined_units.map do |unit|
27
+ puts unit_line(unit, :red)
28
+ end
29
+ end
30
+
31
+ unless uncovered_cases.empty?
32
+ puts "\nUncovered Cases: "
33
+ uncovered_cases.map do |mod|
34
+ puts "* " + mod.name.to_s.ansi(:yellow)
35
+ end
36
+ end
37
+
38
+ puts
39
+ puts tally
40
+ end
41
+
42
+ #
43
+ def unit_line(unit, color)
44
+ data = [unit.to_s.ansi(color), unit.access.to_s, unit.function? ? 'function' : 'instance method']
45
+ "* %s %s %s" % data
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
@@ -0,0 +1,15 @@
1
+ require 'lemon/view/cover_reports/abstract'
2
+
3
+ module Lemon::CoverReports
4
+
5
+ class Yaml < Abstract
6
+
7
+ #
8
+ def render
9
+ puts checklist.to_yaml
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+
@@ -0,0 +1,149 @@
1
+ module Lemon::TestReports
2
+
3
+ # Test Reporter Base Class
4
+ class Abstract
5
+
6
+ require 'ansi/code'
7
+
8
+ #
9
+ def self.inherited(base)
10
+ registry << base
11
+ end
12
+
13
+ #
14
+ def self.registry
15
+ @registry ||= []
16
+ end
17
+
18
+ #
19
+ def initialize(runner)
20
+ @runner = runner
21
+ @source = {}
22
+ end
23
+
24
+ #
25
+ attr :runner
26
+
27
+ #
28
+ def start_suite(suite)
29
+ end
30
+
31
+ #
32
+ def start_case(instance)
33
+ end
34
+
35
+ #
36
+ #def instance(instance)
37
+ #end
38
+
39
+ #
40
+ def start_unit(unit)
41
+ end
42
+
43
+ # Report an omitted unit test.
44
+ def omit(unit)
45
+ end
46
+
47
+ #
48
+ def pass(unit)
49
+ end
50
+
51
+ #
52
+ def fail(unit, exception)
53
+ end
54
+
55
+ #
56
+ def error(unit, exception)
57
+ end
58
+
59
+ #
60
+ def finish_unit(testunit)
61
+ end
62
+
63
+ #
64
+ def finish_case(instance)
65
+ end
66
+
67
+ #
68
+ def finish_suite(suite)
69
+ end
70
+
71
+ private
72
+
73
+ def record ; runner.record ; end
74
+
75
+ # Is coverage information requested?
76
+ #def cover? ; runner.cover? ; end
77
+
78
+ #
79
+ def total
80
+ %w{pending pass fail error omit}.inject(0){ |s,r| s += record[r.to_sym].size; s }
81
+ end
82
+
83
+ #
84
+ def tally
85
+ sizes = %w{pending fail error omit pass}.map{ |r| record[r.to_sym].size }
86
+ data = [total] + sizes
87
+ s = "%s tests: %s pending, %s fail, %s err, %s omit, %s pass " % data
88
+ #s += "(#{uncovered_units.size} uncovered, #{undefined_units.size} undefined)" if cover?
89
+ s
90
+ end
91
+
92
+ #FILE_SEPARATOR = Regexp.escape(File::SEPARATOR)
93
+
94
+ #
95
+ INTERNALS = /(lib|bin)[\\\/]lemon/
96
+
97
+ # Clean the backtrace of any reference to ko/ paths and code.
98
+ def clean_backtrace(backtrace)
99
+ trace = backtrace.reject{ |bt| bt =~ INTERNALS }
100
+ trace.map do |bt|
101
+ if i = bt.index(':in')
102
+ bt[0...i]
103
+ else
104
+ bt
105
+ end
106
+ end
107
+ end
108
+
109
+ # Have to thank Suraj N. Kurapati for the crux of this code.
110
+ def code_snippet(exception, bredth=3)
111
+ backtrace = exception.backtrace.reject{ |bt| bt =~ INTERNALS }
112
+ backtrace.first =~ /(.+?):(\d+(?=:|\z))/ or return ""
113
+ source_file, source_line = $1, $2.to_i
114
+
115
+ source = source(source_file)
116
+
117
+ radius = bredth # number of surrounding lines to show
118
+ region = [source_line - radius, 1].max ..
119
+ [source_line + radius, source.length].min
120
+
121
+ # ensure proper alignment by zero-padding line numbers
122
+ format = " %2s %0#{region.last.to_s.length}d %s"
123
+
124
+ pretty = region.map do |n|
125
+ format % [('=>' if n == source_line), n, source[n-1].chomp]
126
+ end #.unshift "[#{region.inspect}] in #{source_file}"
127
+
128
+ pretty
129
+ end
130
+
131
+ #
132
+ def source(file)
133
+ @source[file] ||= (
134
+ File.readlines(file)
135
+ )
136
+ end
137
+
138
+ # TODO: Show more of the file name than just the basename.
139
+ def file_and_line(exception)
140
+ line = exception.backtrace[0]
141
+ return "" unless line
142
+ i = line.rindex(':in')
143
+ line = i ? line[0...i] : line
144
+ File.basename(line)
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -0,0 +1,73 @@
1
+ require 'lemon/view/test_reports/abstract'
2
+
3
+ module Lemon::TestReports
4
+
5
+ # Simple Dot-Progress Reporter
6
+ class Dotprogress < Abstract
7
+
8
+ def omit(unit)
9
+ print "O"; $stdout.flush
10
+ end
11
+
12
+ def pass(unit)
13
+ print "."; $stdout.flush
14
+ end
15
+
16
+ def fail(unit, exception)
17
+ print "F"
18
+ end
19
+
20
+ def error(unit, exception)
21
+ print "E"
22
+ end
23
+
24
+ def pending(unit, exception)
25
+ print "P"
26
+ end
27
+
28
+ def finish_suite(suite)
29
+ puts; puts
30
+
31
+ ## if verbose
32
+ unless record[:omit].empty?
33
+ puts "OMITTED:\n\n"
34
+ puts record[:omit].map{ |u| u.to_s }.sort.join(' ')
35
+ puts
36
+ end
37
+ ## end
38
+
39
+ unless record[:pending].empty?
40
+ puts "PENDING:\n\n"
41
+ record[:pending].each do |testunit, exception|
42
+ puts " #{testunit}"
43
+ end
44
+ puts
45
+ end
46
+
47
+ unless record[:fail].empty?
48
+ puts "FAILURES:\n\n"
49
+ record[:fail].each do |testunit, exception|
50
+ puts " #{testunit}"
51
+ puts " #{exception}"
52
+ puts " #{exception.backtrace[0]}"
53
+ puts
54
+ end
55
+ end
56
+
57
+ unless record[:error].empty?
58
+ puts "ERRORS:\n\n"
59
+ record[:error].each do |testunit, exception|
60
+ puts " #{testunit}"
61
+ puts " #{exception}"
62
+ puts " #{exception.backtrace[0]}"
63
+ puts
64
+ end
65
+ end
66
+
67
+ puts tally
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
@@ -0,0 +1,146 @@
1
+ require 'lemon/view/test_reports/abstract'
2
+
3
+ module Lemon::TestReports
4
+
5
+ # HTML Test Reporter
6
+ #
7
+ # TODO: Make this more like a microformat and add timer info.
8
+ class Html < Abstract
9
+
10
+ #
11
+ def start_suite(suite)
12
+ timer_reset
13
+ @html = []
14
+ @html << %[<html>]
15
+ @html << %[<head>]
16
+ @html << %[<title>Unit Test Report</title>]
17
+ @html << %[ <style>]
18
+ @html << %[ html{ background: #fff; margin: 0; padding: 0; font-family: helvetica; }]
19
+ @html << %[ body{ margin: 0; padding: 0;}]
20
+ @html << %[ h3{color:#555;}]
21
+ @html << %[ #main{ margin: 0 auto; color: #110; width: 600px; ]
22
+ @html << %[ border-right: 1px solid #ddd; border-left: 1px solid #ddd; ]
23
+ @html << %[ padding: 10px 30px; width: 500px; } ]
24
+ @html << %[ .lemon{ color: gold; font-size: 22px; font-weight: bold; ]
25
+ @html << %[ font-family: courier; margin-bottom: -15px;}]
26
+ @html << %[ .tally{ font-weight: bold; margin-bottom: 10px; }]
27
+ @html << %[ .omit{ color: cyan; }]
28
+ @html << %[ .pass{ color: green; }]
29
+ @html << %[ .fail{ color: red; }]
30
+ @html << %[ .footer{ font-size: 0.7em; color: #666; margin: 20px 0; }]
31
+ @html << %[ </style>]
32
+ @html << %[</head>]
33
+ @html << %[<body>]
34
+ @html << %[<div id="main">]
35
+ @html << %[<div class="lemon">L E M O N</div>]
36
+ @html << %[<h1>Unit Test Report</h1>]
37
+ @body = []
38
+ end
39
+
40
+ #
41
+ def start_case(tc)
42
+ @body << "<h2>"
43
+ @body << tc.to_s
44
+ @body << "</h2>"
45
+ end
46
+
47
+ #
48
+ def instance(instance)
49
+ @body << "<h3>"
50
+ @body << "#{instance}"
51
+ @body << "</h3>"
52
+ end
53
+
54
+ #
55
+ def start_unit(unit)
56
+ instance = unit.instance
57
+ if @instance != instance
58
+ @instance = instance
59
+ instance(instance)
60
+ end
61
+ end
62
+
63
+ #
64
+ def omit(unit)
65
+ @body << %[<li class="omit">]
66
+ @body << " %s %s %s" % ["OMIT", unit.name, unit.aspect]
67
+ @body << %[</li>]
68
+ end
69
+
70
+ #
71
+ def pass(unit)
72
+ @body << %[<li class="pass">]
73
+ @body << "%s %s %s" % ["PASS", unit.name, unit.aspect]
74
+ @body << %[</li>]
75
+ end
76
+
77
+ #
78
+ def fail(unit, exception)
79
+ @body << %[<li class="fail">]
80
+ @body << "%s %s %s" % ["FAIL", unit.name, unit.aspect]
81
+ @body << "<pre>"
82
+ @body << " FAIL #{exception.backtrace[0]}"
83
+ @body << " #{exception}"
84
+ @body << "</pre>"
85
+ @body << %[</li>]
86
+ end
87
+
88
+ #
89
+ def error(unit, exception)
90
+ @body << %[<li class="error">]
91
+ @body << "%s %s %s" % ["ERROR", unit.name, unit.aspect]
92
+ @body << "<pre>"
93
+ @body << " ERROR #{exception.class}"
94
+ @body << " #{exception}"
95
+ @body << " " + exception.backtrace.join("\n ")
96
+ @body << "</pre>"
97
+ @body << %[</li>]
98
+ end
99
+
100
+ #
101
+ def pending(unit, exception)
102
+ @body << %[<li class="pending">]
103
+ @body << " %s %s %s" % ["PENDING", unit.name, unit.aspect]
104
+ @body << %[</li>]
105
+ end
106
+
107
+ #
108
+ def finish_suite(suite)
109
+ @html << ""
110
+ @html << %[<div class="tally">]
111
+ @html << tally
112
+ @html << %[</div>]
113
+ @html << ""
114
+
115
+ @body << ""
116
+ @body << %[<div class="footer">]
117
+ @body << %[Generated by <a href="http://proutils.github.com/lemon">Lemon</a>]
118
+ @body << %[on #{Time.now}.]
119
+ @body << %[</div>]
120
+ @body << ""
121
+ @body << %[</div>]
122
+ @body << %[</div>]
123
+ @body << ""
124
+ @body << %[</body>]
125
+ @body << %[</html>]
126
+
127
+ puts @html.join("\n")
128
+ puts @body.join("\n")
129
+ end
130
+
131
+ #
132
+ def timer
133
+ secs = Time.now - @time
134
+ @time = Time.now
135
+ return "%0.5fs" % [secs.to_s]
136
+ end
137
+
138
+ #
139
+ def timer_reset
140
+ @time = Time.now
141
+ end
142
+
143
+ end
144
+
145
+ end
146
+