mirror of
https://github.com/edgecase/ruby_koans.git
synced 2026-04-15 07:23:19 -04:00
Compare commits
43 Commits
codemash-2
...
cinci-day-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0a01786f4 | ||
|
|
ed2ef0f439 | ||
|
|
1f6c0e03a5 | ||
|
|
06c47eb284 | ||
|
|
bc1a20a310 | ||
|
|
e6fc8f6434 | ||
|
|
36f93c6c63 | ||
|
|
bc55853983 | ||
|
|
d17cc7b457 | ||
|
|
f88e9f1dfc | ||
|
|
05d5ab9a5e | ||
|
|
1b31a5b4dc | ||
|
|
3aa75e86aa | ||
|
|
9c0ccd53a2 | ||
|
|
9a459a7eb3 | ||
|
|
e1ada6ca9f | ||
|
|
a5180d9ea1 | ||
|
|
7db19b5e92 | ||
|
|
aa21cae64b | ||
|
|
7c52931392 | ||
|
|
028e4a0c75 | ||
|
|
eee3429394 | ||
|
|
6365c8d61d | ||
|
|
f2ac27f52e | ||
|
|
c4549eb24b | ||
|
|
ee9a03740b | ||
|
|
8ef93f1d3a | ||
|
|
7046294343 | ||
|
|
e8456fa321 | ||
|
|
138bc7c9bc | ||
|
|
2c3b65ec79 | ||
|
|
fbd36f6b0d | ||
|
|
56206e0a41 | ||
|
|
308ad5d9c5 | ||
|
|
c40424e9a4 | ||
|
|
f0b1560f34 | ||
|
|
3b824d0e86 | ||
|
|
110ff38b3f | ||
|
|
1d1ab85777 | ||
|
|
d4c9150453 | ||
|
|
ec6458e174 | ||
|
|
6c69bcb0ef | ||
|
|
6052c776bc |
66
README.rdoc
66
README.rdoc
@@ -1,29 +1,29 @@
|
||||
= EdgeCase Ruby Koans
|
||||
|
||||
The Ruby Koans walk you along the path to enlightenment in order to learn Ruby.
|
||||
The goal is to learn the Ruby language, syntax, structure, and some common
|
||||
The Ruby Koans walk you along the path to enlightenment in order to learn Ruby.
|
||||
The goal is to learn the Ruby language, syntax, structure, and some common
|
||||
functions and libraries. We also teach you culture. Testing is not just something we
|
||||
pay lip service to, but something we live. It is essential in your quest to learn
|
||||
and do great things in the language.
|
||||
pay lip service to, but something we live. It is essential in your quest to learn
|
||||
and do great things in the language.
|
||||
|
||||
== The Structure
|
||||
|
||||
The koans are broken out into areas by file, hashes are covered in about_hashes.rb,
|
||||
modules are introduced in about_modules.rb, etc. They are presented in order in the
|
||||
path_to_enlightenment.rb file.
|
||||
The koans are broken out into areas by file, hashes are covered in about_hashes.rb,
|
||||
modules are introduced in about_modules.rb, etc. They are presented in order in the
|
||||
path_to_enlightenment.rb file.
|
||||
|
||||
Each koan builds up your knowledge of Ruby and builds upon itself. It will stop at
|
||||
the first place you need to correct.
|
||||
Each koan builds up your knowledge of Ruby and builds upon itself. It will stop at
|
||||
the first place you need to correct.
|
||||
|
||||
Some koans simply need to have the correct answer substituted for an incorrect one.
|
||||
Some, however, require you to supply your own answer. If you see the method +__+ (a
|
||||
double underscore) listed, it is a hint to you to supply your own code in order to
|
||||
make it work correctly.
|
||||
Some koans simply need to have the correct answer substituted for an incorrect one.
|
||||
Some, however, require you to supply your own answer. If you see the method +__+ (a
|
||||
double underscore) listed, it is a hint to you to supply your own code in order to
|
||||
make it work correctly.
|
||||
|
||||
== Installing Ruby
|
||||
|
||||
If you do not have Ruby setup, please visit http://ruby-lang.org/en/downloads/ for
|
||||
operating specific instructions. In order to run this you need ruby and rake
|
||||
If you do not have Ruby setup, please visit http://ruby-lang.org/en/downloads/ for
|
||||
operating specific instructions. In order to run this you need ruby and rake
|
||||
installed. To check the installations simply type:
|
||||
|
||||
*nix platforms from any terminal window:
|
||||
@@ -33,11 +33,11 @@ installed. To check the installations simply type:
|
||||
|
||||
Windows from the command prompt (cmd.exe)
|
||||
|
||||
c:\ruby --version
|
||||
c:\ruby --version
|
||||
c:\rake --version
|
||||
|
||||
Any response for Ruby with a version number greater than 1.8 is fine (should be
|
||||
around 1.8.6 or more). Any version of rake will do.
|
||||
|
||||
Any response for Ruby with a version number greater than 1.8 is fine (should be
|
||||
around 1.8.6 or more). Any version of rake will do.
|
||||
|
||||
== The Path To Enlightenment
|
||||
|
||||
@@ -48,18 +48,18 @@ recommended way to run them as we might build more functionality into this task)
|
||||
|
||||
[ruby_koans] $ rake # runs the default target :walk_the_path
|
||||
[ruby_koans] $ ruby path_to_enlightenment.rb # simply call the file directly
|
||||
|
||||
|
||||
Windows is the same thing
|
||||
|
||||
c:\ruby_koans\rake # runs the default target :walk_the_path
|
||||
c:\ruby_koans\ruby path_to_enlightenment.rb # simply call the file directly
|
||||
|
||||
|
||||
=== Red, Green, Refactor
|
||||
|
||||
In test-driven development the mantra has always been, red, green, refactor. Write a
|
||||
failing test and run it (red), make the test pass (green), then refactor it (that is
|
||||
look at the code and see if you can make it any better. In this case you will need
|
||||
to run the koan and see it fail (red), make the test pass (green), then take a
|
||||
to run the koan and see it fail (red), make the test pass (green), then take a
|
||||
moment and reflect upon the test to see what it is teaching you and improve the
|
||||
code to better communicate its intent (refactor).
|
||||
|
||||
@@ -68,26 +68,26 @@ The very first time you run it you will see the following output:
|
||||
[ ruby_koans ] $ rake
|
||||
(in /Users/person/dev/ruby_koans)
|
||||
cd koans
|
||||
|
||||
|
||||
Thinking AboutAsserts
|
||||
test_assert_truth has damaged your karma.
|
||||
|
||||
|
||||
You have not yet reached enlightenment ...
|
||||
<false> is not true.
|
||||
|
||||
|
||||
Please meditate on the following code:
|
||||
./about_asserts.rb:10:in `test_assert_truth'
|
||||
path_to_enlightenment.rb:27
|
||||
|
||||
mountains are merely mountains
|
||||
|
||||
|
||||
You have come to your first stage. If you notice it is telling you where to look for
|
||||
the first solution:
|
||||
|
||||
Please meditate on the following code:
|
||||
./about_asserts.rb:10:in `test_assert_truth'
|
||||
path_to_enlightenment.rb:27
|
||||
|
||||
|
||||
We then open up the about_asserts.rb file and look at the first test:
|
||||
|
||||
# We shall contemplate truth by testing reality, via asserts.
|
||||
@@ -97,13 +97,13 @@ We then open up the about_asserts.rb file and look at the first test:
|
||||
|
||||
We then change the +false+ to +true+ and run the test again. After you are
|
||||
done, think about what you are learning. In this case, ignore everything except
|
||||
the method name (+test_assert_truth+) and the parts inside the method (everything
|
||||
before the +end+).
|
||||
|
||||
In this case the goal is for you to see that if you pass a value to the +assert+
|
||||
the method name (+test_assert_truth+) and the parts inside the method (everything
|
||||
before the +end+).
|
||||
|
||||
In this case the goal is for you to see that if you pass a value to the +assert+
|
||||
method, it will either ensure it is +true+ and continue on, or fail if in fact
|
||||
the statement is +false+.
|
||||
|
||||
the statement is +false+.
|
||||
|
||||
== Inspiration
|
||||
|
||||
A special thanks to Mike Clark and Ara Howard for inspiring this
|
||||
|
||||
3
Rakefile
3
Rakefile
@@ -21,6 +21,7 @@ module Koans
|
||||
line = line.gsub(/\b____\([^\)]+\)/, "____")
|
||||
line = line.gsub(/\b___\([^\)]+\)/, "___")
|
||||
line = line.gsub(/\b__\([^\)]+\)/, "__")
|
||||
line = line.gsub(/\b_n_\([^\)]+\)/, "_n_")
|
||||
line = line.gsub(%r(/\#\{__\}/), "/__/")
|
||||
line
|
||||
end
|
||||
@@ -28,6 +29,8 @@ module Koans
|
||||
def Koans.make_koan_file(infile, outfile)
|
||||
if infile =~ /edgecase/
|
||||
cp infile, outfile
|
||||
elsif infile =~ /autotest/
|
||||
cp_r infile, outfile
|
||||
else
|
||||
open(infile) do |ins|
|
||||
open(outfile, "w") do |outs|
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
= EdgeCase Ruby Koans
|
||||
|
||||
The Ruby Koans walk you along the path to enlightenment in order to learn Ruby.
|
||||
The goal is to learn the Ruby language, syntax, structure, and some common
|
||||
The Ruby Koans walk you along the path to enlightenment in order to learn Ruby.
|
||||
The goal is to learn the Ruby language, syntax, structure, and some common
|
||||
functions and libraries. We also teach you culture. Testing is not just something we
|
||||
pay lip service to, but something we live. It is essential in your quest to learn
|
||||
and do great things in the language.
|
||||
pay lip service to, but something we live. It is essential in your quest to learn
|
||||
and do great things in the language.
|
||||
|
||||
== The Structure
|
||||
|
||||
The koans are broken out into areas by file, hashes are covered in about_hashes.rb,
|
||||
modules are introduced in about_modules.rb, etc. They are presented in order in the
|
||||
path_to_enlightenment.rb file.
|
||||
The koans are broken out into areas by file, hashes are covered in about_hashes.rb,
|
||||
modules are introduced in about_modules.rb, etc. They are presented in order in the
|
||||
path_to_enlightenment.rb file.
|
||||
|
||||
Each koan builds up your knowledge of Ruby and builds upon itself. It will stop at
|
||||
the first place you need to correct.
|
||||
Each koan builds up your knowledge of Ruby and builds upon itself. It will stop at
|
||||
the first place you need to correct.
|
||||
|
||||
Some koans simply need to have the correct answer substituted for an incorrect one.
|
||||
Some, however, require you to supply your own answer. If you see the method +__+ (a
|
||||
double underscore) listed, it is a hint to you to supply your own code in order to
|
||||
make it work correctly.
|
||||
Some koans simply need to have the correct answer substituted for an incorrect one.
|
||||
Some, however, require you to supply your own answer. If you see the method +__+ (a
|
||||
double underscore) listed, it is a hint to you to supply your own code in order to
|
||||
make it work correctly.
|
||||
|
||||
== Installing Ruby
|
||||
|
||||
If you do not have Ruby setup, please visit http://ruby-lang.org/en/downloads/ for
|
||||
operating specific instructions. In order to run this you need ruby and rake
|
||||
If you do not have Ruby setup, please visit http://ruby-lang.org/en/downloads/ for
|
||||
operating specific instructions. In order to run this you need ruby and rake
|
||||
installed. To check the installations simply type:
|
||||
|
||||
*nix platforms from any terminal window:
|
||||
@@ -33,11 +33,11 @@ installed. To check the installations simply type:
|
||||
|
||||
Windows from the command prompt (cmd.exe)
|
||||
|
||||
c:\ruby --version
|
||||
c:\ruby --version
|
||||
c:\rake --version
|
||||
|
||||
Any response for Ruby with a version number greater than 1.8 is fine (should be
|
||||
around 1.8.6 or more). Any version of rake will do.
|
||||
|
||||
Any response for Ruby with a version number greater than 1.8 is fine (should be
|
||||
around 1.8.6 or more). Any version of rake will do.
|
||||
|
||||
== The Path To Enlightenment
|
||||
|
||||
@@ -48,18 +48,18 @@ recommended way to run them as we might build more functionality into this task)
|
||||
|
||||
[ruby_koans] $ rake # runs the default target :walk_the_path
|
||||
[ruby_koans] $ ruby path_to_enlightenment.rb # simply call the file directly
|
||||
|
||||
|
||||
Windows is the same thing
|
||||
|
||||
c:\ruby_koans\rake # runs the default target :walk_the_path
|
||||
c:\ruby_koans\ruby path_to_enlightenment.rb # simply call the file directly
|
||||
|
||||
|
||||
=== Red, Green, Refactor
|
||||
|
||||
In test-driven development the mantra has always been, red, green, refactor. Write a
|
||||
failing test and run it (red), make the test pass (green), then refactor it (that is
|
||||
look at the code and see if you can make it any better. In this case you will need
|
||||
to run the koan and see it fail (red), make the test pass (green), then take a
|
||||
to run the koan and see it fail (red), make the test pass (green), then take a
|
||||
moment and reflect upon the test to see what it is teaching you and improve the
|
||||
code to better communicate its intent (refactor).
|
||||
|
||||
@@ -68,26 +68,26 @@ The very first time you run it you will see the following output:
|
||||
[ ruby_koans ] $ rake
|
||||
(in /Users/person/dev/ruby_koans)
|
||||
cd koans
|
||||
|
||||
|
||||
Thinking AboutAsserts
|
||||
test_assert_truth has damaged your karma.
|
||||
|
||||
|
||||
You have not yet reached enlightenment ...
|
||||
<false> is not true.
|
||||
|
||||
|
||||
Please meditate on the following code:
|
||||
./about_asserts.rb:10:in `test_assert_truth'
|
||||
path_to_enlightenment.rb:27
|
||||
|
||||
mountains are merely mountains
|
||||
|
||||
|
||||
You have come to your first stage. If you notice it is telling you where to look for
|
||||
the first solution:
|
||||
|
||||
Please meditate on the following code:
|
||||
./about_asserts.rb:10:in `test_assert_truth'
|
||||
path_to_enlightenment.rb:27
|
||||
|
||||
|
||||
We then open up the about_asserts.rb file and look at the first test:
|
||||
|
||||
# We shall contemplate truth by testing reality, via asserts.
|
||||
@@ -97,13 +97,13 @@ We then open up the about_asserts.rb file and look at the first test:
|
||||
|
||||
We then change the +false+ to +true+ and run the test again. After you are
|
||||
done, think about what you are learning. In this case, ignore everything except
|
||||
the method name (+test_assert_truth+) and the parts inside the method (everything
|
||||
before the +end+).
|
||||
|
||||
In this case the goal is for you to see that if you pass a value to the +assert+
|
||||
the method name (+test_assert_truth+) and the parts inside the method (everything
|
||||
before the +end+).
|
||||
|
||||
In this case the goal is for you to see that if you pass a value to the +assert+
|
||||
method, it will either ensure it is +true+ and continue on, or fail if in fact
|
||||
the statement is +false+.
|
||||
|
||||
the statement is +false+.
|
||||
|
||||
== Inspiration
|
||||
|
||||
A special thanks to Mike Clark and Ara Howard for inspiring this
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutArrayAssignment < EdgeCase::Koan
|
||||
def test_non_parallel_assignment
|
||||
@@ -35,4 +35,11 @@ class AboutArrayAssignment < EdgeCase::Koan
|
||||
assert_equal __, first_name
|
||||
end
|
||||
|
||||
def test_swapping_with_parallel_assignment
|
||||
first_name = "Roy"
|
||||
last_name = "Rob"
|
||||
first_name, last_name = last_name, first_name
|
||||
assert_equal __, first_name
|
||||
assert_equal __, last_name
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutArrays < EdgeCase::Koan
|
||||
def test_creating_arrays
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env ruby
|
||||
# -*- ruby -*-
|
||||
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutAsserts < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutBlocks < EdgeCase::Koan
|
||||
def method_with_block
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutClassMethods < EdgeCase::Koan
|
||||
class Dog
|
||||
@@ -19,11 +19,11 @@ class AboutClassMethods < EdgeCase::Koan
|
||||
|
||||
def test_objects_have_methods
|
||||
fido = Dog.new
|
||||
assert_equal __, fido.methods.size
|
||||
assert fido.methods.size > _n_
|
||||
end
|
||||
|
||||
def test_classes_have_methods
|
||||
assert_equal __, Dog.methods.size
|
||||
assert Dog.methods.size > _n_
|
||||
end
|
||||
|
||||
def test_you_can_define_methods_on_individual_objects
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutClasses < EdgeCase::Koan
|
||||
class Dog
|
||||
@@ -43,7 +43,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
fido = Dog2.new
|
||||
fido.set_name("Fido")
|
||||
|
||||
assert_equal __, fido.instance_variable_get("@name")
|
||||
assert_equal __, fido.instance_variable_get("@name")
|
||||
end
|
||||
|
||||
def test_you_can_rip_the_value_out_using_instance_eval
|
||||
@@ -89,7 +89,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
|
||||
assert_equal __, fido.name
|
||||
end
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class Dog5
|
||||
@@ -125,7 +125,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
# THINK ABOUT IT:
|
||||
# Why is this so?
|
||||
end
|
||||
|
||||
|
||||
def test_different_objects_have_difference_instance_variables
|
||||
fido = Dog6.new("Fido")
|
||||
rover = Dog6.new("Rover")
|
||||
@@ -186,5 +186,5 @@ class AboutClasses < EdgeCase::Koan
|
||||
assert_equal __, "STRING".to_s
|
||||
assert_equal __, "STRING".inspect
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
87
koans/about_constants.rb
Normal file
87
koans/about_constants.rb
Normal file
@@ -0,0 +1,87 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
C = "top level"
|
||||
|
||||
class AboutConstants < EdgeCase::Koan
|
||||
|
||||
C = "nested"
|
||||
|
||||
def test_nested_constants_may_also_be_referenced_with_relative_paths
|
||||
assert_equal __, C
|
||||
end
|
||||
|
||||
def test_top_level_constants_are_referenced_by_double_colons
|
||||
assert_equal __, ::C
|
||||
end
|
||||
|
||||
def test_nested_constants_are_referenced_by_their_complete_path
|
||||
assert_equal __, AboutConstants::C
|
||||
assert_equal __, ::AboutConstants::C
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class Animal
|
||||
LEGS = 4
|
||||
def legs_in_animal
|
||||
LEGS
|
||||
end
|
||||
|
||||
class NestedAnimal
|
||||
def legs_in_nested_animal
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_nested_classes_inherit_constants_from_enclosing_classes
|
||||
assert_equal __, Animal::NestedAnimal.new.legs_in_nested_animal
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class Reptile < Animal
|
||||
def legs_in_reptile
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
|
||||
def test_subclasses_inherit_constants_from_parent_classes
|
||||
assert_equal __, Reptile.new.legs_in_reptile
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class MyAnimals
|
||||
LEGS = 2
|
||||
|
||||
class Bird < Animal
|
||||
def legs_in_bird
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_who_wins_with_both_nested_and_inherited_constants
|
||||
assert_equal __, MyAnimals::Bird.new.legs_in_bird
|
||||
end
|
||||
|
||||
# QUESTION: Which has precedence: The constant in the lexical scope,
|
||||
# or the constant from the inheritance heirarachy?
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class MyAnimals::Oyster < Animal
|
||||
def legs_in_oyster
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
|
||||
def test_who_wins_with_explicit_scoping_on_class_definition
|
||||
assert_equal __, MyAnimals::Oyster.new.legs_in_oyster
|
||||
end
|
||||
|
||||
# QUESTION: Now Which has precedence: The constant in the lexical
|
||||
# scope, or the constant from the inheritance heirarachy? Why is it
|
||||
# different than the previous answer?
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutControlStatements < EdgeCase::Koan
|
||||
|
||||
@@ -11,7 +11,7 @@ class AboutControlStatements < EdgeCase::Koan
|
||||
assert_equal __, result
|
||||
end
|
||||
|
||||
def test_if_then_else_statements
|
||||
def test_if_then_statements
|
||||
result = :default_value
|
||||
if true
|
||||
result = :true_value
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class DiceSet
|
||||
attr_reader :values
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutExceptions < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutHashes < EdgeCase::Koan
|
||||
def test_creating_hashes
|
||||
@@ -48,7 +48,7 @@ class AboutHashes < EdgeCase::Koan
|
||||
|
||||
def test_hash_values
|
||||
hash = { :one => "uno", :two => "dos" }
|
||||
assert_equal __, hash.keys.size
|
||||
assert_equal __, hash.values.size
|
||||
assert_equal __, hash.values.include?("uno")
|
||||
assert_equal __, hash.values.include?("dos")
|
||||
assert_equal Array, hash.values.class
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutInheritance < EdgeCase::Koan
|
||||
class Dog
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutIteration < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
|
||||
class MessageCatcher
|
||||
def caught?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_methods_can_be_called_directly
|
||||
mc = MessageCatcher.new
|
||||
|
||||
assert mc.caught?
|
||||
|
||||
assert mc.caught?
|
||||
end
|
||||
|
||||
|
||||
def test_methods_can_be_invoked_by_sending_the_message
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert mc.send(:caught?)
|
||||
end
|
||||
|
||||
|
||||
def test_methods_can_be_invoked_more_dynamically
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert mc.send("caught?")
|
||||
assert mc.send("caught" + __ ) # What do you need to add to the first string?
|
||||
assert mc.send("CAUGHT?".____ ) # What would you need to do to the string?
|
||||
@@ -40,23 +40,22 @@ class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
def test_classes_can_be_asked_if_they_know_how_to_respond
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert_equal __, mc.respond_to?(:caught?)
|
||||
assert_equal __, mc.respond_to?(:does_not_exist)
|
||||
end
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class MessageCatcher
|
||||
def add_a_payload(*args)
|
||||
return :empty unless args
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_sending_a_message_with_arguments
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert_equal __, mc.add_a_payload
|
||||
assert_equal __, mc.send(:add_a_payload)
|
||||
|
||||
@@ -90,6 +89,18 @@ class AboutMessagePassing < EdgeCase::Koan
|
||||
#
|
||||
# If the method :method_missing causes the NoMethodError, then
|
||||
# what would happen if we redefine method_missing?
|
||||
#
|
||||
# NOTE:
|
||||
#
|
||||
# In Ruby 1.8 the method_missing method is public and can be
|
||||
# called as shown above. However, in Ruby 1.9 the method_missing
|
||||
# method is private. We explicitly made it public in the testing
|
||||
# framework so this example works in both versions of Ruby. Just
|
||||
# keep in mind you can't call method_missing like that in Ruby
|
||||
# 1.9. normally.
|
||||
#
|
||||
# Thanks. We now return you to your regularly schedule Ruby
|
||||
# Koans.
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
def my_global_method(a,b)
|
||||
a + b
|
||||
@@ -10,14 +10,14 @@ class AboutMethods < EdgeCase::Koan
|
||||
assert_equal __, my_global_method(2,3)
|
||||
end
|
||||
|
||||
def test_calling_global_methods_without_parenthesis
|
||||
def test_calling_global_methods_without_parentheses
|
||||
result = my_global_method 2, 3
|
||||
assert_equal __, result
|
||||
end
|
||||
|
||||
# (NOTE: We are Using eval below because the example code is
|
||||
# considered to be syntactically invalid).
|
||||
def test_sometimes_missing_parenthesis_are_ambiguous
|
||||
def test_sometimes_missing_parentheses_are_ambiguous
|
||||
eval "assert_equal 5, my_global_method 2, 3" # ENABLE CHECK
|
||||
#
|
||||
# Ruby doesn't know if you mean:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutModules < EdgeCase::Koan
|
||||
module Nameable
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutNil < EdgeCase::Koan
|
||||
def test_nil_is_an_object
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutOpenClasses < EdgeCase::Koan
|
||||
class Dog
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# Project: Create a Proxy Class
|
||||
#
|
||||
|
||||
159
koans/about_regular_expressions.rb
Normal file
159
koans/about_regular_expressions.rb
Normal file
@@ -0,0 +1,159 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutRegularExpressions < EdgeCase::Koan
|
||||
def test_a_pattern_is_a_regular_expression
|
||||
assert_equal Regexp, /pattern/.class
|
||||
end
|
||||
|
||||
def test_a_regexp_can_search_a_string_for_matching_content
|
||||
assert_equal "match", "some matching content"[/match/]
|
||||
end
|
||||
|
||||
def test_a_failed_match_returns_nil
|
||||
assert_equal __, "some matching content"[/missing/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_question_mark_means_optional
|
||||
assert_equal __, "abbcccddddeeeee"[/ab?/]
|
||||
assert_equal __, "abbcccddddeeeee"[/az?/]
|
||||
end
|
||||
|
||||
def test_plus_means_one_or_more
|
||||
assert_equal __, "abbcccddddeeeee"[/bc+/]
|
||||
end
|
||||
|
||||
def test_asterisk_means_zero_or_more
|
||||
assert_equal __, "abbcccddddeeeee"[/ab*/]
|
||||
assert_equal __, "abbcccddddeeeee"[/az*/]
|
||||
assert_equal __, "abbcccddddeeeee"[/z*/]
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# When would * fail to match?
|
||||
end
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# We say that the repetition operators above are "greedy."
|
||||
#
|
||||
# Why?
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_the_left_most_match_wins
|
||||
assert_equal __, "abbccc az"[/az*/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_character_classes_give_options_for_a_character
|
||||
animals = ["cat", "bat", "rat", "zat"]
|
||||
assert_equal __, animals.select { |a| a[/[cbr]at/] }
|
||||
end
|
||||
|
||||
def test_slash_d_is_a_shortcut_for_a_digit_character_class
|
||||
assert_equal __, "the number is 42"[/[0123456789]+/]
|
||||
assert_equal __, "the number is 42"[/\d+/]
|
||||
end
|
||||
|
||||
def test_character_classes_can_include_ranges
|
||||
assert_equal __, "the number is 42"[/[0-9]+/]
|
||||
end
|
||||
|
||||
def test_slash_s_is_a_shortcut_for_a_whitespace_character_class
|
||||
assert_equal __, "space: \t\n"[/\s+/]
|
||||
end
|
||||
|
||||
def test_slash_w_is_a_shortcut_for_a_word_character_class
|
||||
# NOTE: This is more like how a programmer might define a word.
|
||||
assert_equal __, "variable_1 = 42"[/[a-zA-Z0-9_]+/]
|
||||
assert_equal __, "variable_1 = 42"[/\w+/]
|
||||
end
|
||||
|
||||
def test_period_is_a_shortcut_for_any_non_newline_character
|
||||
assert_equal __, "abc\n123"[/a.+/]
|
||||
end
|
||||
|
||||
def test_a_character_class_can_be_negated
|
||||
assert_equal __, "the number is 42"[/[^0-9]+/]
|
||||
end
|
||||
|
||||
def test_shortcut_character_classes_are_negated_with_capitals
|
||||
assert_equal __, "the number is 42"[/\D+/]
|
||||
assert_equal __, "space: \t\n"[/\S+/]
|
||||
assert_equal __, "variable_1 = 42"[/\W+/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_slash_a_anchors_to_the_start_of_the_string
|
||||
assert_equal __, "start end"[/\Astart/]
|
||||
assert_equal __, "start end"[/\Aend/]
|
||||
end
|
||||
|
||||
def test_slash_z_anchors_to_the_end_of_the_string
|
||||
assert_equal __, "start end"[/end\z/]
|
||||
assert_equal __, "start end"[/start\z/]
|
||||
end
|
||||
|
||||
def test_caret_anchors_to_the_start_of_lines
|
||||
assert_equal __, "num 42\n2 lines"[/^\d+/]
|
||||
end
|
||||
|
||||
def test_dollar_sign_anchors_to_the_end_of_lines
|
||||
assert_equal __, "2 lines\nnum 42"[/\d+$/]
|
||||
end
|
||||
|
||||
def test_slash_b_anchors_to_a_word_boundary
|
||||
assert_equal __, "bovine vines"[/\bvine./]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_parentheses_group_contents
|
||||
assert_equal __, "ahahaha"[/(ha)+/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_parentheses_also_capture_matched_content_by_number
|
||||
assert_equal __, "Gray, James"[/(\w+), (\w+)/, 1]
|
||||
assert_equal __, "Gray, James"[/(\w+), (\w+)/, 2]
|
||||
end
|
||||
|
||||
def test_variables_can_also_be_used_to_access_captures
|
||||
assert_equal __, "Name: Gray, James"[/(\w+), (\w+)/]
|
||||
assert_equal __, $1
|
||||
assert_equal __, $2
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_a_vertical_pipe_means_or
|
||||
grays = /(James|Dana|Summer) Gray/
|
||||
assert_equal __, "James Gray"[grays]
|
||||
assert_equal __, "Summer Gray"[grays, 1]
|
||||
assert_equal __, "Jim Gray"[grays, 1]
|
||||
end
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# Explain the difference between a character class ([…]) and alternation (|).
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_scan_is_like_find_all
|
||||
assert_equal __, "one two-three".scan(/\w+/)
|
||||
end
|
||||
|
||||
def test_sub_is_like_find_and_replace
|
||||
assert_equal __, "one two-three".sub(/(t\w*)/) { $1[0, 1] }
|
||||
end
|
||||
|
||||
def test_gsub_is_like_find_and_replace_all
|
||||
assert_equal __, "one two-three".gsub(/(t\w*)/) { $1[0, 1] }
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutUsingBlocks < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutScope < EdgeCase::Koan
|
||||
module Jims
|
||||
@@ -28,7 +28,7 @@ class AboutScope < EdgeCase::Koan
|
||||
rover = Joes::Dog.new
|
||||
assert_equal __, fido.identify
|
||||
assert_equal __, rover.identify
|
||||
|
||||
|
||||
assert_not_equal fido.class, rover.class
|
||||
assert_not_equal Jims::Dog, Joes::Dog
|
||||
end
|
||||
@@ -41,7 +41,7 @@ class AboutScope < EdgeCase::Koan
|
||||
def test_bare_bones_class_names_assume_the_current_scope
|
||||
assert_equal __, AboutScope::String == String
|
||||
end
|
||||
|
||||
|
||||
def test_nested_string_is_not_the_same_as_the_system_string
|
||||
assert_equal __, String == "HI".class
|
||||
end
|
||||
@@ -74,6 +74,6 @@ class AboutScope < EdgeCase::Koan
|
||||
|
||||
def test_you_can_get_a_list_of_constants_for_any_class_or_module
|
||||
assert_equal __, Jims.constants
|
||||
assert_equal __, Object.constants.size
|
||||
assert Object.constants.size > _n_
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# Greed is a dice game where you roll up to five dice to accumulate
|
||||
# points. The following "score" function will be used calculate the
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutStrings < EdgeCase::Koan
|
||||
def test_double_quoted_strings_are_strings
|
||||
@@ -146,11 +146,20 @@ EOS
|
||||
# Surprised?
|
||||
end
|
||||
|
||||
def test_single_characters_are_represented_by_integers
|
||||
assert_equal __, ?a
|
||||
assert_equal __, ?a == 97
|
||||
in_ruby_version("1.8") do
|
||||
def test_in_ruby_1_8_single_characters_are_represented_by_integers
|
||||
assert_equal __, ?a
|
||||
assert_equal __, ?a == 97
|
||||
|
||||
assert_equal __, ?b == (?a + 1)
|
||||
assert_equal __, ?b == (?a + 1)
|
||||
end
|
||||
end
|
||||
|
||||
in_ruby_version("1.9") do
|
||||
def test_in_ruby_1_9_single_characters_are_represented_by_strings
|
||||
assert_equal __, ?a
|
||||
assert_equal __, ?a == 97
|
||||
end
|
||||
end
|
||||
|
||||
def test_strings_can_be_split
|
||||
@@ -165,8 +174,8 @@ EOS
|
||||
assert_equal [__, __, __, __], words
|
||||
|
||||
# NOTE: Patterns are formed from Regular Expressions. Ruby has a
|
||||
# very powerful Regular Expression library. Unfortunately, time
|
||||
# does not permit us to explore it in detail in Ruby 101.
|
||||
# very powerful Regular Expression library. We will become
|
||||
# enlightened about them soon.
|
||||
end
|
||||
|
||||
def test_strings_can_be_joined
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# You need to write the triangle method in the file 'triangle.rb'
|
||||
require 'triangle.rb'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# You need to write the triangle method in the file 'triangle.rb'
|
||||
require 'triangle.rb'
|
||||
@@ -9,6 +9,7 @@ class AboutTriangleAssignment2 < EdgeCase::Koan
|
||||
def test_illegal_triangles_throw_exceptions
|
||||
assert_raise(TriangleError) do triangle(0, 0, 0) end
|
||||
assert_raise(TriangleError) do triangle(3, 4, -5) end
|
||||
assert_raise(TriangleError) do triangle(1, 1, 3) end
|
||||
assert_raise(TriangleError) do triangle(2, 4, 2) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutTrueAndFalse < EdgeCase::Koan
|
||||
def truth_value(condition)
|
||||
|
||||
3
koans/autotest/discover.rb
Normal file
3
koans/autotest/discover.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
Autotest.add_discovery do
|
||||
"rubykoan" if File.exist? 'path_to_enlightenment.rb'
|
||||
end
|
||||
24
koans/autotest/rubykoan.rb
Normal file
24
koans/autotest/rubykoan.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
require 'autotest'
|
||||
|
||||
class Autotest::Rubykoan < Autotest
|
||||
def initialize
|
||||
super
|
||||
@exceptions = /\.txt|Rakefile|\.rdoc/
|
||||
|
||||
self.order = :alpha
|
||||
self.add_mapping(/^about_.*rb$/) do |filename, _|
|
||||
filename
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def make_test_cmd files_to_test
|
||||
"#{ruby} 'path_to_enlightenment.rb'"
|
||||
end
|
||||
|
||||
# quiet test/unit chatter
|
||||
def handle_results(results)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1 +1 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
@@ -6,8 +6,24 @@ require 'test/unit/assertions'
|
||||
class FillMeInError < StandardError
|
||||
end
|
||||
|
||||
def __(value="FILL ME IN")
|
||||
value
|
||||
def in_ruby_version(version)
|
||||
yield if RUBY_VERSION =~ /^#{version}/
|
||||
end
|
||||
|
||||
def __(value="FILL ME IN", value19=:mu)
|
||||
if RUBY_VERSION < "1.9"
|
||||
value
|
||||
else
|
||||
(value19 == :mu) ? value : value19
|
||||
end
|
||||
end
|
||||
|
||||
def _n_(value=999999, value19=:mu)
|
||||
if RUBY_VERSION < "1.9"
|
||||
value
|
||||
else
|
||||
(value19 == :mu) ? value : value19
|
||||
end
|
||||
end
|
||||
|
||||
def ___(value=FillMeInError)
|
||||
@@ -20,13 +36,56 @@ class Object
|
||||
self.send(method)
|
||||
end
|
||||
end
|
||||
|
||||
in_ruby_version("1.9") do
|
||||
public :method_missing
|
||||
end
|
||||
end
|
||||
|
||||
module EdgeCase
|
||||
|
||||
module Color
|
||||
#shamelessly stolen (and modified) from redgreen
|
||||
COLORS = {
|
||||
:clear => 0, :black => 30, :red => 31,
|
||||
:green => 32, :yellow => 33, :blue => 34,
|
||||
:magenta => 35, :cyan => 36,
|
||||
}
|
||||
|
||||
module_function
|
||||
|
||||
COLORS.each do |color, value|
|
||||
module_eval "def #{color}(string); colorize(string, #{value}); end"
|
||||
module_function color
|
||||
end
|
||||
|
||||
def colorize(string, color_value)
|
||||
if ENV['NO_COLOR']
|
||||
string
|
||||
else
|
||||
color(color_value) + string + color(COLORS[:clear])
|
||||
end
|
||||
end
|
||||
|
||||
def color(color_value)
|
||||
"\e[#{color_value}m"
|
||||
end
|
||||
end
|
||||
|
||||
class Sensei
|
||||
attr_reader :failure, :failed_test
|
||||
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
in_ruby_version("1.8") do
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
end
|
||||
|
||||
in_ruby_version("1.9") do
|
||||
if defined?(MiniTest)
|
||||
AssertionError = MiniTest::Assertion
|
||||
else
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@pass_count = 0
|
||||
@@ -37,9 +96,9 @@ module EdgeCase
|
||||
def accumulate(test)
|
||||
if test.passed?
|
||||
@pass_count += 1
|
||||
puts " #{test.name} has expanded your awareness."
|
||||
puts Color.green(" #{test.name} has expanded your awareness.")
|
||||
else
|
||||
puts " #{test.name} has damaged your karma."
|
||||
puts Color.red(" #{test.name} has damaged your karma.")
|
||||
@failed_test = test
|
||||
@failure = test.failure
|
||||
throw :edgecase_exit
|
||||
@@ -57,18 +116,19 @@ module EdgeCase
|
||||
def report
|
||||
if failed?
|
||||
puts
|
||||
puts "You have not yet reached enlightenment ..."
|
||||
puts failure.message
|
||||
puts Color.green("You have not yet reached enlightenment ...")
|
||||
puts Color.red(failure.message)
|
||||
puts
|
||||
puts "Please meditate on the following code:"
|
||||
puts Color.green("Please meditate on the following code:")
|
||||
if assert_failed?
|
||||
puts find_interesting_lines(failure.backtrace)
|
||||
#puts find_interesting_lines(failure.backtrace)
|
||||
puts find_interesting_lines(failure.backtrace).collect {|l| Color.red(l) }
|
||||
else
|
||||
puts failure.backtrace
|
||||
puts Color.red(failure.backtrace)
|
||||
end
|
||||
puts
|
||||
end
|
||||
say_something_zenlike
|
||||
puts Color.green(a_zenlike_statement)
|
||||
end
|
||||
|
||||
def find_interesting_lines(backtrace)
|
||||
@@ -79,28 +139,29 @@ module EdgeCase
|
||||
|
||||
# Hat's tip to Ara T. Howard for the zen statements from his
|
||||
# metakoans Ruby Quiz (http://rubyquiz.com/quiz67.html)
|
||||
def say_something_zenlike
|
||||
def a_zenlike_statement
|
||||
puts
|
||||
if !failed?
|
||||
puts "Mountains are again merely mountains"
|
||||
zen_statement = "Mountains are again merely mountains"
|
||||
else
|
||||
case (@pass_count % 10)
|
||||
zen_statement = case (@pass_count % 10)
|
||||
when 0
|
||||
puts "mountains are merely mountains"
|
||||
"mountains are merely mountains"
|
||||
when 1, 2
|
||||
puts "learn the rules so you know how to break them properly"
|
||||
"learn the rules so you know how to break them properly"
|
||||
when 3, 4
|
||||
puts "remember that silence is sometimes the best answer"
|
||||
"remember that silence is sometimes the best answer"
|
||||
when 5, 6
|
||||
puts "sleep is the best meditation"
|
||||
"sleep is the best meditation"
|
||||
when 7, 8
|
||||
puts "when you lose, don't lose the lesson"
|
||||
"when you lose, don't lose the lesson"
|
||||
else
|
||||
puts "things are not what they appear to be: nor are they otherwise"
|
||||
"things are not what they appear to be: nor are they otherwise"
|
||||
end
|
||||
end
|
||||
zen_statement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Koan
|
||||
include Test::Unit::Assertions
|
||||
@@ -138,7 +199,7 @@ module EdgeCase
|
||||
|
||||
def run_tests(accumulator)
|
||||
puts
|
||||
puts "Thinking #{self}"
|
||||
puts Color.green("Thinking #{self}")
|
||||
testmethods.each do |m|
|
||||
self.run_test(m, accumulator) if Koan.test_pattern =~ m.to_s
|
||||
end
|
||||
@@ -149,12 +210,12 @@ module EdgeCase
|
||||
test.setup
|
||||
begin
|
||||
test.send(method)
|
||||
rescue StandardError => ex
|
||||
rescue StandardError, EdgeCase::Sensei::AssertionError => ex
|
||||
test.failed(ex)
|
||||
ensure
|
||||
begin
|
||||
test.teardown
|
||||
rescue StandardError => ex
|
||||
rescue StandardError, EdgeCase::Sensei::AssertionError => ex
|
||||
test.failed(ex) if test.passed?
|
||||
end
|
||||
end
|
||||
@@ -177,7 +238,7 @@ module EdgeCase
|
||||
load(arg)
|
||||
else
|
||||
fail "Unknown command line argument '#{arg}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# The path to Ruby Enlightenment starts with the following:
|
||||
|
||||
$LOAD_PATH << File.dirname(__FILE__)
|
||||
|
||||
require 'about_asserts'
|
||||
require 'about_nil'
|
||||
require 'about_arrays'
|
||||
require 'about_array_assignment'
|
||||
require 'about_hashes'
|
||||
require 'about_strings'
|
||||
require 'about_regular_expressions'
|
||||
require 'about_methods'
|
||||
require 'about_constants'
|
||||
require 'about_control_statements'
|
||||
require 'about_true_and_false'
|
||||
require 'about_triangle_project'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutArrayAssignment < EdgeCase::Koan
|
||||
def test_non_parallel_assignment
|
||||
@@ -35,4 +35,11 @@ class AboutArrayAssignment < EdgeCase::Koan
|
||||
assert_equal __("John"), first_name
|
||||
end
|
||||
|
||||
def test_swapping_with_parallel_assignment
|
||||
first_name = "Roy"
|
||||
last_name = "Rob"
|
||||
first_name, last_name = last_name, first_name
|
||||
assert_equal __('Rob'), first_name
|
||||
assert_equal __('Roy'), last_name
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutArrays < EdgeCase::Koan
|
||||
def test_creating_arrays
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env ruby
|
||||
# -*- ruby -*-
|
||||
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutAsserts < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutBlocks < EdgeCase::Koan
|
||||
def method_with_block
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutClassMethods < EdgeCase::Koan
|
||||
class Dog
|
||||
@@ -19,11 +19,11 @@ class AboutClassMethods < EdgeCase::Koan
|
||||
|
||||
def test_objects_have_methods
|
||||
fido = Dog.new
|
||||
assert_equal __(44), fido.methods.size
|
||||
assert fido.methods.size > _n_(30)
|
||||
end
|
||||
|
||||
def test_classes_have_methods
|
||||
assert_equal __(79), Dog.methods.size
|
||||
assert Dog.methods.size > _n_(40)
|
||||
end
|
||||
|
||||
def test_you_can_define_methods_on_individual_objects
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutClasses < EdgeCase::Koan
|
||||
class Dog
|
||||
@@ -22,7 +22,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
assert_equal __([]), fido.instance_variables
|
||||
|
||||
fido.set_name("Fido")
|
||||
assert_equal __(["@name"]), fido.instance_variables
|
||||
assert_equal __(["@name"], [:@name]), fido.instance_variables
|
||||
end
|
||||
|
||||
def test_instance_variables_cannot_be_accessed_outside_the_class
|
||||
@@ -43,7 +43,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
fido = Dog2.new
|
||||
fido.set_name("Fido")
|
||||
|
||||
assert_equal __("Fido"), fido.instance_variable_get("@name")
|
||||
assert_equal __("Fido"), fido.instance_variable_get("@name")
|
||||
end
|
||||
|
||||
def test_you_can_rip_the_value_out_using_instance_eval
|
||||
@@ -89,7 +89,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
|
||||
assert_equal __("Fido"), fido.name
|
||||
end
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class Dog5
|
||||
@@ -125,7 +125,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
# THINK ABOUT IT:
|
||||
# Why is this so?
|
||||
end
|
||||
|
||||
|
||||
def test_different_objects_have_difference_instance_variables
|
||||
fido = Dog6.new("Fido")
|
||||
rover = Dog6.new("Rover")
|
||||
@@ -180,11 +180,11 @@ class AboutClasses < EdgeCase::Koan
|
||||
def test_all_objects_support_to_s_and_inspect
|
||||
array = [1,2,3]
|
||||
|
||||
assert_equal __("123"), array.to_s
|
||||
assert_equal __("123", "[1, 2, 3]"), array.to_s
|
||||
assert_equal __("[1, 2, 3]"), array.inspect
|
||||
|
||||
assert_equal __("STRING"), "STRING".to_s
|
||||
assert_equal __('"STRING"'), "STRING".inspect
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
87
src/about_constants.rb
Normal file
87
src/about_constants.rb
Normal file
@@ -0,0 +1,87 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
C = "top level"
|
||||
|
||||
class AboutConstants < EdgeCase::Koan
|
||||
|
||||
C = "nested"
|
||||
|
||||
def test_nested_constants_may_also_be_referenced_with_relative_paths
|
||||
assert_equal __("nested"), C
|
||||
end
|
||||
|
||||
def test_top_level_constants_are_referenced_by_double_colons
|
||||
assert_equal __("top level"), ::C
|
||||
end
|
||||
|
||||
def test_nested_constants_are_referenced_by_their_complete_path
|
||||
assert_equal __("nested"), AboutConstants::C
|
||||
assert_equal __("nested"), ::AboutConstants::C
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class Animal
|
||||
LEGS = 4
|
||||
def legs_in_animal
|
||||
LEGS
|
||||
end
|
||||
|
||||
class NestedAnimal
|
||||
def legs_in_nested_animal
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_nested_classes_inherit_constants_from_enclosing_classes
|
||||
assert_equal __(4), Animal::NestedAnimal.new.legs_in_nested_animal
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class Reptile < Animal
|
||||
def legs_in_reptile
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
|
||||
def test_subclasses_inherit_constants_from_parent_classes
|
||||
assert_equal __(4), Reptile.new.legs_in_reptile
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class MyAnimals
|
||||
LEGS = 2
|
||||
|
||||
class Bird < Animal
|
||||
def legs_in_bird
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_who_wins_with_both_nested_and_inherited_constants
|
||||
assert_equal __(2), MyAnimals::Bird.new.legs_in_bird
|
||||
end
|
||||
|
||||
# QUESTION: Which has precedence: The constant in the lexical scope,
|
||||
# or the constant from the inheritance heirarachy?
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class MyAnimals::Oyster < Animal
|
||||
def legs_in_oyster
|
||||
LEGS
|
||||
end
|
||||
end
|
||||
|
||||
def test_who_wins_with_explicit_scoping_on_class_definition
|
||||
assert_equal __(4), MyAnimals::Oyster.new.legs_in_oyster
|
||||
end
|
||||
|
||||
# QUESTION: Now Which has precedence: The constant in the lexical
|
||||
# scope, or the constant from the inheritance heirarachy? Why is it
|
||||
# different than the previous answer?
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutControlStatements < EdgeCase::Koan
|
||||
|
||||
@@ -8,10 +8,10 @@ class AboutControlStatements < EdgeCase::Koan
|
||||
else
|
||||
result = :false_value
|
||||
end
|
||||
assert_equal __, result
|
||||
assert_equal __(:true_value), result
|
||||
end
|
||||
|
||||
def test_if_then_else_statements
|
||||
def test_if_then_statements
|
||||
result = :default_value
|
||||
if true
|
||||
result = :true_value
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class DiceSet
|
||||
attr_reader :values
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutExceptions < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutHashes < EdgeCase::Koan
|
||||
def test_creating_hashes
|
||||
@@ -48,7 +48,7 @@ class AboutHashes < EdgeCase::Koan
|
||||
|
||||
def test_hash_values
|
||||
hash = { :one => "uno", :two => "dos" }
|
||||
assert_equal __(2), hash.keys.size
|
||||
assert_equal __(2), hash.values.size
|
||||
assert_equal __(true), hash.values.include?("uno")
|
||||
assert_equal __(true), hash.values.include?("dos")
|
||||
assert_equal Array, hash.values.class
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutInheritance < EdgeCase::Koan
|
||||
class Dog
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutIteration < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
|
||||
class MessageCatcher
|
||||
def caught?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_methods_can_be_called_directly
|
||||
mc = MessageCatcher.new
|
||||
|
||||
assert mc.caught?
|
||||
|
||||
assert mc.caught?
|
||||
end
|
||||
|
||||
|
||||
def test_methods_can_be_invoked_by_sending_the_message
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert mc.send(:caught?)
|
||||
end
|
||||
|
||||
|
||||
def test_methods_can_be_invoked_more_dynamically
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert mc.send("caught?")
|
||||
assert mc.send("caught" + __("?") ) # What do you need to add to the first string?
|
||||
assert mc.send("CAUGHT?".____(:downcase) ) # What would you need to do to the string?
|
||||
@@ -40,23 +40,22 @@ class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
def test_classes_can_be_asked_if_they_know_how_to_respond
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert_equal __(true), mc.respond_to?(:caught?)
|
||||
assert_equal __(false), mc.respond_to?(:does_not_exist)
|
||||
end
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class MessageCatcher
|
||||
def add_a_payload(*args)
|
||||
return :empty unless args
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_sending_a_message_with_arguments
|
||||
mc = MessageCatcher.new
|
||||
|
||||
|
||||
assert_equal __([]), mc.add_a_payload
|
||||
assert_equal __([]), mc.send(:add_a_payload)
|
||||
|
||||
@@ -90,6 +89,18 @@ class AboutMessagePassing < EdgeCase::Koan
|
||||
#
|
||||
# If the method :method_missing causes the NoMethodError, then
|
||||
# what would happen if we redefine method_missing?
|
||||
#
|
||||
# NOTE:
|
||||
#
|
||||
# In Ruby 1.8 the method_missing method is public and can be
|
||||
# called as shown above. However, in Ruby 1.9 the method_missing
|
||||
# method is private. We explicitly made it public in the testing
|
||||
# framework so this example works in both versions of Ruby. Just
|
||||
# keep in mind you can't call method_missing like that in Ruby
|
||||
# 1.9. normally.
|
||||
#
|
||||
# Thanks. We now return you to your regularly schedule Ruby
|
||||
# Koans.
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
def my_global_method(a,b)
|
||||
a + b
|
||||
@@ -10,14 +10,14 @@ class AboutMethods < EdgeCase::Koan
|
||||
assert_equal __(5), my_global_method(2,3)
|
||||
end
|
||||
|
||||
def test_calling_global_methods_without_parenthesis
|
||||
def test_calling_global_methods_without_parentheses
|
||||
result = my_global_method 2, 3
|
||||
assert_equal __(5), result
|
||||
end
|
||||
|
||||
# (NOTE: We are Using eval below because the example code is
|
||||
# considered to be syntactically invalid).
|
||||
def test_sometimes_missing_parenthesis_are_ambiguous
|
||||
def test_sometimes_missing_parentheses_are_ambiguous
|
||||
#--
|
||||
eval "assert_equal 5, my_global_method(2, 3)" # REMOVE CHECK
|
||||
if false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutModules < EdgeCase::Koan
|
||||
module Nameable
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutNil < EdgeCase::Koan
|
||||
def test_nil_is_an_object
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutOpenClasses < EdgeCase::Koan
|
||||
class Dog
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# Project: Create a Proxy Class
|
||||
#
|
||||
|
||||
159
src/about_regular_expressions.rb
Normal file
159
src/about_regular_expressions.rb
Normal file
@@ -0,0 +1,159 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutRegularExpressions < EdgeCase::Koan
|
||||
def test_a_pattern_is_a_regular_expression
|
||||
assert_equal Regexp, /pattern/.class
|
||||
end
|
||||
|
||||
def test_a_regexp_can_search_a_string_for_matching_content
|
||||
assert_equal "match", "some matching content"[/match/]
|
||||
end
|
||||
|
||||
def test_a_failed_match_returns_nil
|
||||
assert_equal __(nil), "some matching content"[/missing/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_question_mark_means_optional
|
||||
assert_equal __("ab"), "abbcccddddeeeee"[/ab?/]
|
||||
assert_equal __("a"), "abbcccddddeeeee"[/az?/]
|
||||
end
|
||||
|
||||
def test_plus_means_one_or_more
|
||||
assert_equal __("bccc"), "abbcccddddeeeee"[/bc+/]
|
||||
end
|
||||
|
||||
def test_asterisk_means_zero_or_more
|
||||
assert_equal __("abb"), "abbcccddddeeeee"[/ab*/]
|
||||
assert_equal __("a"), "abbcccddddeeeee"[/az*/]
|
||||
assert_equal __(""), "abbcccddddeeeee"[/z*/]
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# When would * fail to match?
|
||||
end
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# We say that the repetition operators above are "greedy."
|
||||
#
|
||||
# Why?
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_the_left_most_match_wins
|
||||
assert_equal __("a"), "abbccc az"[/az*/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_character_classes_give_options_for_a_character
|
||||
animals = ["cat", "bat", "rat", "zat"]
|
||||
assert_equal __(["cat", "bat", "rat"]), animals.select { |a| a[/[cbr]at/] }
|
||||
end
|
||||
|
||||
def test_slash_d_is_a_shortcut_for_a_digit_character_class
|
||||
assert_equal __("42"), "the number is 42"[/[0123456789]+/]
|
||||
assert_equal __("42"), "the number is 42"[/\d+/]
|
||||
end
|
||||
|
||||
def test_character_classes_can_include_ranges
|
||||
assert_equal __("42"), "the number is 42"[/[0-9]+/]
|
||||
end
|
||||
|
||||
def test_slash_s_is_a_shortcut_for_a_whitespace_character_class
|
||||
assert_equal __(" \t\n"), "space: \t\n"[/\s+/]
|
||||
end
|
||||
|
||||
def test_slash_w_is_a_shortcut_for_a_word_character_class
|
||||
# NOTE: This is more like how a programmer might define a word.
|
||||
assert_equal __("variable_1"), "variable_1 = 42"[/[a-zA-Z0-9_]+/]
|
||||
assert_equal __("variable_1"), "variable_1 = 42"[/\w+/]
|
||||
end
|
||||
|
||||
def test_period_is_a_shortcut_for_any_non_newline_character
|
||||
assert_equal __("abc"), "abc\n123"[/a.+/]
|
||||
end
|
||||
|
||||
def test_a_character_class_can_be_negated
|
||||
assert_equal __("the number is "), "the number is 42"[/[^0-9]+/]
|
||||
end
|
||||
|
||||
def test_shortcut_character_classes_are_negated_with_capitals
|
||||
assert_equal __("the number is "), "the number is 42"[/\D+/]
|
||||
assert_equal __("space:"), "space: \t\n"[/\S+/]
|
||||
assert_equal __(" = "), "variable_1 = 42"[/\W+/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_slash_a_anchors_to_the_start_of_the_string
|
||||
assert_equal __("start"), "start end"[/\Astart/]
|
||||
assert_equal __(nil), "start end"[/\Aend/]
|
||||
end
|
||||
|
||||
def test_slash_z_anchors_to_the_end_of_the_string
|
||||
assert_equal __("end"), "start end"[/end\z/]
|
||||
assert_equal __(nil), "start end"[/start\z/]
|
||||
end
|
||||
|
||||
def test_caret_anchors_to_the_start_of_lines
|
||||
assert_equal __("2"), "num 42\n2 lines"[/^\d+/]
|
||||
end
|
||||
|
||||
def test_dollar_sign_anchors_to_the_end_of_lines
|
||||
assert_equal __("42"), "2 lines\nnum 42"[/\d+$/]
|
||||
end
|
||||
|
||||
def test_slash_b_anchors_to_a_word_boundary
|
||||
assert_equal __("vines"), "bovine vines"[/\bvine./]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_parentheses_group_contents
|
||||
assert_equal __("hahaha"), "ahahaha"[/(ha)+/]
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_parentheses_also_capture_matched_content_by_number
|
||||
assert_equal __("Gray"), "Gray, James"[/(\w+), (\w+)/, 1]
|
||||
assert_equal __("James"), "Gray, James"[/(\w+), (\w+)/, 2]
|
||||
end
|
||||
|
||||
def test_variables_can_also_be_used_to_access_captures
|
||||
assert_equal __("Gray, James"), "Name: Gray, James"[/(\w+), (\w+)/]
|
||||
assert_equal __("Gray"), $1
|
||||
assert_equal __("James"), $2
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_a_vertical_pipe_means_or
|
||||
grays = /(James|Dana|Summer) Gray/
|
||||
assert_equal __("James Gray"), "James Gray"[grays]
|
||||
assert_equal __("Summer"), "Summer Gray"[grays, 1]
|
||||
assert_equal __(nil), "Jim Gray"[grays, 1]
|
||||
end
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# Explain the difference between a character class ([…]) and alternation (|).
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_scan_is_like_find_all
|
||||
assert_equal __(["one", "two", "three"]), "one two-three".scan(/\w+/)
|
||||
end
|
||||
|
||||
def test_sub_is_like_find_and_replace
|
||||
assert_equal __("one t-three"), "one two-three".sub(/(t\w*)/) { $1[0, 1] }
|
||||
end
|
||||
|
||||
def test_gsub_is_like_find_and_replace_all
|
||||
assert_equal __("one t-t"), "one two-three".gsub(/(t\w*)/) { $1[0, 1] }
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutUsingBlocks < EdgeCase::Koan
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutScope < EdgeCase::Koan
|
||||
module Jims
|
||||
@@ -28,7 +28,7 @@ class AboutScope < EdgeCase::Koan
|
||||
rover = Joes::Dog.new
|
||||
assert_equal __(:jims_dog), fido.identify
|
||||
assert_equal __(:joes_dog), rover.identify
|
||||
|
||||
|
||||
assert_not_equal fido.class, rover.class
|
||||
assert_not_equal Jims::Dog, Joes::Dog
|
||||
end
|
||||
@@ -41,7 +41,7 @@ class AboutScope < EdgeCase::Koan
|
||||
def test_bare_bones_class_names_assume_the_current_scope
|
||||
assert_equal __(true), AboutScope::String == String
|
||||
end
|
||||
|
||||
|
||||
def test_nested_string_is_not_the_same_as_the_system_string
|
||||
assert_equal __(false), String == "HI".class
|
||||
end
|
||||
@@ -73,7 +73,7 @@ class AboutScope < EdgeCase::Koan
|
||||
end
|
||||
|
||||
def test_you_can_get_a_list_of_constants_for_any_class_or_module
|
||||
assert_equal __(["Dog"]), Jims.constants
|
||||
assert_equal __(122), Object.constants.size
|
||||
assert_equal __(["Dog"], [:Dog]), Jims.constants
|
||||
assert Object.constants.size > _n_(10)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# Greed is a dice game where you roll up to five dice to accumulate
|
||||
# points. The following "score" function will be used calculate the
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutStrings < EdgeCase::Koan
|
||||
def test_double_quoted_strings_are_strings
|
||||
@@ -141,16 +141,25 @@ EOS
|
||||
|
||||
def test_you_can_get_a_single_character_from_a_string
|
||||
string = "Bacon, lettuce and tomato"
|
||||
assert_equal __(97), string[1]
|
||||
assert_equal __(97, 'a'), string[1]
|
||||
|
||||
# Surprised?
|
||||
end
|
||||
|
||||
def test_single_characters_are_represented_by_integers
|
||||
assert_equal __(97), ?a
|
||||
assert_equal __(true), ?a == 97
|
||||
in_ruby_version("1.8") do
|
||||
def test_in_ruby_1_8_single_characters_are_represented_by_integers
|
||||
assert_equal __(97, 'a'), ?a
|
||||
assert_equal __(true, false), ?a == 97
|
||||
|
||||
assert_equal __(true), ?b == (?a + 1)
|
||||
assert_equal __(true), ?b == (?a + 1)
|
||||
end
|
||||
end
|
||||
|
||||
in_ruby_version("1.9") do
|
||||
def test_in_ruby_1_9_single_characters_are_represented_by_strings
|
||||
assert_equal __('a'), ?a
|
||||
assert_equal __(false), ?a == 97
|
||||
end
|
||||
end
|
||||
|
||||
def test_strings_can_be_split
|
||||
@@ -165,8 +174,8 @@ EOS
|
||||
assert_equal [__("the"), __("rain"), __("in"), __("spain")], words
|
||||
|
||||
# NOTE: Patterns are formed from Regular Expressions. Ruby has a
|
||||
# very powerful Regular Expression library. Unfortunately, time
|
||||
# does not permit us to explore it in detail in Ruby 101.
|
||||
# very powerful Regular Expression library. We will become
|
||||
# enlightened about them soon.
|
||||
end
|
||||
|
||||
def test_strings_can_be_joined
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# You need to write the triangle method in the file 'triangle.rb'
|
||||
require 'triangle.rb'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
# You need to write the triangle method in the file 'triangle.rb'
|
||||
require 'triangle.rb'
|
||||
@@ -9,6 +9,7 @@ class AboutTriangleAssignment2 < EdgeCase::Koan
|
||||
def test_illegal_triangles_throw_exceptions
|
||||
assert_raise(TriangleError) do triangle(0, 0, 0) end
|
||||
assert_raise(TriangleError) do triangle(3, 4, -5) end
|
||||
assert_raise(TriangleError) do triangle(1, 1, 3) end
|
||||
assert_raise(TriangleError) do triangle(2, 4, 2) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutTrueAndFalse < EdgeCase::Koan
|
||||
def truth_value(condition)
|
||||
|
||||
3
src/autotest/discover.rb
Normal file
3
src/autotest/discover.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
Autotest.add_discovery do
|
||||
"rubykoan" if File.exist? 'path_to_enlightenment.rb'
|
||||
end
|
||||
24
src/autotest/rubykoan.rb
Normal file
24
src/autotest/rubykoan.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
require 'autotest'
|
||||
|
||||
class Autotest::Rubykoan < Autotest
|
||||
def initialize
|
||||
super
|
||||
@exceptions = /\.txt|Rakefile|\.rdoc/
|
||||
|
||||
self.order = :alpha
|
||||
self.add_mapping(/^about_.*rb$/) do |filename, _|
|
||||
filename
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def make_test_cmd files_to_test
|
||||
"#{ruby} 'path_to_enlightenment.rb'"
|
||||
end
|
||||
|
||||
# quiet test/unit chatter
|
||||
def handle_results(results)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1 +1 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
111
src/edgecase.rb
111
src/edgecase.rb
@@ -6,8 +6,24 @@ require 'test/unit/assertions'
|
||||
class FillMeInError < StandardError
|
||||
end
|
||||
|
||||
def __(value="FILL ME IN")
|
||||
value
|
||||
def in_ruby_version(version)
|
||||
yield if RUBY_VERSION =~ /^#{version}/
|
||||
end
|
||||
|
||||
def __(value="FILL ME IN", value19=:mu)
|
||||
if RUBY_VERSION < "1.9"
|
||||
value
|
||||
else
|
||||
(value19 == :mu) ? value : value19
|
||||
end
|
||||
end
|
||||
|
||||
def _n_(value=999999, value19=:mu)
|
||||
if RUBY_VERSION < "1.9"
|
||||
value
|
||||
else
|
||||
(value19 == :mu) ? value : value19
|
||||
end
|
||||
end
|
||||
|
||||
def ___(value=FillMeInError)
|
||||
@@ -20,13 +36,56 @@ class Object
|
||||
self.send(method)
|
||||
end
|
||||
end
|
||||
|
||||
in_ruby_version("1.9") do
|
||||
public :method_missing
|
||||
end
|
||||
end
|
||||
|
||||
module EdgeCase
|
||||
|
||||
module Color
|
||||
#shamelessly stolen (and modified) from redgreen
|
||||
COLORS = {
|
||||
:clear => 0, :black => 30, :red => 31,
|
||||
:green => 32, :yellow => 33, :blue => 34,
|
||||
:magenta => 35, :cyan => 36,
|
||||
}
|
||||
|
||||
module_function
|
||||
|
||||
COLORS.each do |color, value|
|
||||
module_eval "def #{color}(string); colorize(string, #{value}); end"
|
||||
module_function color
|
||||
end
|
||||
|
||||
def colorize(string, color_value)
|
||||
if ENV['NO_COLOR']
|
||||
string
|
||||
else
|
||||
color(color_value) + string + color(COLORS[:clear])
|
||||
end
|
||||
end
|
||||
|
||||
def color(color_value)
|
||||
"\e[#{color_value}m"
|
||||
end
|
||||
end
|
||||
|
||||
class Sensei
|
||||
attr_reader :failure, :failed_test
|
||||
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
in_ruby_version("1.8") do
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
end
|
||||
|
||||
in_ruby_version("1.9") do
|
||||
if defined?(MiniTest)
|
||||
AssertionError = MiniTest::Assertion
|
||||
else
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@pass_count = 0
|
||||
@@ -37,9 +96,9 @@ module EdgeCase
|
||||
def accumulate(test)
|
||||
if test.passed?
|
||||
@pass_count += 1
|
||||
puts " #{test.name} has expanded your awareness."
|
||||
puts Color.green(" #{test.name} has expanded your awareness.")
|
||||
else
|
||||
puts " #{test.name} has damaged your karma."
|
||||
puts Color.red(" #{test.name} has damaged your karma.")
|
||||
@failed_test = test
|
||||
@failure = test.failure
|
||||
throw :edgecase_exit
|
||||
@@ -57,18 +116,19 @@ module EdgeCase
|
||||
def report
|
||||
if failed?
|
||||
puts
|
||||
puts "You have not yet reached enlightenment ..."
|
||||
puts failure.message
|
||||
puts Color.green("You have not yet reached enlightenment ...")
|
||||
puts Color.red(failure.message)
|
||||
puts
|
||||
puts "Please meditate on the following code:"
|
||||
puts Color.green("Please meditate on the following code:")
|
||||
if assert_failed?
|
||||
puts find_interesting_lines(failure.backtrace)
|
||||
#puts find_interesting_lines(failure.backtrace)
|
||||
puts find_interesting_lines(failure.backtrace).collect {|l| Color.red(l) }
|
||||
else
|
||||
puts failure.backtrace
|
||||
puts Color.red(failure.backtrace)
|
||||
end
|
||||
puts
|
||||
end
|
||||
say_something_zenlike
|
||||
puts Color.green(a_zenlike_statement)
|
||||
end
|
||||
|
||||
def find_interesting_lines(backtrace)
|
||||
@@ -79,28 +139,29 @@ module EdgeCase
|
||||
|
||||
# Hat's tip to Ara T. Howard for the zen statements from his
|
||||
# metakoans Ruby Quiz (http://rubyquiz.com/quiz67.html)
|
||||
def say_something_zenlike
|
||||
def a_zenlike_statement
|
||||
puts
|
||||
if !failed?
|
||||
puts "Mountains are again merely mountains"
|
||||
zen_statement = "Mountains are again merely mountains"
|
||||
else
|
||||
case (@pass_count % 10)
|
||||
zen_statement = case (@pass_count % 10)
|
||||
when 0
|
||||
puts "mountains are merely mountains"
|
||||
"mountains are merely mountains"
|
||||
when 1, 2
|
||||
puts "learn the rules so you know how to break them properly"
|
||||
"learn the rules so you know how to break them properly"
|
||||
when 3, 4
|
||||
puts "remember that silence is sometimes the best answer"
|
||||
"remember that silence is sometimes the best answer"
|
||||
when 5, 6
|
||||
puts "sleep is the best meditation"
|
||||
"sleep is the best meditation"
|
||||
when 7, 8
|
||||
puts "when you lose, don't lose the lesson"
|
||||
"when you lose, don't lose the lesson"
|
||||
else
|
||||
puts "things are not what they appear to be: nor are they otherwise"
|
||||
"things are not what they appear to be: nor are they otherwise"
|
||||
end
|
||||
end
|
||||
zen_statement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Koan
|
||||
include Test::Unit::Assertions
|
||||
@@ -138,7 +199,7 @@ module EdgeCase
|
||||
|
||||
def run_tests(accumulator)
|
||||
puts
|
||||
puts "Thinking #{self}"
|
||||
puts Color.green("Thinking #{self}")
|
||||
testmethods.each do |m|
|
||||
self.run_test(m, accumulator) if Koan.test_pattern =~ m.to_s
|
||||
end
|
||||
@@ -149,12 +210,12 @@ module EdgeCase
|
||||
test.setup
|
||||
begin
|
||||
test.send(method)
|
||||
rescue StandardError => ex
|
||||
rescue StandardError, EdgeCase::Sensei::AssertionError => ex
|
||||
test.failed(ex)
|
||||
ensure
|
||||
begin
|
||||
test.teardown
|
||||
rescue StandardError => ex
|
||||
rescue StandardError, EdgeCase::Sensei::AssertionError => ex
|
||||
test.failed(ex) if test.passed?
|
||||
end
|
||||
end
|
||||
@@ -177,7 +238,7 @@ module EdgeCase
|
||||
load(arg)
|
||||
else
|
||||
fail "Unknown command line argument '#{arg}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# The path to Ruby Enlightenment starts with the following:
|
||||
|
||||
$LOAD_PATH << File.dirname(__FILE__)
|
||||
|
||||
require 'about_asserts'
|
||||
require 'about_nil'
|
||||
require 'about_arrays'
|
||||
require 'about_array_assignment'
|
||||
require 'about_hashes'
|
||||
require 'about_strings'
|
||||
require 'about_regular_expressions'
|
||||
require 'about_methods'
|
||||
require 'about_constants'
|
||||
require 'about_control_statements'
|
||||
require 'about_true_and_false'
|
||||
require 'about_triangle_project'
|
||||
|
||||
Reference in New Issue
Block a user