qed 2.1.1 → 2.2.0

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 (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