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 |
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,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
|
||||
|
||||
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,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
@@ -49,7 +49,6 @@ class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
class MessageCatcher
|
||||
def add_a_payload(*args)
|
||||
return :empty unless args
|
||||
args
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
@@ -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,26 +139,27 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -180,7 +180,7 @@ 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
|
||||
|
||||
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,4 +1,4 @@
|
||||
require 'edgecase'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
@@ -49,7 +49,6 @@ class AboutMessagePassing < EdgeCase::Koan
|
||||
|
||||
class MessageCatcher
|
||||
def add_a_payload(*args)
|
||||
return :empty unless args
|
||||
args
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
@@ -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')
|
||||
|
||||
107
src/edgecase.rb
107
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,26 +139,27 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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