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,42 @@
1
+ = Helpers
2
+
3
+ There are two ways to load advice scripts. Either per
4
+ demonstration or globally. Per demonstration helpers
5
+ apply only to the current demonstration. Global helpers
6
+ apply to all demonstrations.
7
+
8
+ == Global Helpers
9
+
10
+ Global helpers are loaded at the start of a session and
11
+ apply equally to all demonstrations in a suite. Global
12
+ helpers are simply Ruby scripts and are placed in an
13
+ +environment+ subdirectory. For instance this document
14
+ is used <a href="environment/env.rb">environment/env.rb</a>.
15
+
16
+ == Local Helpers
17
+
18
+ Helper scripts can be written just like demonstration scripts,
19
+ or they can be defined as pure Ruby scripts. Either way
20
+ they are loaded per-demonstration by using specially
21
+ marked links.
22
+
23
+ For example, because this link, Advice[qed://helpers/advice.rb],
24
+ begins with +qed:+, it will be used to load a global
25
+ helper. We can see this with the following:
26
+
27
+ pudding.assert.include?('load advice.rb')
28
+
29
+ No where in the demonstration have we defined +pudding+, but
30
+ it has been defined for us in the advice.rb helper script.
31
+
32
+ We can also see that the generic When clause in our advice
33
+ helper is keeping count of descriptions. Since the helper
34
+ script was loaded three paragraphs back, the count will be 3.
35
+
36
+ count.assert == 3
37
+
38
+ Helpers are vital to building test-demonstration suites for
39
+ applications. But here again, only use them as necessary.
40
+ The more helpers you use the more difficult your demos will
41
+ be to follow.
42
+
@@ -0,0 +1,29 @@
1
+ = Fixtures
2
+
3
+ == Flat-file Data
4
+
5
+ When creating testable demonstrations, there are times when sizable
6
+ chunks of data are needed. It is convenient to store such data in
7
+ separate files. The +Data+ method makes is easy to load such files.
8
+
9
+ Data('demo/fixtures/data.txt').assert =~ /dolor/
10
+
11
+ All files are found relative to the location of current document.
12
+
13
+ == Tabular Data
14
+
15
+ The +Table+ method is similar to the +Data+ method except that it
16
+ expects a YAML file, and it can take a block to iterate the data over.
17
+ This makes it easy to test tables of examples.
18
+
19
+ The arity of the table block corresponds to the number of columns in
20
+ each row of the table. Each row is assigned in turn and run through
21
+ the coded step. Consider the following example:
22
+
23
+ Every row in the {table.yml table}[table.yml] will be assigned to
24
+ the block parameters and run through the subsequent assertion.
25
+
26
+ Table 'demo/fixtures/table.yml' do |x, y|
27
+ x.upcase.assert == y
28
+ end
29
+
@@ -0,0 +1,24 @@
1
+ = Quotes
2
+
3
+ We do not always want verbatum clauses to be interpreted as code.
4
+ Sometimes it would more useful to trest them a plan text to
5
+ which the preceeding paragraph can make use in a processing rule.
6
+
7
+ For example let say we want to make an example out of the following
8
+ text...
9
+
10
+ The file will contain
11
+
12
+ this text
13
+
14
+ The use of the ellipsis ('...') tells the processor that the next
15
+ segment is a continuation of the current segment. If the next segment
16
+ is varbatum it will be added to the end of the arguments list of
17
+ any applicable processing rule.
18
+
19
+ Behind the scenes we created a rule to set the text to an instance
20
+ variable called @quote_text, as we can now verify:
21
+
22
+ @quote_text.assert == "The file will contain\n\nthis text"
23
+
24
+
@@ -0,0 +1,42 @@
1
+ = Toplevel Simulation
2
+
3
+ QED simulates Ruby's TOPLEVEL environment in both the Demonstrandum
4
+ and the Applique contexts. This serves two important purposes.
5
+ First, it provides the tester the environment that is most intutive.
6
+ And second, and more importantly, it stays out of the actual
7
+ TOPLEVEL space to prevent any potential interferece with any of
8
+ the code it is intended to test.
9
+
10
+ Let's look at some examples. For starters, we have access to a class
11
+ defined at the "toplevel" in the applique.
12
+
13
+ ToplevelClass
14
+
15
+ We can also call a method defined in the toplevel.
16
+
17
+ toplevel_method.assert == true
18
+
19
+ At the demonstrandum level we can define reusable methods.
20
+
21
+ def demo_method
22
+ true
23
+ end
24
+
25
+ demo_method.assert == true
26
+
27
+ And at the demonstrandum level even singleton methods are accessible.
28
+
29
+ def self.singleton_method; true; end
30
+
31
+ singleton_method.assert == true
32
+
33
+ QED uses a self-extend modules to achieve this simulation, so the
34
+ contexts are in fact a bit more capable then even Ruby's TOPLEVEL.
35
+ For instance, #define_method can be used.
36
+
37
+ define_method(:named_method){ true }
38
+
39
+ named_method.assert == true
40
+
41
+
42
+
@@ -0,0 +1,27 @@
1
+ = Cross-Scripting Setup
2
+
3
+ We define some variables here to make sure it is
4
+ not visible in the next script.
5
+
6
+ Let's set two local variables.
7
+
8
+ a = 100
9
+ b = 200
10
+
11
+ And two instance varaibles.
12
+
13
+ @a = 1000
14
+ @b = 2000
15
+
16
+ Also let check how it effect constants.
17
+
18
+ CROSS_SCRIPT_CONSTANT = "cross?"
19
+
20
+ And a method.
21
+
22
+ def cross_script_method
23
+ "common"
24
+ end
25
+
26
+
27
+
@@ -0,0 +1,27 @@
1
+ = Cross-Scripting Check
2
+
3
+ Make sure local and instance variables from previous
4
+ QED scripts are not visible in this document.
5
+
6
+ expect NameError do
7
+ a.assert = 100
8
+ b.assert = 200
9
+ end
10
+
11
+ And two instance_varaibles
12
+
13
+ @a.assert! == 1000
14
+ @b.assert! == 2000
15
+
16
+
17
+ Method definitions also do not cross QED scripts.
18
+
19
+ expect NameError do
20
+ cross_script_method
21
+ end
22
+
23
+ Constants, on the other hand, like global variables do make
24
+ their way across.
25
+
26
+ CROSS_SCRIPT_CONSTANT.assert == "cross?"
27
+
@@ -0,0 +1,16 @@
1
+ = Missing Constant
2
+
3
+ If a constant is missing it is because it was not found
4
+ in either the demos scope, the applique or the toplevel.
5
+
6
+ begin
7
+ UnknownConstant
8
+ rescue => err
9
+ # no colon means toplevel
10
+ /[^:]UnknownConstant/ =~ err.message
11
+ end
12
+
13
+ A constant defined in the applique is visible.
14
+
15
+ APPLIQUE_CONSTANT.assert = true
16
+
@@ -0,0 +1,2 @@
1
+ APPLIQUE_CONSTANT = true
2
+
@@ -0,0 +1,5 @@
1
+ Before do
2
+ @steps ||= 0
3
+ @steps += 1
4
+ end
5
+
@@ -0,0 +1 @@
1
+ require 'tmpdir'
@@ -0,0 +1,10 @@
1
+ When "lets say we have", "document called (((.*?))) with the following contents" do |file, text|
2
+ file = Dir.tmpdir + '/sow/examples/' + file
3
+ FileUtils.mkdir_p(File.dirname(file))
4
+ File.open(file, 'w'){ |f| f << text }
5
+ end
6
+
7
+ When 'when we run these examples' do
8
+ Dir.chdir(Dir.tmpdir + '/sow/examples/')
9
+ end
10
+
@@ -0,0 +1,4 @@
1
+ When "we want to make an example out of the following text" do |text|
2
+ @quote_text = text
3
+ end
4
+
@@ -0,0 +1,15 @@
1
+
2
+ # Define a toplevel class to ensure it is accessible.
3
+ class ToplevelClass
4
+ end
5
+
6
+ # Define a toplevel method to ensure it is also accessible.
7
+ def toplevel_method
8
+ true
9
+ end
10
+
11
+ # Define a toplevel method to ensure it is also accessible.
12
+ def self.toplevel_singleton_method
13
+ true
14
+ end
15
+
@@ -0,0 +1 @@
1
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -0,0 +1,5 @@
1
+ ---
2
+ - [ try , TRY ]
3
+ - [ me , ME ]
4
+ - [ mc , MC ]
5
+
@@ -0,0 +1,40 @@
1
+ # This helper is used to demonstrate
2
+ # the use of advice --before, after
3
+ # and when clauses.
4
+
5
+ count = 0
6
+ pudding = []
7
+
8
+ When(:load) do
9
+ pudding << "load #{File.basename(__FILE__)}"
10
+ end
11
+
12
+ When(:unload) do
13
+ pudding << "unload #{File.basename(__FILE__)}"
14
+ end
15
+
16
+ #Before do
17
+ # pudding << :before_step
18
+ #end
19
+
20
+ #After do
21
+ # pudding << :after_step
22
+ #end
23
+
24
+ When /.*?/ do
25
+ count += 1
26
+ end
27
+
28
+ When /proof is in the pudding/ do
29
+ pudding << 'proof'
30
+ end
31
+
32
+ #When /proof is in the pussing/ do
33
+ # pudding << :proof
34
+ #end
35
+
36
+ #
37
+ def prepare_example
38
+ "Hello, World!"
39
+ end
40
+
@@ -0,0 +1,4 @@
1
+ #require 'ae/should'
2
+ puts "This is just here to demonstrate that helpers are loaded."
3
+ puts
4
+
@@ -0,0 +1,6 @@
1
+ class ToplevelExample
2
+ def foo
3
+ "foo"
4
+ end
5
+ end
6
+
@@ -0,0 +1,15 @@
1
+ = Hello World
2
+
3
+ Did you know that famous `Hello World` moniker is
4
+ eleven characters long?
5
+
6
+ "Hello World".size.assert == 11
7
+
8
+ To pass a piece of literal text on with a description
9
+ we simply need to end it with a ...
10
+
11
+ Now this text will appear verbatim.
12
+ In the applique arguments.
13
+
14
+ That's all.
15
+
File without changes
File without changes
data/lib/qed.rb CHANGED
@@ -1,5 +1,24 @@
1
+ require 'yaml'
2
+
1
3
  module QED
2
- VERSION="2.1.1" #:till: VERSION="<%= version %>"
4
+ DIRECTORY = File.dirname(__FILE__) + '/qed'
5
+
6
+ PROFILE = YAML.load(File.new(DIRECTORY + '/profile.yml')) rescue {}
7
+ PACKAGE = YAML.load(File.new(DIRECTORY + '/package.yml')) rescue {}
8
+
9
+ VERSION = PACKAGE.values_at('major','minor','patch','build').compact.join('.')
10
+
11
+ #
12
+ def self.const_missing(name)
13
+ key = name.to_s.downcase
14
+ if PACKAGE.key?(key)
15
+ PACKAGE[key]
16
+ elsif PROFILE.key?(key)
17
+ PROFILE[key]
18
+ else
19
+ super(name)
20
+ end
21
+ end
3
22
  end
4
23
 
5
24
  require 'qed/session'
data/lib/qed/advice.rb CHANGED
@@ -8,7 +8,7 @@ module QED
8
8
  # This class tracks advice defined by demo scripts
9
9
  # and helpers. It is instantiated in Scope, so that
10
10
  # the advice methods will have access to the same
11
- # local binding and the demo scripts themselves.
11
+ # local binding and the scripts themselves.
12
12
  #
13
13
  class Advice
14
14
 
@@ -21,41 +21,15 @@ module QED
21
21
  @events = Events.new
22
22
  end
23
23
 
24
- def call(type, *args)
24
+ def call(scope, type, *args)
25
25
  case type
26
26
  when :when
27
- @patterns.call(*args)
27
+ @patterns.call(scope, *args)
28
28
  else
29
- @events.call(type, *args)
29
+ @events.call(scope, type, *args)
30
30
  end
31
31
  end
32
32
  end
33
33
 
34
- #
35
- module Advisable
36
-
37
- def __advice__
38
- @__advice__ ||= Advice.new
39
- end
40
-
41
- def When(pattern, &procedure)
42
- case pattern
43
- when Symbol
44
- __advice__.events.add(:"#{pattern}", &procedure)
45
- else
46
- __advice__.patterns.add(pattern, &procedure)
47
- end
48
- end
49
-
50
- def Before(type=:code, &procedure)
51
- __advice__.events.add(:"before_#{type}", &procedure)
52
- end
53
-
54
- def After(type=:code, &procedure)
55
- __advice__.events.add(:"after_#{type}", &procedure)
56
- end
57
-
58
- end
59
-
60
34
  end
61
35
 
@@ -2,7 +2,8 @@ module QED
2
2
 
3
3
  class Advice
4
4
 
5
- # Event advice: Before, After and Upon.
5
+ # This class encapsulates advice on symbolic targets,
6
+ # such as Before, After and Upon.
6
7
  #
7
8
  class Events
8
9
 
@@ -20,10 +21,12 @@ module QED
20
21
  end
21
22
 
22
23
  #
23
- def call(type, *args)
24
+ def call(scope, type, *args)
25
+
24
26
  @signals.each do |set|
25
27
  proc = set[type.to_sym]
26
- proc.call(*args) if proc
28
+ #proc.call(*args) if proc
29
+ scope.instance_exec(*args, &proc) if proc
27
30
  end
28
31
  end
29
32