mirror of
https://github.com/edgecase/ruby_koans.git
synced 2026-04-15 07:23:19 -04:00
Compare commits
10 Commits
jruby
...
become_the
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d27004c70d | ||
|
|
e5843f64fd | ||
|
|
fdb8774c95 | ||
|
|
5b483df29b | ||
|
|
7dee146a8c | ||
|
|
e24d94eeff | ||
|
|
4789e831df | ||
|
|
b41d6167b4 | ||
|
|
c0bbe773d9 | ||
|
|
6fb8e3c3af |
@@ -18,13 +18,19 @@ class AboutArrayAssignment < EdgeCase::Koan
|
||||
assert_equal __, last_name
|
||||
end
|
||||
|
||||
def test_parallel_assignments_with_extra_variables
|
||||
def test_parallel_assignments_with_splat_operator
|
||||
first_name, *last_name = ["John", "Smith", "III"]
|
||||
assert_equal __, first_name
|
||||
assert_equal __, last_name
|
||||
end
|
||||
|
||||
def test_parallel_assignments_with_too_few_variables
|
||||
first_name, last_name = ["Cher"]
|
||||
assert_equal __, first_name
|
||||
assert_equal __, last_name
|
||||
end
|
||||
|
||||
def test_parallel_assignements_with_subarrays
|
||||
def test_parallel_assignments_with_subarrays
|
||||
first_name, last_name = [["Willie", "Rae"], "Johnson"]
|
||||
assert_equal __, first_name
|
||||
assert_equal __, last_name
|
||||
|
||||
@@ -45,9 +45,9 @@ class AboutArrays < EdgeCase::Koan
|
||||
end
|
||||
|
||||
def test_arrays_and_ranges
|
||||
assert_equal Range, (1..5).class
|
||||
assert_equal __, (1..5).class
|
||||
assert_not_equal [1,2,3,4,5], (1..5)
|
||||
assert_equal [1,2,3,4,5], (1..5).to_a
|
||||
assert_equal __, (1..5).to_a
|
||||
assert_equal __, (1...5).to_a
|
||||
end
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ class AboutClasses < EdgeCase::Koan
|
||||
fido = Dog6.new("Fido")
|
||||
rover = Dog6.new("Rover")
|
||||
|
||||
assert_not_equal rover.name, fido.name
|
||||
assert_equal __, rover.name != fido.name
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
@@ -164,12 +164,12 @@ class AboutClasses < EdgeCase::Koan
|
||||
|
||||
def test_to_s_provides_a_string_version_of_the_object
|
||||
fido = Dog7.new("Fido")
|
||||
assert_equal "Fido", fido.to_s
|
||||
assert_equal __, fido.to_s
|
||||
end
|
||||
|
||||
def test_to_s_is_used_in_string_interpolation
|
||||
fido = Dog7.new("Fido")
|
||||
assert_equal "My dog is Fido", "My dog is #{fido}"
|
||||
assert_equal __, "My dog is #{fido}"
|
||||
end
|
||||
|
||||
def test_inspect_provides_a_more_complete_string_version
|
||||
|
||||
@@ -22,8 +22,8 @@ class AboutExceptions < EdgeCase::Koan
|
||||
|
||||
assert_equal __, result
|
||||
|
||||
assert ex.is_a?(StandardError), "Failure message."
|
||||
assert ex.is_a?(RuntimeError), "Failure message."
|
||||
assert ex.is_a?(___), "Failure message."
|
||||
assert ex.is_a?(___), "Failure message."
|
||||
|
||||
assert RuntimeError.ancestors.include?(StandardError),
|
||||
"RuntimeError is a subclass of StandardError"
|
||||
|
||||
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
class AboutHashes < EdgeCase::Koan
|
||||
def test_creating_hashes
|
||||
empty_hash = Hash.new
|
||||
assert_equal Hash, empty_hash.class
|
||||
assert_equal __, empty_hash.class
|
||||
assert_equal({}, empty_hash)
|
||||
assert_equal __, empty_hash.size
|
||||
end
|
||||
@@ -25,7 +25,7 @@ class AboutHashes < EdgeCase::Koan
|
||||
hash[:one] = "eins"
|
||||
|
||||
expected = { :one => __, :two => "dos" }
|
||||
assert_equal expected, hash
|
||||
assert_equal __, expected == hash
|
||||
|
||||
# Bonus Question: Why was "expected" broken out into a variable
|
||||
# rather than used as a literal?
|
||||
@@ -35,7 +35,7 @@ class AboutHashes < EdgeCase::Koan
|
||||
hash1 = { :one => "uno", :two => "dos" }
|
||||
hash2 = { :two => "dos", :one => "uno" }
|
||||
|
||||
assert_equal hash1, hash2
|
||||
assert_equal __, hash1 == hash2
|
||||
end
|
||||
|
||||
def test_hash_keys
|
||||
@@ -43,7 +43,7 @@ class AboutHashes < EdgeCase::Koan
|
||||
assert_equal __, hash.keys.size
|
||||
assert_equal __, hash.keys.include?(:one)
|
||||
assert_equal __, hash.keys.include?(:two)
|
||||
assert_equal Array, hash.keys.class
|
||||
assert_equal __, hash.keys.class
|
||||
end
|
||||
|
||||
def test_hash_values
|
||||
@@ -51,16 +51,16 @@ class AboutHashes < EdgeCase::Koan
|
||||
assert_equal __, hash.values.size
|
||||
assert_equal __, hash.values.include?("uno")
|
||||
assert_equal __, hash.values.include?("dos")
|
||||
assert_equal Array, hash.values.class
|
||||
assert_equal __, hash.values.class
|
||||
end
|
||||
|
||||
def test_combining_hashes
|
||||
hash = { "jim" => 53, "amy" => 20, "dan" => 23 }
|
||||
new_hash = hash.merge({ "jim" => 54, "jenny" => 26 })
|
||||
|
||||
assert_not_equal hash, new_hash
|
||||
assert_equal __, hash != new_hash
|
||||
|
||||
expected = { "jim" => __, "amy" => 20, "dan" => 23, "jenny" => __ }
|
||||
assert_equal expected, new_hash
|
||||
assert_equal __, expected == new_hash
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ class AboutIteration < EdgeCase::Koan
|
||||
array.each do |item|
|
||||
sum += item
|
||||
end
|
||||
assert_equal 6, sum
|
||||
assert_equal __, sum
|
||||
end
|
||||
|
||||
def test_each_can_use_curly_brace_blocks_too
|
||||
|
||||
124
koans/about_java_interop.rb
Normal file
124
koans/about_java_interop.rb
Normal file
@@ -0,0 +1,124 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
include Java
|
||||
|
||||
# Concepts
|
||||
# * Pull in a java class
|
||||
# * calling a method, Camel vs snake
|
||||
# * Resovling module/class name conflicts
|
||||
# * Showing what gets returned
|
||||
# * Ruby Strings VS Java Strings
|
||||
# * Calling custom java class
|
||||
# * Calling Ruby from java???
|
||||
|
||||
class AboutJavaInterop < EdgeCase::Koan
|
||||
def test_using_a_java_library_class
|
||||
java_array = java.util.ArrayList.new
|
||||
assert_equal __, java_array.class
|
||||
end
|
||||
|
||||
def test_java_class_can_be_referenced_using_both_ruby_and_java_like_syntax
|
||||
assert_equal __, Java::JavaUtil::ArrayList == java.util.ArrayList
|
||||
end
|
||||
|
||||
def test_include_class_includes_class_in_module_scope
|
||||
assert_nil defined?(TreeSet)
|
||||
include_class "java.util.TreeSet"
|
||||
assert_equal __, defined?(TreeSet)
|
||||
end
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# What if we use:
|
||||
#
|
||||
# include_class "java.lang.String"
|
||||
#
|
||||
# What would be the value of the String constant after this
|
||||
# include_class is run? Would it be useful to provide a way of
|
||||
# aliasing java classes to different names?
|
||||
|
||||
JString = java.lang.String
|
||||
def test_also_java_class_can_be_given_ruby_aliases
|
||||
java_string = JString.new("A Java String")
|
||||
assert_equal __, java_string.class
|
||||
assert_equal __, JString
|
||||
end
|
||||
|
||||
def test_can_directly_call_java_methods_on_java_objects
|
||||
java_string = JString.new("A Java String")
|
||||
assert_equal __, java_string.toLowerCase
|
||||
end
|
||||
|
||||
def test_jruby_provides_snake_case_versions_of_java_methods
|
||||
java_string = JString.new("A Java String")
|
||||
assert_equal __, java_string.to_lower_case
|
||||
end
|
||||
|
||||
def test_jruby_provides_question_mark_versions_of_boolean_methods
|
||||
java_string = JString.new("A Java String")
|
||||
assert_equal __, java_string.endsWith("String")
|
||||
assert_equal __, java_string.ends_with("String")
|
||||
assert_equal __, java_string.ends_with?("String")
|
||||
end
|
||||
|
||||
def test_java_string_are_not_ruby_strings
|
||||
ruby_string = "A Java String"
|
||||
java_string = java.lang.String.new(ruby_string)
|
||||
assert_equal __, java_string.is_a?(java.lang.String)
|
||||
assert_equal __, java_string.is_a?(String)
|
||||
end
|
||||
|
||||
def test_java_strings_can_be_compared_to_ruby_strings_maybe
|
||||
ruby_string = "A Java String"
|
||||
java_string = java.lang.String.new(ruby_string)
|
||||
assert_equal __, ruby_string == java_string
|
||||
assert_equal __, java_string == ruby_string
|
||||
|
||||
# THINK ABOUT IT:
|
||||
#
|
||||
# Is there any possible way for this to be more wrong?
|
||||
#
|
||||
# SERIOUSLY, THINK ABOUT IT:
|
||||
#
|
||||
# Why do you suppose that Ruby and Java strings compare like that?
|
||||
#
|
||||
# ADVANCED THINK ABOUT IT:
|
||||
#
|
||||
# Is there a way to make Ruby/Java string comparisons commutative?
|
||||
# How would you do it?
|
||||
end
|
||||
|
||||
def test_however_most_methods_returning_strings_return_ruby_strings
|
||||
java_array = java.util.ArrayList.new
|
||||
assert_equal __, java_array.toString
|
||||
assert_equal __, java_array.toString.is_a?(String)
|
||||
assert_equal __, java_array.toString.is_a?(java.lang.String)
|
||||
end
|
||||
|
||||
def test_java_collections_are_enumerable
|
||||
java_array = java.util.ArrayList.new
|
||||
java_array << "one" << "two" << "three"
|
||||
assert_equal __, java_array.map { |item| item.upcase }
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# Open the Java ArrayList class and add a new method.
|
||||
class Java::JavaUtil::ArrayList
|
||||
def multiply_all
|
||||
result = 1
|
||||
each do |item|
|
||||
result *= item
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def test_java_class_are_open_from_ruby
|
||||
java_array = java.util.ArrayList.new
|
||||
java_array.add_all([1,2,3,4,5])
|
||||
|
||||
assert_equal __, java_array.multiply_all
|
||||
end
|
||||
|
||||
end
|
||||
@@ -36,12 +36,12 @@ class AboutMethods < EdgeCase::Koan
|
||||
exception = assert_raise(___) do
|
||||
my_global_method
|
||||
end
|
||||
assert_match(/#{__ of arguments")}/, exception.message)
|
||||
assert_match(/__/, exception.message)
|
||||
|
||||
exception = assert_raise(___) do
|
||||
my_global_method(1,2,3)
|
||||
end
|
||||
assert_match(/#{__ of arguments")}/, exception.message)
|
||||
assert_match(/__/, exception.message)
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -3,11 +3,11 @@ 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
|
||||
assert_equal __, /pattern/.class
|
||||
end
|
||||
|
||||
def test_a_regexp_can_search_a_string_for_matching_content
|
||||
assert_equal "match", "some matching content"[/match/]
|
||||
assert_equal __, "some matching content"[/match/]
|
||||
end
|
||||
|
||||
def test_a_failed_match_returns_nil
|
||||
|
||||
@@ -29,8 +29,8 @@ class AboutScope < EdgeCase::Koan
|
||||
assert_equal __, fido.identify
|
||||
assert_equal __, rover.identify
|
||||
|
||||
assert_not_equal fido.class, rover.class
|
||||
assert_not_equal Jims::Dog, Joes::Dog
|
||||
assert_equal __, fido.class != rover.class
|
||||
assert_equal __, Jims::Dog != Joes::Dog
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
118
koans/about_sensei.rb
Normal file
118
koans/about_sensei.rb
Normal file
@@ -0,0 +1,118 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class Sensei
|
||||
def observe(step)
|
||||
# Step Protocol: step.passed? | step.failure | step.koan_file | step.name
|
||||
# WRITE THIS CODE
|
||||
end
|
||||
|
||||
def pass_count
|
||||
# WRITE THIS CODE
|
||||
end
|
||||
|
||||
def failed?
|
||||
# WRITE THIS CODE
|
||||
end
|
||||
|
||||
def instruct
|
||||
# WRITE THIS CODE
|
||||
end
|
||||
end
|
||||
|
||||
def student_passes_test
|
||||
assert true # DO NOT CHANGE YOUR STUDENT'S ANSWER
|
||||
end
|
||||
|
||||
def student_fails_test
|
||||
assert false # DO NOT CHANGE YOUR STUDENT'S ANSWER
|
||||
end
|
||||
|
||||
class AboutSensei < EdgeCase::Koan
|
||||
def test_sensei_comments_about_expanded_awareness
|
||||
you = Sensei.new
|
||||
student_step = EdgeCase::Koan.new(:student_passes_test, self)
|
||||
student_meditation = student_step.meditate
|
||||
observation = you.observe(student_meditation)
|
||||
assert_equal "AboutSensei#student_passes_test has expanded your awareness.", observation
|
||||
end
|
||||
|
||||
def test_sensei_comments_about_damaged_karma
|
||||
you = Sensei.new
|
||||
student_step = EdgeCase::Koan.new(:student_fails_test, self)
|
||||
student_meditation = student_step.meditate
|
||||
observation = you.observe(student_meditation)
|
||||
assert_equal "AboutSensei#student_fails_test has damaged your karma.", observation
|
||||
end
|
||||
|
||||
def test_sensei_counts_passed_steps
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step.meditate
|
||||
end
|
||||
assert_equal 4, you.pass_count
|
||||
end
|
||||
|
||||
def test_sensei_reports_failed_true
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step
|
||||
end
|
||||
assert you.failed?
|
||||
end
|
||||
|
||||
def test_sensei_reports_failed_true
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step
|
||||
end
|
||||
assert ! you.failed?
|
||||
end
|
||||
|
||||
def test_sensei_shows_beginning_progress
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step.meditate
|
||||
end
|
||||
instructions = you.instruct
|
||||
assert_match "You have not yet reached enlightenment", instructions
|
||||
assert_match "You have passed 0 steps", instructions
|
||||
end
|
||||
|
||||
def test_sensei_shows_partial_progress
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step.meditate
|
||||
end
|
||||
instructions = you.instruct
|
||||
assert_match "You have not yet reached enlightenment", instructions
|
||||
assert_match "You have passed 3 steps", instructions
|
||||
end
|
||||
|
||||
def test_sensei_congratulates_student
|
||||
you = Sensei.new
|
||||
# run all of Ruby Koans with you as the sensei
|
||||
EdgeCase::ThePath.new(you).walk
|
||||
|
||||
instructions = you.instruct
|
||||
assert_match "The student has become the master", instructions
|
||||
end
|
||||
end
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
require 'test/unit/assertions'
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Support code for the Ruby Koans.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
class FillMeInError < StandardError
|
||||
end
|
||||
|
||||
@@ -16,6 +20,8 @@ def in_ruby_version(*versions)
|
||||
yield if versions.any? { |v| ruby_version?(v) }
|
||||
end
|
||||
|
||||
# Standard, generic replacement value.
|
||||
# If value19 is given, it is used inplace of value for Ruby 1.9.
|
||||
def __(value="FILL ME IN", value19=:mu)
|
||||
if RUBY_VERSION < "1.9"
|
||||
value
|
||||
@@ -24,6 +30,7 @@ def __(value="FILL ME IN", value19=:mu)
|
||||
end
|
||||
end
|
||||
|
||||
# Numeric replacement value.
|
||||
def _n_(value=999999, value19=:mu)
|
||||
if RUBY_VERSION < "1.9"
|
||||
value
|
||||
@@ -32,10 +39,12 @@ def _n_(value=999999, value19=:mu)
|
||||
end
|
||||
end
|
||||
|
||||
# Error object replacement value.
|
||||
def ___(value=FillMeInError)
|
||||
value
|
||||
end
|
||||
|
||||
# Method name replacement.
|
||||
class Object
|
||||
def ____(method=nil)
|
||||
if method
|
||||
@@ -48,7 +57,25 @@ class Object
|
||||
end
|
||||
end
|
||||
|
||||
class String
|
||||
def side_padding(width)
|
||||
extra = width - self.size
|
||||
if width < 0
|
||||
self
|
||||
else
|
||||
left_padding = extra / 2
|
||||
right_padding = (extra+1)/2
|
||||
(" " * left_padding) + self + (" " *right_padding)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module EdgeCase
|
||||
class << self
|
||||
def simple_output
|
||||
ENV['SIMPLE_KOAN_OUTPUT'] == 'true'
|
||||
end
|
||||
end
|
||||
|
||||
module Color
|
||||
#shamelessly stolen (and modified) from redgreen
|
||||
@@ -97,7 +124,10 @@ module EdgeCase
|
||||
@pass_count = 0
|
||||
@failure = nil
|
||||
@failed_test = nil
|
||||
@observations = []
|
||||
end
|
||||
|
||||
def observations
|
||||
@observations ||= []
|
||||
end
|
||||
|
||||
PROGRESS_FILE_NAME = '.path_progress'
|
||||
@@ -127,13 +157,13 @@ module EdgeCase
|
||||
if step.passed?
|
||||
@pass_count += 1
|
||||
if @pass_count > progress.last.to_i
|
||||
@observations << Color.green("#{step.koan_file}##{step.name} has expanded your awareness.")
|
||||
observations << Color.green("#{step.koan_file}##{step.name} has expanded your awareness.")
|
||||
end
|
||||
else
|
||||
@failed_test = step
|
||||
@failure = step.failure
|
||||
add_progress(@pass_count)
|
||||
@observations << Color.red("#{step.koan_file}##{step.name} has damaged your karma.")
|
||||
observations << Color.red("#{step.koan_file}##{step.name} has damaged your karma.")
|
||||
throw :edgecase_exit
|
||||
end
|
||||
end
|
||||
@@ -148,7 +178,7 @@ module EdgeCase
|
||||
|
||||
def instruct
|
||||
if failed?
|
||||
@observations.each{|c| puts c }
|
||||
observations.each{|c| puts c }
|
||||
encourage
|
||||
guide_through_error
|
||||
a_zenlike_statement
|
||||
@@ -176,7 +206,23 @@ module EdgeCase
|
||||
end
|
||||
|
||||
def end_screen
|
||||
completed = <<-ENDTEXT
|
||||
screen = if EdgeCase.simple_output
|
||||
end_message
|
||||
else
|
||||
artistic_end_screen
|
||||
end
|
||||
puts screen
|
||||
end
|
||||
|
||||
def end_message
|
||||
"The student has become the master"
|
||||
end
|
||||
|
||||
def artistic_end_screen
|
||||
"JRuby 1.9.x Koans"
|
||||
ruby_version = "(in #{'J' if defined?(JRUBY_VERSION)}Ruby #{defined?(JRUBY_VERSION) ? JRUBY_VERSION : RUBY_VERSION})"
|
||||
ruby_version = ruby_version.side_padding(54)
|
||||
return <<-ENDTEXT
|
||||
,, , ,,
|
||||
: ::::, :::,
|
||||
, ,,: :::::::::::::,, :::: : ,
|
||||
@@ -187,13 +233,13 @@ module EdgeCase
|
||||
,: , ,:,,: :::::::::::::
|
||||
::,: ,,:::, ,::::::::::::,
|
||||
,:::, :,,::: ::::::::::::,
|
||||
,::: :::::::, Mountains are again merely mountains ,::::::::::::
|
||||
,::: :::::::,#{ end_message.side_padding 48 },::::::::::::
|
||||
:::,,,:::::: ::::::::::::
|
||||
,:::::::::::, ::::::::::::,
|
||||
:::::::::::, ,::::::::::::
|
||||
::::::::::::: ,::::::::::::
|
||||
:::::::::::: Ruby Koans ::::::::::::,
|
||||
:::::::::::: ,::::::::::::,
|
||||
::::::::::::#{ ruby_version },::::::::::::,
|
||||
:::::::::::, , ::::::::::::
|
||||
,:::::::::::::, brought to you by ,,::::::::::::,
|
||||
:::::::::::::: ,::::::::::::
|
||||
@@ -211,7 +257,6 @@ module EdgeCase
|
||||
,:::: , ,,
|
||||
,,,
|
||||
ENDTEXT
|
||||
puts completed
|
||||
end
|
||||
|
||||
def encourage
|
||||
@@ -260,7 +305,7 @@ ENDTEXT
|
||||
|
||||
def find_interesting_lines(backtrace)
|
||||
backtrace.reject { |line|
|
||||
line =~ /test\/unit\/|edgecase\.rb/
|
||||
line =~ /test\/unit\/|edgecase\.rb|minitest/
|
||||
}
|
||||
end
|
||||
|
||||
@@ -388,23 +433,28 @@ ENDTEXT
|
||||
end
|
||||
|
||||
class ThePath
|
||||
def walk
|
||||
sensei = EdgeCase::Sensei.new
|
||||
each_step do |step|
|
||||
sensei.observe(step.meditate)
|
||||
def initialize(sensei=nil)
|
||||
@sensei = sensei || Sensei.new
|
||||
end
|
||||
sensei.instruct
|
||||
|
||||
def walk
|
||||
each_step do |step|
|
||||
@sensei.observe(step.meditate)
|
||||
end
|
||||
@sensei.instruct
|
||||
end
|
||||
|
||||
def each_step
|
||||
catch(:edgecase_exit) {
|
||||
step_count = 0
|
||||
EdgeCase::Koan.subclasses.each_with_index do |koan,koan_index|
|
||||
if @sensei.instance_of?(EdgeCase::Sensei) || (koan.to_s != "AboutSensei")
|
||||
koan.testmethods.each do |method_name|
|
||||
step = koan.new(method_name, koan.to_s, koan_index+1, step_count+=1)
|
||||
yield step
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,4 +31,8 @@ require 'about_scope'
|
||||
require 'about_class_methods'
|
||||
require 'about_message_passing'
|
||||
require 'about_proxy_object_project'
|
||||
in_ruby_version("jruby") do
|
||||
require 'about_java_interop'
|
||||
end
|
||||
require 'about_extra_credit'
|
||||
require 'about_sensei'
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace "check" do
|
||||
puts
|
||||
end
|
||||
|
||||
desc "Check that asserts have __ replacements"
|
||||
task :asserts do
|
||||
puts "Checking for asserts missing the replacement text:"
|
||||
begin
|
||||
@@ -28,4 +29,5 @@ namespace "check" do
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run some simple consistancy checks"
|
||||
task :check => ["check:abouts", "check:asserts"]
|
||||
|
||||
@@ -18,13 +18,19 @@ class AboutArrayAssignment < EdgeCase::Koan
|
||||
assert_equal __("Smith"), last_name
|
||||
end
|
||||
|
||||
def test_parallel_assignments_with_extra_variables
|
||||
def test_parallel_assignments_with_splat_operator
|
||||
first_name, *last_name = ["John", "Smith", "III"]
|
||||
assert_equal __("John"), first_name
|
||||
assert_equal __(["Smith","III"]), last_name
|
||||
end
|
||||
|
||||
def test_parallel_assignments_with_too_few_variables
|
||||
first_name, last_name = ["Cher"]
|
||||
assert_equal __("Cher"), first_name
|
||||
assert_equal __(nil), last_name
|
||||
end
|
||||
|
||||
def test_parallel_assignements_with_subarrays
|
||||
def test_parallel_assignments_with_subarrays
|
||||
first_name, last_name = [["Willie", "Rae"], "Johnson"]
|
||||
assert_equal __(["Willie", "Rae"]), first_name
|
||||
assert_equal __("Johnson"), last_name
|
||||
|
||||
@@ -95,4 +95,30 @@ class AboutJavaInterop < EdgeCase::Koan
|
||||
assert_equal __(false), java_array.toString.is_a?(java.lang.String)
|
||||
end
|
||||
|
||||
def test_java_collections_are_enumerable
|
||||
java_array = java.util.ArrayList.new
|
||||
java_array << "one" << "two" << "three"
|
||||
assert_equal __(["ONE", "TWO", "THREE"]), java_array.map { |item| item.upcase }
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# Open the Java ArrayList class and add a new method.
|
||||
class Java::JavaUtil::ArrayList
|
||||
def multiply_all
|
||||
result = 1
|
||||
each do |item|
|
||||
result *= item
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def test_java_class_are_open_from_ruby
|
||||
java_array = java.util.ArrayList.new
|
||||
java_array.add_all([1,2,3,4,5])
|
||||
|
||||
assert_equal __(120), java_array.multiply_all
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -43,12 +43,15 @@ class AboutMethods < EdgeCase::Koan
|
||||
exception = assert_raise(___(ArgumentError)) do
|
||||
my_global_method
|
||||
end
|
||||
assert_match(/#{__("wrong (number|#) of arguments")}/, exception.message)
|
||||
#--
|
||||
pattern = "wrong (number|#) of arguments"
|
||||
#++
|
||||
assert_match(/#{__(pattern)}/, exception.message)
|
||||
|
||||
exception = assert_raise(___(ArgumentError)) do
|
||||
my_global_method(1,2,3)
|
||||
end
|
||||
assert_match(/#{__("wrong (number|#) of arguments")}/, exception.message)
|
||||
assert_match(/#{__(pattern)}/, exception.message)
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
141
src/about_sensei.rb
Normal file
141
src/about_sensei.rb
Normal file
@@ -0,0 +1,141 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
|
||||
|
||||
class Sensei
|
||||
def observe(step)
|
||||
# Step Protocol: step.passed? | step.failure | step.koan_file | step.name
|
||||
# WRITE THIS CODE
|
||||
#--
|
||||
@pass_count ||= 0
|
||||
if step.passed?
|
||||
@pass_count += 1
|
||||
"#{step.koan_file.class.to_s}##{step.name} has expanded your awareness."
|
||||
else
|
||||
@failure = step.failure
|
||||
"#{step.koan_file.class.to_s}##{step.name} has damaged your karma."
|
||||
end
|
||||
#++
|
||||
end
|
||||
|
||||
def pass_count
|
||||
# WRITE THIS CODE
|
||||
#--
|
||||
@pass_count
|
||||
#++
|
||||
end
|
||||
|
||||
def failed?
|
||||
# WRITE THIS CODE
|
||||
#--
|
||||
! @failure.nil?
|
||||
#++
|
||||
end
|
||||
|
||||
def instruct
|
||||
# WRITE THIS CODE
|
||||
#--
|
||||
if failed?
|
||||
"You have not yet reached enlightenment. You have passed #{pass_count} steps."
|
||||
else
|
||||
"The student has become the master"
|
||||
end
|
||||
#++
|
||||
end
|
||||
end
|
||||
|
||||
def student_passes_test
|
||||
assert true # DO NOT CHANGE YOUR STUDENT'S ANSWER
|
||||
end
|
||||
|
||||
def student_fails_test
|
||||
assert false # DO NOT CHANGE YOUR STUDENT'S ANSWER
|
||||
end
|
||||
|
||||
class AboutSensei < EdgeCase::Koan
|
||||
def test_sensei_comments_about_expanded_awareness
|
||||
you = Sensei.new
|
||||
student_step = EdgeCase::Koan.new(:student_passes_test, self)
|
||||
student_meditation = student_step.meditate
|
||||
observation = you.observe(student_meditation)
|
||||
assert_equal "AboutSensei#student_passes_test has expanded your awareness.", observation
|
||||
end
|
||||
|
||||
def test_sensei_comments_about_damaged_karma
|
||||
you = Sensei.new
|
||||
student_step = EdgeCase::Koan.new(:student_fails_test, self)
|
||||
student_meditation = student_step.meditate
|
||||
observation = you.observe(student_meditation)
|
||||
assert_equal "AboutSensei#student_fails_test has damaged your karma.", observation
|
||||
end
|
||||
|
||||
def test_sensei_counts_passed_steps
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step.meditate
|
||||
end
|
||||
assert_equal 4, you.pass_count
|
||||
end
|
||||
|
||||
def test_sensei_reports_failed_true
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step
|
||||
end
|
||||
assert you.failed?
|
||||
end
|
||||
|
||||
def test_sensei_reports_failed_true
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step
|
||||
end
|
||||
assert ! you.failed?
|
||||
end
|
||||
|
||||
def test_sensei_shows_beginning_progress
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step.meditate
|
||||
end
|
||||
instructions = you.instruct
|
||||
assert_match "You have not yet reached enlightenment", instructions
|
||||
assert_match "You have passed 0 steps", instructions
|
||||
end
|
||||
|
||||
def test_sensei_shows_partial_progress
|
||||
you = Sensei.new
|
||||
student_steps = [EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_passes_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self),
|
||||
EdgeCase::Koan.new(:student_fails_test, self)]
|
||||
student_steps.each do |step|
|
||||
you.observe step.meditate
|
||||
end
|
||||
instructions = you.instruct
|
||||
assert_match "You have not yet reached enlightenment", instructions
|
||||
assert_match "You have passed 3 steps", instructions
|
||||
end
|
||||
|
||||
def test_sensei_congratulates_student
|
||||
you = Sensei.new
|
||||
# run all of Ruby Koans with you as the sensei
|
||||
EdgeCase::ThePath.new(you).walk
|
||||
|
||||
instructions = you.instruct
|
||||
assert_match "The student has become the master", instructions
|
||||
end
|
||||
end
|
||||
@@ -124,7 +124,10 @@ module EdgeCase
|
||||
@pass_count = 0
|
||||
@failure = nil
|
||||
@failed_test = nil
|
||||
@observations = []
|
||||
end
|
||||
|
||||
def observations
|
||||
@observations ||= []
|
||||
end
|
||||
|
||||
PROGRESS_FILE_NAME = '.path_progress'
|
||||
@@ -154,13 +157,13 @@ module EdgeCase
|
||||
if step.passed?
|
||||
@pass_count += 1
|
||||
if @pass_count > progress.last.to_i
|
||||
@observations << Color.green("#{step.koan_file}##{step.name} has expanded your awareness.")
|
||||
observations << Color.green("#{step.koan_file}##{step.name} has expanded your awareness.")
|
||||
end
|
||||
else
|
||||
@failed_test = step
|
||||
@failure = step.failure
|
||||
add_progress(@pass_count)
|
||||
@observations << Color.red("#{step.koan_file}##{step.name} has damaged your karma.")
|
||||
observations << Color.red("#{step.koan_file}##{step.name} has damaged your karma.")
|
||||
throw :edgecase_exit
|
||||
end
|
||||
end
|
||||
@@ -175,7 +178,7 @@ module EdgeCase
|
||||
|
||||
def instruct
|
||||
if failed?
|
||||
@observations.each{|c| puts c }
|
||||
observations.each{|c| puts c }
|
||||
encourage
|
||||
guide_through_error
|
||||
a_zenlike_statement
|
||||
@@ -203,22 +206,23 @@ module EdgeCase
|
||||
end
|
||||
|
||||
def end_screen
|
||||
if EdgeCase.simple_output
|
||||
boring_end_screen
|
||||
screen = if EdgeCase.simple_output
|
||||
end_message
|
||||
else
|
||||
artistic_end_screen
|
||||
end
|
||||
puts screen
|
||||
end
|
||||
|
||||
def boring_end_screen
|
||||
puts "Mountains are again merely mountains"
|
||||
def end_message
|
||||
"The student has become the master"
|
||||
end
|
||||
|
||||
def artistic_end_screen
|
||||
"JRuby 1.9.x Koans"
|
||||
ruby_version = "(in #{'J' if defined?(JRUBY_VERSION)}Ruby #{defined?(JRUBY_VERSION) ? JRUBY_VERSION : RUBY_VERSION})"
|
||||
ruby_version = ruby_version.side_padding(54)
|
||||
completed = <<-ENDTEXT
|
||||
return <<-ENDTEXT
|
||||
,, , ,,
|
||||
: ::::, :::,
|
||||
, ,,: :::::::::::::,, :::: : ,
|
||||
@@ -229,7 +233,7 @@ module EdgeCase
|
||||
,: , ,:,,: :::::::::::::
|
||||
::,: ,,:::, ,::::::::::::,
|
||||
,:::, :,,::: ::::::::::::,
|
||||
,::: :::::::, Mountains are again merely mountains ,::::::::::::
|
||||
,::: :::::::,#{ end_message.side_padding 48 },::::::::::::
|
||||
:::,,,:::::: ::::::::::::
|
||||
,:::::::::::, ::::::::::::,
|
||||
:::::::::::, ,::::::::::::
|
||||
@@ -253,7 +257,6 @@ module EdgeCase
|
||||
,:::: , ,,
|
||||
,,,
|
||||
ENDTEXT
|
||||
puts completed
|
||||
end
|
||||
|
||||
def encourage
|
||||
@@ -430,23 +433,28 @@ ENDTEXT
|
||||
end
|
||||
|
||||
class ThePath
|
||||
def walk
|
||||
sensei = EdgeCase::Sensei.new
|
||||
each_step do |step|
|
||||
sensei.observe(step.meditate)
|
||||
def initialize(sensei=nil)
|
||||
@sensei = sensei || Sensei.new
|
||||
end
|
||||
sensei.instruct
|
||||
|
||||
def walk
|
||||
each_step do |step|
|
||||
@sensei.observe(step.meditate)
|
||||
end
|
||||
@sensei.instruct
|
||||
end
|
||||
|
||||
def each_step
|
||||
catch(:edgecase_exit) {
|
||||
step_count = 0
|
||||
EdgeCase::Koan.subclasses.each_with_index do |koan,koan_index|
|
||||
if @sensei.instance_of?(EdgeCase::Sensei) || (koan.to_s != "AboutSensei")
|
||||
koan.testmethods.each do |method_name|
|
||||
step = koan.new(method_name, koan.to_s, koan_index+1, step_count+=1)
|
||||
yield step
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,4 +31,8 @@ require 'about_scope'
|
||||
require 'about_class_methods'
|
||||
require 'about_message_passing'
|
||||
require 'about_proxy_object_project'
|
||||
in_ruby_version("jruby") do
|
||||
require 'about_java_interop'
|
||||
end
|
||||
require 'about_extra_credit'
|
||||
require 'about_sensei'
|
||||
|
||||
Reference in New Issue
Block a user