attest 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +6 -1
  3. data/README.rdoc +121 -36
  4. data/Rakefile +12 -1
  5. data/VERSION +1 -1
  6. data/attest.gemspec +61 -36
  7. data/bin/attest +18 -24
  8. data/doodle.txt +73 -29
  9. data/examples/{magic_calculator.rb → basic_functionality_example.rb} +42 -8
  10. data/examples/mocha_example.rb +43 -0
  11. data/examples/module_example.rb +49 -0
  12. data/examples/more/{placeholder.rb → multiple_context_example.rb} +0 -0
  13. data/examples/more/nesting/expectations_as_tests_example.rb +20 -0
  14. data/lib/attest.rb +4 -20
  15. data/lib/attest/config.rb +3 -6
  16. data/lib/attest/core_ext/kernel.rb +19 -1
  17. data/lib/attest/core_ext/object.rb +1 -2
  18. data/lib/attest/core_ext/proc.rb +35 -0
  19. data/lib/attest/execution_context.rb +156 -50
  20. data/lib/attest/expectation_result.rb +22 -1
  21. data/lib/attest/interface/output_writer_configurator.rb +25 -0
  22. data/lib/attest/interface/possible_tests_configurator.rb +35 -0
  23. data/lib/attest/interface/test_double_configurator.rb +40 -0
  24. data/lib/attest/output/basic_output_writer.rb +14 -46
  25. data/lib/attest/output/failures_only_output_writer.rb +47 -0
  26. data/lib/attest/output/output_writer.rb +124 -0
  27. data/lib/attest/output/output_writer_interface.rb +24 -0
  28. data/lib/attest/output/test_unit_output_writer.rb +32 -0
  29. data/lib/attest/proc/proc_source_reader.rb +49 -0
  30. data/lib/attest/rake/attesttask.rb +38 -0
  31. data/lib/attest/test_container.rb +15 -4
  32. data/lib/attest/test_loader.rb +28 -0
  33. data/lib/attest/test_object.rb +35 -29
  34. data/lib/attest/test_parser.rb +69 -11
  35. data/lib/trollop.rb +782 -0
  36. data/spec/interface/output_writer_configurator_test.rb +18 -0
  37. data/spec/interface/possible_tests_configurator_test.rb +55 -0
  38. data/spec/interface/test_double_configurator_test.rb +20 -0
  39. data/spec/output/output_writer_test.rb +20 -0
  40. data/spec/tmp/new_require_test.rb +10 -0
  41. metadata +55 -18
  42. data/.gitignore +0 -23
  43. data/examples/standard_calculator.rb +0 -28
  44. data/lib/attest/attest_error.rb +0 -7
  45. data/lib/attest/itself.rb +0 -34
data/doodle.txt CHANGED
@@ -93,50 +93,94 @@ most basic
93
93
  - don't print summaries after every context, only a totals summary at the end DONE
94
94
  - make it so that tests can take an options hash and one of the options should be to not run setup or teardown for the test, perhaps make it not part of the opts hash DONE
95
95
  - should be able to specify a test without a body for it to appear in the output as pending DONE
96
- - refactor all example code so it is a bit nicer and more representative
97
- - once all the above are done, create some RDOC documentation to describe the basic features and usage of the framework
98
- - also fix up the description and extended description, make sure everything looks proper as far as doco is concerned on github etc.
99
- - if everything is ok at this point, do a first public release of the gem (give it an appropriately betaish version number)
100
- - make sure the gem is available through rubyforge as well as wherever else is appropriate, e.g. gemcutter
96
+ - refactor all example code so it is a bit nicer and more representative DONE
97
+ - once all the above are done, create some RDOC documentation to describe the basic features and usage of the framework DONE
98
+ - also fix up the description and extended description, make sure everything looks proper as far as doco is concerned on github etc. DONE
99
+ - if everything is ok at this point, do a first public release of the gem (give it an appropriately betaish version number) DONE
100
+ - make sure the gem is available through rubyforge as well as wherever else is appropriate, e.g. gemcutter DONE
101
101
 
102
102
 
103
- - when committing need to make sure there is a valid gemspec
104
- - when used with bundler dependencies like trollop don't come trhough so can't execute attest properly get an error instead need to detect if being used via bundler and do a bundle setup etc.
105
-
106
103
  next release
107
104
 
108
- - integrate mocha so that can mock using mocha
109
- - output calculations of expectations not just tests
110
- - allow expectations to be specified directly as tests (perhaps failures should contain the block that has failed)
111
- - create a failures only output writer and allow it to be configured
112
- - create a test/unit style output writer and allow it to be configured
113
- - test out with method missing defined on the class, does it still work ok
114
- - make sure if method missing is defined it is tried out first before the new_method_missing on kernel takes over
115
- - should be able to disable a test so that it is not executed, but is listed as disabled in the output
105
+ $ test out with method missing defined on the class, does it still work ok, essentially call the original method missing first, catch appropriate exception out of there and then run my method missing code and if still no good then propagate the original exception DONE
106
+ $ make sure if method missing is defined it is tried out first before the new_method_missing on kernel takes over (this is very similar to the one above), need a test here
107
+ $ integrate mocha so that can mock using mocha, this should be relatively straight forward DONE
108
+ $ mocha should be set up as a configurable parameter even though it will be the only test double capability available DONE
109
+ $ try out using mocha within the framework on another project totally separate, to nut out how it should be not made a runtime dependency but can be used when pulled in to the other project as a development dependency or a default dependency, also if not using bundler at all and it is not installed, what happens DONE
110
+ $ refactor how mocha gets included into the project DONE
111
+ $ make sure the binary is only used to read the command line and calls down to other methods to actually load the test files and begin execution of all the tests including outputting the summary at the end DONE
112
+ $ output calculations of expectations not just tests, relatively straight forward and is a good idea DONE
113
+ $ allow expectations to be specified directly as tests (perhaps failures should contain the block that has failed), the test passes and fails and the floating expectation passes and fails will probably need to be reported separately DONE
114
+ $ if we get a test failure, perhaps more of a message regarding where/why the failure occured i.e. which expectation actually failed DONE
115
+ $ create a failures only output writer DONE
116
+ $ create a test/unit style output writer the one with the dots DONE
117
+ $ allow the different types of output writer to be configured as the one to use via command line parameter DONE
118
+ $ should be able to disable a test so that it is not executed, but is listed as disabled in the output DONE
119
+ $ refactor the command line handling to split out actual cli stuff from the attest code that acts on the cli params DONE
120
+ $ should be able to configure attest to be used without any test double framework at all DONE
121
+ $ create a better examples directory more consistent test naming etc DONE
122
+ $ combine assertion reporting and test reporting, we only really care about assertion reporting, no need to print out separate line for both DONE
123
+ $ ability to provide multiple directories, files from which to pull the possible tests DONE
124
+ $ ability to provide multiple directories, file which should be excluded from possible tests DONE
125
+ $ need to refactor my execution context for less duplication and more consistency DONE
126
+ $ rename before_all to be before each DONE
127
+ $ need a before_each and a before_all which gets executed before all the test in the group, currently have a before_all which really acts like a before_each not good DONE
128
+ $ possible bug or unexpected feature, if test contains no assertions in the output then it is treated by the output writer as having an implicit assertion/expectation (a success expectation) this is ok I think DONE
129
+ $ currently unable to specify expectations in before_all and after_all and have them be picked up, this should work, expectations should belong to the test container rather than to any specific test object, on second thoughts maybe shouldn't have expectations on before and after all DONE
130
+ $ should be able to specify expectations on the before_each and after_each DONE
131
+ $ more different types of expectations, should_equal(5){5}, should_not_equal, should_be_same(obj), should_be_same_as, should_not_be_same, should_not_be_same_as, should_not_fail, should_pass, should_be_around(6){5}.plus_minus(1), should_be_a/an(some_lambda){"hello"}, should_match/should_match_a/should_match_an, more thought regarding how to specify a custom matcher, something for arrays and hashes, should_include(some_array), perhaps ability to do blocks and do without blocks i.e. should_include(5, some_array) DONE
132
+ $ refactor expectations so that they can be used without a block but simply with parameters DONE
133
+ $ need to refactor my output writers to extract all common functionality so that there isn't so much code duplication (perhaps using modules or something) DONE
134
+ $ create a rake task that can be easily configured into a rake file with all the relevant configuration values so that attest can be run through rake instead of just the command line DONE
135
+ $ timing for how long it took to complete the whole test suite DONE
136
+ $ better failure reporting DONE
137
+ $ modify the readme, mention the problems wil inline test definition, mention the new expectations, mentiont about the new output writers, mention how output reporting works, disabled tests, test double framework configuration, inclusion and exclusion, before_all and before_each, mention the rake task DONE
138
+
139
+
140
+ $ BUG: I think I am now counting expectations passes rather than test passes, since i am getting ran 6 test 7 successful for mocka tests, need to look into this further DONE
141
+
142
+ $ POC perhaps hold off until next release, ability to actually convert a block to a string to be able to provide more information regarding what actually failed, essentially will need proc.to_s code DONE
143
+ $ POC remove trollop as a dependency to minimize dependecies, either that, or pull the trollop code in directly to minimize on dependecies, see if it's possible to easily acomplish this with git, if not then just manual DONE
144
+ - POC once test double functionality is in, see what we can do about writing some tests for this framework using itself, even a minimal test suite will be better than nothing
145
+ $ POC rake task that can easily be configured in a project to configure all the moving parts and run attest via rake (e.g. rake attest) DONE
146
+ - POC expectations on objects themselves, see if this can be done in such a way as to make it possible to include that bit separately via a separate require or command line paramter or rake config or all of the above
147
+ - POC hook in autotest somehow
148
+ - POC write some smarts about requiring things maybe even do this as a separate gem similar to require_all but with even more smarts and potential configurations call it require_bot
149
+ - POC own test double framework first only for ability to simply provide stubs, also ability to do mocks that verify expected behaviour, possibly two modes, one that complains when unexpected methods are called within test methods, the other mode is the opposite, is fine with unexpected methods, but complains when expected methods are not called, mock and stub class and instance methods, mock on just one object or all objects of the type, probably should be its own gem as well
150
+ $ POC support to allow more traditional i.e. non-inline creating of test in which case perhaps the if env block should not be necessary, tests will live in an attest directory, whatever once again should work via executable as well as rake task, all the smarts that we need to get this to happen DONE
116
151
 
117
152
  next release 2
118
153
 
154
+ - figure out if mocha works properly when using bundler, my guess it will not
155
+ - need to be able to define helper methods within tests somehow that can be called from within tests and setups etc.
156
+ - timing for each test as well as each container should be recorded even if not outputted
157
+ - refactor the duplication between the attest executable in bin and the attest rake task
158
+ - figure out a better way to read/execute tests if they are defined inline
159
+ - as part of the spec test suite create a set of blackbox tests that replicate the functionality in the examples directory to test that actual functionality is working correctly, perhaps create some sort of testing output writer and use that for asserting stuff possibly, these will esssentially be acceptance tests
160
+ - create a better set of unit tests that are not as black box
161
+ - perhaps keep track of timings for how long it took to complete each of the test containers as well as each of the individual tests so that can track stats for test execution speed
162
+ - still more matchers, should_be_around(6, :plus_minus => 1){5} that should work for floats also, maybe give ability to do predicate matchers, i.e if objects responds to a question mark method like include? should be able to do should_include 5, some_array, also think about a good way to create more flexible matchers, more flexible than lambda based ones so that can supply parameters to matchers
119
163
  - write and integrate own test double framework (look at rr for syntax suggestions)
120
164
  - create some tests using the framework itself around the framework classes (minimal test suite)
121
165
  - allow expectations to be made on objects themselves
122
166
  - allow for tests to be given ids as well as descriptions
123
167
  - allow for multiple before and after blocks should specify which test to run this block for using ids of tests as parameters
168
+ - think of even more different types of expectations
169
+ - specify your own expectations
170
+ - some way to share the expectations that you have created yourself amongs all the different tests in different files
171
+ - pull in tests from other files into current file easily
172
+ - ability to run tests in parallel in multiple different ruby processes (depending on how many processors you have, configurable) then aggregate all the results, unit test parallelisation, ability to declare some test classes as non-parallelisable in which case they execute in a traditional fashion after all the parallelised tests have been run
173
+ - ability to only run unsuccessful tests from a previous run, only the fails and the errors
174
+ - ability to run only the tests that were run on the previous run
175
+ - print out how long it took to complete the current test run
124
176
 
125
177
  next release 3
126
178
  - come up with some more useful expectations, both on object and as standalone methods of test
127
179
  - look into rails stuff regarding expectations and idioms etc
128
180
  - should somehow be able to require all the necessary ruby files that are needed when a test is run for the test not to fail, e.g. because ruby files depend on other ruby files
181
+ - hook into autotest somehow
129
182
 
130
-
131
-
132
- what to say in readme
133
- give an example of usage
134
- talk about how to define tests inline
135
- talk about how to execute the tests in one file or directory etc
136
- list the currently supported expectations
137
- talk about pendind tests
138
- talk about the fact that other output writers are coming
139
- talk about the fact that you can disable setup for particular tests
140
- talk about how to test modules within an included class
141
- no nested context as yet, but can define multiple top level ones, no shared tests or contexts as yet
142
- mention the examples directory but it is currently crappy
183
+ bug
184
+ - when requiring ruby files in another ruby file that one seems to inherit the tests from the other one DONE
185
+ - have a look at doing a similar thing for load method, i.e. myself call new load with an introduced new paramter, and only in that case should the env var for attest be set otherwise even regular load should ignore the if attest block, only if it look slike being an issue
186
+ - BUG when nosetup is defined on test when the test is parsed it is parsed in the context of the parser and therefore hits method missing the only reason it works right now is because there is an instance var on parser called nosetup
@@ -1,4 +1,4 @@
1
- class MagicCalculator
1
+ class ACalculator
2
2
  def remember_value(value)
3
3
  @value_in_memory = value
4
4
  end
@@ -22,19 +22,19 @@ class MagicCalculator
22
22
  end
23
23
 
24
24
  if ENV["attest"]
25
- this_tests MagicCalculator do
26
- before_all{@calculator = MagicCalculator.new}
27
- after_all{@calculator = nil}
25
+ this_tests ACalculator do
26
+ before_each{@calculator = ACalculator.new}
27
+ after_each{@calculator = nil}
28
28
 
29
29
  test("a pending test")
30
30
  test("deliberately fail the test"){should_fail}
31
31
  test("a successful empty test"){}
32
32
  test("should NOT raise an error") {should_not_raise{@calculator.increment 4}}
33
33
  test("it should raise an error, don't care what kind") {should_raise {@calculator.divide 5, 0}}
34
- test("it should raise a ZeroDivisionError error with a message"){should_raise(ZeroDivisionError){@calculator.divide 5, 0}.with_message(/divided by.*/)}
35
- test("adding 5 and 2 does not equal 8") { should_not_be_true{ @calculator.add(5,2) == 8 } }
34
+ test("it should raise a ZeroDivisionError error with a message"){should_raise(ZeroDivisionError, :with_message => /divided by.*/){@calculator.divide 5, 0}}
35
+ test("adding 5 and 2 does not equal 8") { should_not_be_true(@calculator.add(5,2) == 8) }
36
36
  test("this test will be an error when non-existant method called") {should_be_true{ @calculator.non_existant }}
37
- test("should be able to call a private method like it was public"){should_be_true{@calculator.multiply(2,2) == 4}}
37
+ test("should be able to call a private method like it was public"){should_be_true(@calculator.multiply(2,2) == 4)}
38
38
 
39
39
  test "access an instance variable without explicitly exposing it" do
40
40
  @calculator.remember_value(5)
@@ -45,6 +45,40 @@ if ENV["attest"]
45
45
  should_not_raise{@calculator.increment 4}
46
46
  should_raise{ @calculator.non_existant }
47
47
  end
48
- test("should not have access to calculator instance since run without setup", nosetup){should_be_true{@calculator == nil}}
48
+
49
+ nosetup
50
+ test("should not have access to calculator instance since run without setup"){should_be_true(@calculator == nil)}
51
+
52
+ test("should_equal expectations with and without block") do
53
+ should_equal 5, 5
54
+ should_equal(5){5}
55
+ should_not_equal 7, 8
56
+ should_not_be_equal(8){9}
57
+ end
58
+
59
+ test("should_be_same and should_not_be_same with and without block") do
60
+ should_be_same 5, 5
61
+ should_not_be_same(5){5.0}
62
+ string = "a"
63
+ should_be_same_as(string, string)
64
+ should_not_be_same_as("a"){string}
65
+ end
66
+
67
+ test("should_be_true without block") {should_be_true 5 == 5.0}
68
+ test("should_not_be_true without block") {should_be_false 5 == 6}
69
+
70
+ test("should_succeed test") do
71
+ should_succeed
72
+ end
73
+
74
+ test("should_be a lambda based matcher test") do
75
+ great = lambda{"great"}
76
+ should_be(great){"great"}
77
+ should_not_be(great){"bad"}
78
+
79
+ joke = lambda{"knock, knock"}
80
+ should_be_a(joke){"knock, knock"}
81
+ should_not_be_a(joke){"hello"}
82
+ end
49
83
  end
50
84
  end
@@ -0,0 +1,43 @@
1
+ class Product
2
+ end
3
+
4
+ if ENV["attest"]
5
+ this_tests "testing of basic mocha integration" do
6
+ test("mocking a class method") do
7
+ product = Product.new
8
+ Product.expects(:find).with(1).returns(product)
9
+ should_be_true {product == Product.find(1)}
10
+ end
11
+
12
+ test("mocking an instance method") do
13
+ product = Product.new
14
+ product.expects(:save).returns(true)
15
+ should_be_true{product.save}
16
+ end
17
+
18
+ test("stubbing an instance method") do
19
+ prices = [stub(:pence => 1000), stub(:pence => 2000)]
20
+ product = Product.new
21
+ product.stubs(:prices).returns(prices)
22
+ should_be_true{ [1000, 2000] == product.prices.collect {|p| p.pence}}
23
+ end
24
+
25
+ test("stubbing an all instances") do
26
+ Product.any_instance.stubs(:name).returns('stubbed_name')
27
+ product = Product.new
28
+ should_be_true{ 'stubbed_name' == product.name }
29
+ end
30
+
31
+ test("traditional mocking") do
32
+ object = mock()
33
+ object.expects(:expected_method).with(:p1, :p2).returns(:result)
34
+ should_be_true { :result == object.expected_method(:p1, :p2) }
35
+ end
36
+
37
+ test("shortcuts") do
38
+ object = stub(:method1 => :result1, :method2 => :result2)
39
+ should_be_true{ :result1 == object.method1 }
40
+ should_be_true{ :result2 == object.method2 }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,49 @@
1
+ class StandardCalculator
2
+ def self.plus(x, y)
3
+ x + y
4
+ end
5
+
6
+ def self.minus(x, y)
7
+ x - y
8
+ end
9
+ end
10
+
11
+ module CalcModule
12
+ def double(x)
13
+ 2 * x
14
+ end
15
+ end
16
+
17
+ if ENV["attest"]
18
+ this_tests "another class with calculations" do
19
+ test("adding two numbers") {should_be_true{StandardCalculator.plus(5,11) == 16}}
20
+ test("subtracting two numbers"){should_not_be_true{StandardCalculator.minus(10,5) == 4}}
21
+ end
22
+
23
+ this_tests CalcModule do
24
+ before_all do
25
+ @hello = [1,2,3]
26
+ end
27
+
28
+ before_each { @module_class = create_and_include(CalcModule) }
29
+
30
+ test("magically instance of a class that will include the module"){should_be_true{@module_class.double(5)==10}}
31
+
32
+ nosetup
33
+ test("another test without setup"){should_be_true{true}}
34
+
35
+ disabled
36
+ test("a disabled test"){should_be_true{true}}
37
+
38
+ test("accessing object which was created in a before_all block") do
39
+ should_be_true{@hello.size == 3}
40
+ @hello << 5
41
+ should_be_true{@hello.size == 4}
42
+ end
43
+
44
+ test("accessing object from before_all block again to make sure it is the same object") do
45
+ should_be_true{@hello.last == 5}
46
+ @hello << 10
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ class AssertionsAsTests
2
+ class << self
3
+ def five
4
+ 5
5
+ end
6
+
7
+ def error
8
+ raise
9
+ end
10
+ end
11
+ end
12
+
13
+ if ENV["attest"]
14
+ this_tests "the fact that assertions can be specified as tests" do
15
+ should_be_true{5 == AssertionsAsTests.five}
16
+ should_raise do
17
+ AssertionsAsTests.error
18
+ end
19
+ end
20
+ end
@@ -1,22 +1,6 @@
1
- require "rubygems"
2
- require "bundler"
3
- Bundler.setup(:default)
1
+ $:.unshift(File.expand_path(File.dirname(__FILE__))) unless $:.include?(File.expand_path(File.dirname(__FILE__)))
4
2
 
5
- require "trollop"
6
- require "singleton"
7
3
  require 'attest/config'
8
- require 'attest/core_ext/kernel'
9
- require 'attest/core_ext/object'
10
-
11
- require 'attest/expectation_result'
12
- require 'attest/test_container'
13
- require 'attest/test_object'
14
- require 'attest/execution_context'
15
- require 'attest/test_parser'
16
- require 'attest/itself'
17
- require 'attest/attest_error'
18
-
19
- require 'attest/output/basic_output_writer'
20
4
 
21
5
  module Attest
22
6
  class << self
@@ -29,9 +13,9 @@ module Attest
29
13
 
30
14
  Attest::Config.public_instance_methods(false).each do |name|
31
15
  self.class_eval <<-EOT
32
- def #{name}(*args)
33
- configure.send("#{name}", *args)
34
- end
16
+ def #{name}(*args)
17
+ configure.send("#{name}", *args)
18
+ end
35
19
  EOT
36
20
  end
37
21
  end
@@ -1,12 +1,9 @@
1
+ require 'singleton'
2
+
1
3
  module Attest
2
4
  class Config
3
5
  include Singleton
4
6
 
5
- attr_accessor :output_writer, :current_file
6
-
7
- def initialize
8
- @output_writer = Attest::Output::BasicOutputWriter.new
9
- end
10
-
7
+ attr_accessor :output_writer, :current_file, :testdouble, :possible_tests
11
8
  end
12
9
  end
@@ -1,5 +1,14 @@
1
+ require 'attest/test_parser'
2
+
1
3
  module Kernel
2
4
  def new_method_missing(name, *args, &block)
5
+ original_error = nil
6
+ begin
7
+ old_method_missing(name, *args, &block)
8
+ return
9
+ rescue NoMethodError => e
10
+ original_error = e
11
+ end
3
12
  private_method = false
4
13
  instance_variable = false
5
14
  private_methods.each do |meth|
@@ -14,12 +23,21 @@ module Kernel
14
23
  end
15
24
  send(name, *args, &block)
16
25
  else
17
- old_method_missing(name, *args, &block)
26
+ raise original_error
18
27
  end
19
28
  end
20
29
  alias_method :old_method_missing, :method_missing
21
30
  alias_method :method_missing, :new_method_missing
22
31
 
32
+ def new_require(filename)
33
+ current_attest_value = ENV["attest"]
34
+ ENV["attest"] = nil
35
+ old_require(filename)
36
+ ENV["attest"] = current_attest_value
37
+ end
38
+ alias_method :old_require, :require
39
+ alias_method :require, :new_require
40
+
23
41
  private
24
42
  def this_tests(description="anonymous", &block)
25
43
  container = Attest::TestParser.new(description, block).parse
@@ -1,5 +1,4 @@
1
1
  class Object
2
- def itself
3
- Attest::Itself.new(self)
2
+ def hello
4
3
  end
5
4
  end
@@ -0,0 +1,35 @@
1
+ current_dir = File.expand_path(File.dirname(__FILE__))
2
+ require "#{current_dir}/../proc/proc_source_reader"
3
+
4
+ class Proc
5
+ def to_string
6
+ @source ||= Attest::ProcSourceReader.find(*source_descriptor)
7
+ end
8
+
9
+ private
10
+ def source_descriptor
11
+ unless @file && @line
12
+ if md = /^#<Proc:0x[0-9A-Fa-f]+@(.+):(\d+)(.+?)?>$/.match(inspect)
13
+ @file, @line = md.captures
14
+ end
15
+ end
16
+ [@file, @line.to_i]
17
+ end
18
+ end
19
+
20
+ if __FILE__ == $0
21
+ simple_proc = Proc.new() { |a|
22
+ puts "Hello Rudy2"
23
+ }
24
+ puts simple_proc.to_string
25
+
26
+ another_simple_proc = Proc.new() do |x|
27
+ #printing
28
+ puts "Printing #{x}"
29
+ puts "printing more stuff"
30
+ end
31
+ puts another_simple_proc.to_string
32
+
33
+ third_proc = eval "Proc.new do puts 'blah'; end"
34
+ puts third_proc.to_string
35
+ end