qed 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/COPYING +622 -344
  2. data/DIARY.rdoc +117 -0
  3. data/HISTORY +36 -0
  4. data/PROFILE +16 -0
  5. data/README.rdoc +69 -36
  6. data/REQUIRE +9 -0
  7. data/ROADMAP +12 -0
  8. data/VERSION +5 -0
  9. data/demo/01_demos.rdoc +56 -0
  10. data/demo/02_advice.rdoc +158 -0
  11. data/demo/03_helpers.rdoc +42 -0
  12. data/demo/04_fixtures.rdoc +29 -0
  13. data/demo/05_quote.rdoc +24 -0
  14. data/demo/07_toplevel.rdoc +42 -0
  15. data/demo/08_cross_script.rdoc +27 -0
  16. data/demo/09_cross_script.rdoc +27 -0
  17. data/demo/10_constant_lookup.rdoc +16 -0
  18. data/demo/applique/constant.rb +2 -0
  19. data/demo/applique/env.rb +5 -0
  20. data/demo/applique/fileutils.rb +1 -0
  21. data/demo/applique/markup.rb +10 -0
  22. data/demo/applique/quote.rb +4 -0
  23. data/demo/applique/toplevel.rb +15 -0
  24. data/demo/fixtures/data.txt +1 -0
  25. data/demo/fixtures/table.yml +5 -0
  26. data/demo/helpers/advice.rb +40 -0
  27. data/demo/helpers/sample.rb +4 -0
  28. data/demo/helpers/toplevel.rb +6 -0
  29. data/eg/hello_world.rdoc +15 -0
  30. data/{demo/error.rdoc → eg/view_error.rdoc} +0 -0
  31. data/{demo → eg}/website.rdoc +0 -0
  32. data/lib/qed.rb +20 -1
  33. data/lib/qed/advice.rb +4 -30
  34. data/lib/qed/advice/events.rb +6 -3
  35. data/lib/qed/advice/patterns.rb +37 -19
  36. data/lib/qed/applique.rb +85 -0
  37. data/lib/qed/command.rb +3 -5
  38. data/lib/qed/evaluator.rb +52 -56
  39. data/lib/qed/package.yml +5 -0
  40. data/lib/qed/parser.rb +149 -0
  41. data/lib/qed/profile.yml +16 -0
  42. data/lib/qed/reporter/{base.rb → abstract.rb} +17 -19
  43. data/lib/qed/reporter/bullet.rb +14 -16
  44. data/lib/qed/reporter/dotprogress.rb +7 -6
  45. data/lib/qed/reporter/html.rb +21 -3
  46. data/lib/qed/reporter/verbatim.rb +28 -26
  47. data/lib/qed/scope.rb +98 -82
  48. data/lib/qed/script.rb +21 -69
  49. data/lib/qed/session.rb +44 -3
  50. data/script/qedoc +2 -0
  51. data/script/test +2 -0
  52. metadata +74 -28
  53. data/doc/qedoc/index.html +0 -515
  54. data/doc/qedoc/jquery.js +0 -19
  55. data/meta/authors +0 -1
  56. data/meta/created +0 -1
  57. data/meta/description +0 -2
  58. data/meta/homepage +0 -1
  59. data/meta/name +0 -1
  60. data/meta/released +0 -1
  61. data/meta/repository +0 -1
  62. data/meta/requires +0 -5
  63. data/meta/ruby +0 -2
  64. data/meta/suite +0 -1
  65. data/meta/summary +0 -1
  66. data/meta/title +0 -1
  67. data/meta/version +0 -1
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: QED
3
+ suite: proutils
4
+ summary: Quod Erat Demonstrandum
5
+ authors: Thomas Sawyer <transfire@gmail.com>
6
+ created: 2006-12-16
7
+
8
+ description:
9
+ QED (Quality Ensured Demonstrations) is a TDD/BDD framework
10
+ utilizing Literate Programming techniques.
11
+
12
+ resources:
13
+ home: http://proutils.github.com/qed
14
+ work: http://github.com/protuils/qed
15
+ repo: git://github.com/proutils/qed.git
16
+
@@ -4,18 +4,15 @@ module Reporter
4
4
  require 'facets/string'
5
5
  require 'ansi/code'
6
6
 
7
- # = Reporter BaseClass
7
+ # = Reporter Absract Base Class
8
8
  #
9
9
  # Serves as the base class for all other output formats.
10
10
  #
11
- class BaseClass
11
+ class Abstract
12
12
 
13
13
  attr :io
14
14
  attr :steps
15
15
  attr :omit
16
- attr :pass
17
- attr :fail
18
- attr :error
19
16
 
20
17
  def initialize(options={})
21
18
  @io = options[:io] || STDOUT
@@ -29,6 +26,10 @@ module Reporter
29
26
  @error = []
30
27
  end
31
28
 
29
+ def passes ; @pass ; end
30
+ def errors ; @error ; end
31
+ def failures ; @fail ; end
32
+
32
33
  #
33
34
  def trace?
34
35
  @trace
@@ -79,23 +80,16 @@ module Reporter
79
80
  @demos += 1
80
81
  end
81
82
 
82
- #
83
- def tag(element)
84
- end
85
-
86
83
  #
87
84
  def load(demo)
88
85
  end
86
+
89
87
  #
90
88
  def import(file)
91
89
  end
92
90
 
93
- # Before running a step.
94
- def element(step)
95
- end
96
-
97
- def comment(elem)
98
- end
91
+ #def comment(elem)
92
+ #end
99
93
 
100
94
  # Before running a step that is omitted.
101
95
  #def omit_step(step)
@@ -107,6 +101,14 @@ module Reporter
107
101
  @steps += 1
108
102
  end
109
103
 
104
+ # Right before running code.
105
+ def code(section)
106
+ end
107
+
108
+ # Right before text section.
109
+ def text(section)
110
+ end
111
+
110
112
  # After running a step that passed.
111
113
  def pass(step)
112
114
  @pass << step
@@ -127,10 +129,6 @@ module Reporter
127
129
  def after_code(step, file)
128
130
  end
129
131
 
130
- #
131
- def after_element(elem)
132
- end
133
-
134
132
  #
135
133
  def unload
136
134
  end
@@ -1,22 +1,20 @@
1
1
  module QED
2
2
  module Reporter #:nodoc:
3
3
 
4
- require 'qed/reporter/base'
4
+ require 'qed/reporter/abstract'
5
5
 
6
6
  # = Bullet Point Reporter
7
7
  #
8
- # Similar to the Verbatim reporter, but does
8
+ # Similar to the Verbose reporter, but does
9
9
  # not display test code for passing tests.
10
- class BulletPoint < BaseClass
10
+ class BulletPoint < Abstract
11
11
 
12
12
  #
13
- def tag(step)
14
- case step.name
15
- when 'pre'
16
- # none
17
- when /h\d/
18
- io.puts ANSI::Code.bold("#{step.text}\n")
19
- when 'p'
13
+ def text(step)
14
+ case step.text
15
+ when /^\=/
16
+ io.puts "#{step.text}".ansi(:bold)
17
+ else
20
18
  txt = step.text.to_s.strip.tabto(2)
21
19
  txt[0,1] = "*"
22
20
  io.puts txt
@@ -25,17 +23,17 @@ module Reporter #:nodoc:
25
23
  end
26
24
 
27
25
  def pass(step)
28
- #io.puts ANSICode.green("#{step}")
26
+ #io.puts "#{step}".ansi(:green)
29
27
  end
30
28
 
31
29
  def fail(step, assertion)
32
30
  msg = ''
33
31
  msg << " ##### FAIL #####\n"
34
32
  msg << " # " + assertion.to_s
35
- msg = ANSI::Code.magenta(msg)
33
+ msg = msg.ansi(:magenta)
36
34
  io.puts msg
37
35
  #io.puts
38
- io.puts ANSI::Code.red("#{step.text}")
36
+ io.puts "#{step.text}".ansi(:red)
39
37
  end
40
38
 
41
39
  def error(step, exception)
@@ -44,10 +42,10 @@ module Reporter #:nodoc:
44
42
  msg << " ##### ERROR #####\n"
45
43
  msg << " # " + exception.to_s + "\n"
46
44
  msg << " # " + clean_backtrace(exception.backtrace[0])
47
- msg = ANSI::Code.magenta(msg)
45
+ msg = msg.ansi(:magenta)
48
46
  io.puts msg
49
47
  #io.puts
50
- io.puts ANSI::Code.red("#{step.text}")
48
+ io.puts "#{step.text}".ansi(:red)
51
49
  end
52
50
 
53
51
  #def report(str)
@@ -69,7 +67,7 @@ module Reporter #:nodoc:
69
67
  # txt[0,1] = "*"
70
68
  # io.puts txt
71
69
  # #io.puts
72
- # #io.puts ANSICode.magenta("#{step}")
70
+ # #io.puts "#{step}".ansi(:magenta)
73
71
  #end
74
72
 
75
73
  end #class Summary
@@ -1,11 +1,11 @@
1
1
  module QED
2
2
  module Reporter #:nodoc:
3
3
 
4
- require 'qed/reporter/base'
4
+ require 'qed/reporter/abstract'
5
5
 
6
6
  # = DotProgress Reporter
7
7
  #
8
- class DotProgress < BaseClass
8
+ class DotProgress < Abstract
9
9
 
10
10
  #
11
11
  def before_session(session)
@@ -16,7 +16,8 @@ module Reporter #:nodoc:
16
16
  #
17
17
  def before_code(step, file)
18
18
  super(step, file)
19
- io.print "." if step.name == 'pre'
19
+ io.print "."
20
+ io.flush
20
21
  end
21
22
 
22
23
  #
@@ -25,7 +26,7 @@ module Reporter #:nodoc:
25
26
 
26
27
  @error.each do |step, exception|
27
28
  backtrace = clean_backtrace(exception.backtrace[0])
28
- io.puts ANSI::Code.red("***** ERROR *****")
29
+ io.puts "***** ERROR *****".ansi(:red)
29
30
  io.puts "#{exception}"
30
31
  io.puts ":#{backtrace}:"
31
32
  #io.puts ":#{exception.backtrace[1]}:"
@@ -35,8 +36,8 @@ module Reporter #:nodoc:
35
36
 
36
37
  @fail.each do |step, assertion|
37
38
  backtrace = clean_backtrace(assertion.backtrace[0])
38
- io.puts ANSI::Code.red("***** FAIL *****")
39
- io.puts ANSI::Code.bold("#{assertion}")
39
+ io.puts "***** FAIL *****".ansi(:red)
40
+ io.puts "#{assertion}".ansi(:bold)
40
41
  io.puts ":#{backtrace}:"
41
42
  #io.puts assertion if $VERBOSE
42
43
  io.puts
@@ -1,11 +1,29 @@
1
1
  module QED
2
- module Reporter #:nodoc:
2
+ module Reporter
3
3
 
4
- require 'qed/reporter/base'
4
+ require 'qed/reporter/abstract'
5
5
 
6
6
  # = Html Reporter
7
7
  #
8
- class Html < BaseClass
8
+ # TODO: This must be completely redesigned since we moved back
9
+ # to text based evaluation --which makes generting HTML with
10
+ # modifications from the evaluation tricky. But I've come up
11
+ # with a farily clever way to handle this. Take the original
12
+ # and use Tilt to translate it into HTML, then take the
13
+ # evaluation results for code steps and use it to search
14
+ # the HTML for "the closest match". Find the \<pre> tag
15
+ # associated with the text and add class and color style.
16
+ # Of course the tricky part is the matching, but if we
17
+ # run the text snippet through Tilt as well we should be
18
+ # able to get an exact match. It won't be fast, but it should
19
+ # work.
20
+
21
+ class Html < Abstract
22
+
23
+ #
24
+ def initialize(*args)
25
+ raise "HTML format is not currently working"
26
+ end
9
27
 
10
28
  #
11
29
  def pass(step)
@@ -1,44 +1,46 @@
1
1
  module QED
2
2
  module Reporter #:nodoc:
3
3
 
4
- require 'qed/reporter/base'
4
+ require 'qed/reporter/abstract'
5
5
 
6
6
  # = Verbose ANSI Console Reporter
7
7
  #
8
- class Verbatim < BaseClass
8
+ class Verbatim < Abstract
9
9
 
10
10
  #
11
- def tag(element)
12
- case element.name
13
- when 'pre'
14
- # none
15
- when /h\d/
16
- io.print ANSI::Code.bold("#{element.text.strip}\n\n")
17
- when 'p'
18
- io.print "#{element.text.strip}\n\n"
19
- #when 'a'
20
- # io.print element.to_s
21
- when 'ul', 'ol'
22
- io.print "\n"
23
- when 'li'
24
- io.print "* #{element.text.strip}\n"
11
+ def text(section)
12
+ case section.text
13
+ when /^\=/
14
+ io.puts "#{section.text}".ansi(:bold)
15
+ else
16
+ io.puts(section.text + "\n")
17
+ end
18
+ if !section.cont.empty?
19
+ section.cont.each do |c|
20
+ io.puts(c.ansi(:blue))
21
+ io.puts
22
+ end
25
23
  end
26
24
  end
27
25
 
26
+ # headers ?
27
+
28
28
  #
29
29
  def pass(step)
30
30
  txt = step.text.rstrip.sub("\n",'')
31
- io.print ANSI::Code.green("#{txt}\n\n")
31
+ io.print "#{txt}\n\n".ansi(:green)
32
32
  end
33
33
 
34
34
  #
35
35
  def fail(step, error)
36
36
  txt = step.text.rstrip.sub("\n",'')
37
37
  tab = step.text.index(/\S/) - 1
38
- io.print ANSI::Code.red("#{txt}\n\n")
38
+ io.print "#{txt}\n\n".ansi(:red)
39
39
  msg = []
40
- msg << ANSI::Code.bold(ANSI::Code.red("FAIL: ")) + error.to_str
41
- msg << ANSI::Code.bold(clean_backtrace(error.backtrace[0]))
40
+ #msg << ANSI::Code.bold(ANSI::Code.red("FAIL: ")) + error.to_str
41
+ #msg << ANSI::Code.bold(clean_backtrace(error.backtrace[0]))
42
+ msg << "FAIL: ".ansi(:bold, :red) + error.to_str
43
+ msg << clean_backtrace(error.backtrace[0]).ansi(:bold)
42
44
  io.puts msg.join("\n").tabto(tab||2)
43
45
  io.puts
44
46
  end
@@ -48,11 +50,11 @@ module Reporter #:nodoc:
48
50
  raise error if $DEBUG
49
51
  txt = step.text.rstrip.sub("\n",'')
50
52
  tab = step.text.index(/\S/) - 1
51
- io.print ANSI::Code.red("#{txt}\n\n")
53
+ io.print "#{txt}\n\n".ansi(:red)
52
54
  msg = []
53
- msg << ANSI::Code.bold(ANSI::Code.red("ERROR: ")) + error.to_str.sub(/for QED::Context.*?$/,'')
54
- msg << ANSI::Code.bold(clean_backtrace(error.backtrace[0]))
55
- #msg = ANSICode.red(msg)
55
+ msg << "ERROR: #{error.class} ".ansi(:bold,:red) + error.to_str #.sub(/for QED::Context.*?$/,'')
56
+ msg << clean_backtrace(error.backtrace[0]).ansi(:bold)
57
+ #msg = msg.ansi(:red)
56
58
  io.puts msg.join("\n").tabto(tab||2)
57
59
  io.puts
58
60
  end
@@ -65,14 +67,14 @@ module Reporter #:nodoc:
65
67
  #end
66
68
 
67
69
  #def report_table(set)
68
- # puts ANSICode.magenta(set.to_yaml.tabto(2))
70
+ # puts set.to_yaml.tabto(2).ansi(:magenta)
69
71
  #end
70
72
 
71
73
  #
72
74
  #def macro(step)
73
75
  # #io.puts
74
76
  # #io.puts step.text
75
- # io.print ANSICode.magenta("#{step}")
77
+ # io.print "#{step}".ansi(:magenta)
76
78
  # #io.puts
77
79
  #end
78
80
 
data/lib/qed/scope.rb CHANGED
@@ -1,102 +1,118 @@
1
- module QED
2
-
3
- require 'ae'
4
- require 'qed/advice'
1
+ require 'ae'
5
2
 
6
- # This module provides the QED syntax (domain specific language)
7
- # used to build QED documents.
3
+ module QED
8
4
 
9
- module DomainLanguage
5
+ # Scope is the context in which QED documents are run.
6
+ #
7
+ class Scope < Module
8
+
9
+ #
10
+ def self.new(applique)
11
+ @applique = applique
12
+ super(applique)
13
+ end
10
14
 
11
- include Advisable
15
+ #
16
+ def self.const_missing(name)
17
+ @applique.const_get(name)
18
+ end
12
19
 
13
- # Table-based steps.
14
- #--
15
- # TODO: Utilize HTML table element for tables.
16
- #++
17
- def Table(file=nil, &blk)
18
- file = file || @_tables.last
19
- tbl = YAML.load(File.new(file))
20
- tbl.each do |set|
21
- blk.call(*set)
22
- end
23
- @__tables__ ||= []
24
- @__tables__ << file
20
+ #
21
+ def initialize(applique)
22
+ super()
23
+ @applique = applique
24
+ extend self
25
+ extend applique # TODO: extend or include applique or none ?
26
+ #extend DSLi
27
+ create_clean_binding_method
25
28
  end
26
29
 
27
- # Read/Write a static data fixture.
28
- #--
29
- # TODO: Perhaps #Data would be best as some sort of Kernel extension.
30
- #++
31
- def Data(file, &content)
32
- raise if File.directory?(file)
33
- if content
34
- FileUtils.mkdir_p(File.dirname(fname))
35
- case File.extname(file)
36
- when '.yml', '.yaml'
37
- File.open(file, 'w'){ |f| f << content.call.to_yaml }
38
- else
39
- File.open(file, 'w'){ |f| f << content.call }
40
- end
41
- else
42
- #raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname)
43
- case File.extname(file)
44
- when '.yml', '.yaml'
45
- YAML.load(File.new(file))
46
- else
47
- File.read(file)
48
- end
30
+ # This turned out to be the key to proper scoping.
31
+ def create_clean_binding_method
32
+ define_method(:__binding__) do
33
+ @__binding__ ||= binding
49
34
  end
50
35
  end
51
36
 
52
- # Code match-and-transform procedure.
53
- #
54
- # This is useful to transform human readable code examples
55
- # into proper exectuable code. For example, say you want to
56
- # run shell code, but want to make if look like typical
57
- # shelle examples:
58
- #
59
- # $ cp fixture/a.rb fixture/b.rb
60
- #
61
- # You can use a transform to convert lines starting with '$'
62
- # into executable Ruby using #system.
63
- #
64
- # system('cp fixture/a.rb fixture/b.rb')
65
- #
66
- #def Transform(pattern=nil, &procedure)
67
- #
68
- #end
37
+ #module DSLi
69
38
 
70
- def __binding__
71
- binding
72
- end
39
+ #def initialize
40
+ # @__binding__ = binding
41
+ #end
73
42
 
74
- end
43
+ #def __binding__
44
+ # @__binding__
45
+ #end
75
46
 
76
- # Scope is the context in which QED documents are run.
77
- # Note, that Scope is now a facade over the TOPLEVEL.
47
+ #
48
+ #def __binding__
49
+ # @__binding__ ||= binding
50
+ #end
78
51
 
79
- class Scope
52
+ #
53
+ def eval(code)
54
+ super(code, __binding__)
55
+ end
80
56
 
81
- # Reroutes Scope instance to TOPLEVEL.
82
- def self.new
83
- @self ||= (
84
- TOPLEVEL_BINDING.eval("include QED::DomainLanguage")
85
- TOPLEVEL_BINDING.eval('self')
86
- )
87
- end
57
+ #
58
+ def When(*patterns, &procedure)
59
+ @applique.When(*patterns, &procedure)
60
+ end
88
61
 
89
- #include DomainLanguage
62
+ #
63
+ def Before(type=:code, &procedure)
64
+ @applique.Before(type, &procedure)
65
+ end
90
66
 
91
- #def initialize
92
- # @__binding__ = binding
93
- #end
67
+ #
68
+ def After(type=:code, &procedure)
69
+ @applique.After(type, &procedure)
70
+ end
71
+
72
+ # Table-based steps.
73
+ #--
74
+ # TODO: Look for files relative to script first?
75
+ #++
76
+ def Table(file=nil, &blk)
77
+ file = file || @_tables.last
78
+ tbl = YAML.load(File.new(file))
79
+ tbl.each do |set|
80
+ blk.call(*set)
81
+ end
82
+ @__tables__ ||= []
83
+ @__tables__ << file
84
+ end
85
+
86
+ # Read/Write a static data fixture.
87
+ #--
88
+ # TODO: Perhaps #Data would be best as some sort of Kernel extension.
89
+ #
90
+ # TODO: Look for files relative to script first?
91
+ #++
92
+ def Data(file, &content)
93
+ raise if File.directory?(file)
94
+ if content
95
+ FileUtils.mkdir_p(File.dirname(fname))
96
+ case File.extname(file)
97
+ when '.yml', '.yaml'
98
+ File.open(file, 'w'){ |f| f << content.call.to_yaml }
99
+ else
100
+ File.open(file, 'w'){ |f| f << content.call }
101
+ end
102
+ else
103
+ #raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname)
104
+ case File.extname(file)
105
+ when '.yml', '.yaml'
106
+ YAML.load(File.new(file))
107
+ else
108
+ File.read(file)
109
+ end
110
+ end
111
+ end
94
112
 
95
- #def __binding__
96
- # @__binding__
97
- #end
98
- end
113
+ #end#module DSL
99
114
 
100
- end
115
+ end#class Scope
101
116
 
117
+ end#module QED
102
118