diff --git a/koans/GREED_RULES.txt b/koans/GREED_RULES.txt deleted file mode 100644 index 58b5a9c..0000000 --- a/koans/GREED_RULES.txt +++ /dev/null @@ -1,66 +0,0 @@ -= Playing Greed - -Greed is a dice game played among 2 or more players, using 5 -six-sided dice. - -== Playing Greed - -Each player takes a turn consisting of one or more rolls of the dice. -On the first roll of the game, a player rolls all five dice which are -scored according to the following: - - Three 1's => 1000 points - Three 6's => 600 points - Three 5's => 500 points - Three 4's => 400 points - Three 3's => 300 points - Three 2's => 200 points - One 1 => 100 points - One 5 => 50 points - -A single die can only be counted once in each roll. For example, -a "5" can only count as part of a triplet (contributing to the 500 -points) or as a single 50 points, but not both in the same roll. - -Example Scoring - - Throw Score - --------- ------------------ - 5 1 3 4 1 50 + 2 * 100 = 250 - 1 1 1 3 1 1000 + 100 = 1100 - 2 4 4 5 4 400 + 50 = 450 - -The dice not contributing to the score are called the non-scoring -dice. "3" and "4" are non-scoring dice in the first example. "3" is -a non-scoring die in the second, and "2" is a non-score die in the -final example. - -After a player rolls and the score is calculated, the scoring dice are -removed and the player has the option of rolling again using only the -non-scoring dice. If all of the thrown dice are scoring, then the -player may roll all 5 dice in the next roll. - -The player may continue to roll as long as each roll scores points. If -a roll has zero points, then the player loses not only their turn, but -also accumulated score for that turn. If a player decides to stop -rolling before rolling a zero-point roll, then the accumulated points -for the turn is added to his total score. - -== Getting "In The Game" - -Before a player is allowed to accumulate points, they must get at -least 300 points in a single turn. Once they have achieved 300 points -in a single turn, the points earned in that turn and each following -turn will be counted toward their total score. - -== End Game - -Once a player reaches 3000 (or more) points, the game enters the final -round where each of the other players gets one more turn. The winner -is the player with the highest score after the final round. - -== References - -Greed is described on Wikipedia at -http://en.wikipedia.org/wiki/Greed_(dice_game), however the rules are -a bit different from the rules given here. diff --git a/koans/README.rdoc b/koans/README.rdoc deleted file mode 100644 index fb6abb1..0000000 --- a/koans/README.rdoc +++ /dev/null @@ -1,146 +0,0 @@ -= 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 -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. - -== 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. - -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. - -== 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 -installed. To check the installations simply type: - -*nix platforms from any terminal window: - - [~] $ ruby --version - [~] $ rake --version - -Windows from the command prompt (cmd.exe) - - c:\ruby --version - c:\rake --version - -If you don't have rake installed, just run `gem install rake` - -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 - -You can run the tests through rake or by calling the file itself (rake is the -recommended way to run them as we might build more functionality into this task). - -*nix platforms, from the koans directory - - [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 -moment and reflect upon the test to see what it is teaching you and improve the -code to better communicate its intent (refactor). - -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 ... - 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. - def test_assert_truth - assert false # This should be true - end - -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+ -method, it will either ensure it is +true+ and continue on, or fail if in fact -the statement is +false+. - -== Inspiration - -A special thanks to Mike Clark and Ara Howard for inspiring this -project. Mike Clark wrote an excellent blog post about learning Ruby -through unit testing. This sparked an idea that has taken a bit to -solidify, that of bringing new rubyists into the community through -testing. Ara Howard then gave us the idea for the Koans in his ruby -quiz entry on Meta Koans (a must for any rubyist wanting to improve -their skills). Also, "The Little Lisper" taught us all the value of -the short questions/simple answers style of learning. - -Mike Clark's post :: http://www.clarkware.com/cgi/blosxom/2005/03/18 -Meta Koans :: http://rubyquiz.com/quiz67.html -The Little Lisper :: http://www.amazon.com/Little-LISPer-Third-Daniel-Friedman/dp/0023397632 - -== Other Resources - -The Ruby Language :: http://ruby-lang.org -Try Ruby in your browser :: http://tryruby.org - -Dave Thomas' introduction to Ruby Programming Ruby (the Pick Axe) :: http://pragprog.com/titles/ruby/programming-ruby - -Brian Marick's fantastic guide for beginners Everyday Scripting with Ruby :: http://pragprog.com/titles/bmsft/everyday-scripting-with-ruby - -= Other stuff - -Author :: Jim Weirich -Author :: Joe O'Brien -Issue Tracker :: http://www.pivotaltracker.com/projects/48111 -Requires :: Ruby 1.8.x or later and Rake (any recent version) - -= License - -http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png - -RubyKoans is released under a Creative Commons, -Attribution-NonCommercial-ShareAlike, Version 3.0 -(http://creativecommons.org/licenses/by-nc-sa/3.0/) License. diff --git a/koans/Rakefile b/koans/Rakefile deleted file mode 100644 index 1a2c7f2..0000000 --- a/koans/Rakefile +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ruby -# -*- ruby -*- - -require 'rake/clean' -require 'rake/testtask' - -task :default => :test - -task :test do - ruby 'path_to_enlightenment.rb' -end - diff --git a/koans/about_array_assignment.rb b/koans/about_array_assignment.rb deleted file mode 100644 index 21a64bb..0000000 --- a/koans/about_array_assignment.rb +++ /dev/null @@ -1,51 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutArrayAssignment < EdgeCase::Koan - def test_non_parallel_assignment - names = ["John", "Smith"] - assert_equal __, names - end - - def test_parallel_assignments - first_name, last_name = ["John", "Smith"] - assert_equal __, first_name - assert_equal __, last_name - end - - def test_parallel_assignments_with_extra_values - first_name, last_name = ["John", "Smith", "III"] - assert_equal __, first_name - assert_equal __, last_name - end - - 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_assignments_with_subarrays - first_name, last_name = [["Willie", "Rae"], "Johnson"] - assert_equal __, first_name - assert_equal __, last_name - end - - def test_parallel_assignment_with_one_variable - first_name, = ["John", "Smith"] - 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 diff --git a/koans/about_arrays.rb b/koans/about_arrays.rb deleted file mode 100644 index 9f27b5a..0000000 --- a/koans/about_arrays.rb +++ /dev/null @@ -1,84 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutArrays < EdgeCase::Koan - def test_creating_arrays - empty_array = Array.new - assert_equal __, empty_array.class - assert_equal __, empty_array.size - end - - def test_array_literals - array = Array.new - assert_equal [], array - - array[0] = 1 - assert_equal [1], array - - array[1] = 2 - assert_equal [1, __], array - - array << 333 - assert_equal __, array - end - - def test_accessing_array_elements - array = [:peanut, :butter, :and, :jelly] - - assert_equal __, array[0] - assert_equal __, array.first - assert_equal __, array[3] - assert_equal __, array.last - assert_equal __, array[-1] - assert_equal __, array[-3] - end - - def test_slicing_arrays - array = [:peanut, :butter, :and, :jelly] - - assert_equal __, array[0,1] - assert_equal __, array[0,2] - assert_equal __, array[2,2] - assert_equal __, array[2,20] - assert_equal __, array[4,0] - assert_equal __, array[4,100] - assert_equal __, array[5,0] - end - - def test_arrays_and_ranges - assert_equal __, (1..5).class - assert_not_equal [1,2,3,4,5], (1..5) - assert_equal __, (1..5).to_a - assert_equal __, (1...5).to_a - end - - def test_slicing_with_ranges - array = [:peanut, :butter, :and, :jelly] - - assert_equal __, array[0..2] - assert_equal __, array[0...2] - assert_equal __, array[2..-1] - end - - def test_pushing_and_popping_arrays - array = [1,2] - array.push(:last) - - assert_equal __, array - - popped_value = array.pop - assert_equal __, popped_value - assert_equal __, array - end - - def test_shifting_arrays - array = [1,2] - array.unshift(:first) - - assert_equal __, array - - shifted_value = array.shift - assert_equal __, shifted_value - assert_equal __, array - end - -end diff --git a/koans/about_asserts.rb b/koans/about_asserts.rb deleted file mode 100644 index e1c34d4..0000000 --- a/koans/about_asserts.rb +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env ruby -# -*- ruby -*- - -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutAsserts < EdgeCase::Koan - - # We shall contemplate truth by testing reality, via asserts. - def test_assert_truth - assert false # This should be true - end - - # Enlightenment may be more easily achieved with appropriate - # messages. - def test_assert_with_message - assert false, "This should be true -- Please fix this" - end - - # To understand reality, we must compare our expectations against - # reality. - def test_assert_equality - expected_value = __ - actual_value = 1 + 1 - - assert expected_value == actual_value - end - - # Some ways of asserting equality are better than others. - def test_a_better_way_of_asserting_equality - expected_value = __ - actual_value = 1 + 1 - - assert_equal expected_value, actual_value - end - - # Sometimes we will ask you to fill in the values - def test_fill_in_values - assert_equal __, 1 + 1 - end -end diff --git a/koans/about_blocks.rb b/koans/about_blocks.rb deleted file mode 100644 index 0abee8f..0000000 --- a/koans/about_blocks.rb +++ /dev/null @@ -1,96 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutBlocks < EdgeCase::Koan - def method_with_block - result = yield - result - end - - def test_methods_can_take_blocks - yielded_result = method_with_block { 1 + 2 } - assert_equal __, yielded_result - end - - def test_blocks_can_be_defined_with_do_end_too - yielded_result = method_with_block do 1 + 2 end - assert_equal __, yielded_result - end - - # ------------------------------------------------------------------ - - def method_with_block_arguments - yield("Jim") - end - - def test_blocks_can_take_arguments - result = method_with_block_arguments do |argument| - assert_equal __, argument - end - end - - # ------------------------------------------------------------------ - - def many_yields - yield(:peanut) - yield(:butter) - yield(:and) - yield(:jelly) - end - - def test_methods_can_call_yield_many_times - result = [] - many_yields { |item| result << item } - assert_equal __, result - end - - # ------------------------------------------------------------------ - - def yield_tester - if block_given? - yield - else - :no_block - end - end - - def test_methods_can_see_if_they_have_been_called_with_a_block - assert_equal __, yield_tester { :with_block } - assert_equal __, yield_tester - end - - # ------------------------------------------------------------------ - - def test_block_can_affect_variables_in_the_code_where_they_are_created - value = :initial_value - method_with_block { value = :modified_in_a_block } - assert_equal __, value - end - - def test_blocks_can_be_assigned_to_variables_and_called_explicitly - add_one = lambda { |n| n + 1 } - assert_equal __, add_one.call(10) - - # Alternative calling sequence - assert_equal __, add_one[10] - end - - def test_stand_alone_blocks_can_be_passed_to_methods_expecting_blocks - make_upper = lambda { |n| n.upcase } - result = method_with_block_arguments(&make_upper) - assert_equal __, result - end - - # ------------------------------------------------------------------ - - def method_with_explicit_block(&block) - block.call(10) - end - - def test_methods_can_take_an_explicit_block_argument - assert_equal __, method_with_explicit_block { |n| n * 2 } - - add_one = lambda { |n| n + 1 } - assert_equal __, method_with_explicit_block(&add_one) - end - -end diff --git a/koans/about_class_methods.rb b/koans/about_class_methods.rb deleted file mode 100644 index ddd32bd..0000000 --- a/koans/about_class_methods.rb +++ /dev/null @@ -1,170 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutClassMethods < EdgeCase::Koan - class Dog - end - - def test_objects_are_objects - fido = Dog.new - assert_equal __, fido.is_a?(Object) - end - - def test_classes_are_classes - assert_equal __, Dog.is_a?(Class) - end - - def test_classes_are_objects_too - assert_equal __, Dog.is_a?(Object) - end - - def test_objects_have_methods - fido = Dog.new - assert fido.methods.size > _n_ - end - - def test_classes_have_methods - assert Dog.methods.size > _n_ - end - - def test_you_can_define_methods_on_individual_objects - fido = Dog.new - def fido.wag - :fidos_wag - end - assert_equal __, fido.wag - end - - def test_other_objects_are_not_affected_by_these_singleton_methods - fido = Dog.new - rover = Dog.new - def fido.wag - :fidos_wag - end - - assert_raise(___) do - rover.wag - end - end - - # ------------------------------------------------------------------ - - class Dog2 - def wag - :instance_level_wag - end - end - - def Dog2.wag - :class_level_wag - end - - def test_since_classes_are_objects_you_can_define_singleton_methods_on_them_too - assert_equal __, Dog2.wag - end - - def test_class_methods_are_independent_of_instance_methods - fido = Dog2.new - assert_equal __, fido.wag - assert_equal __, Dog2.wag - end - - # ------------------------------------------------------------------ - - class Dog - attr_accessor :name - end - - def Dog.name - @name - end - - def test_classes_and_instances_do_not_share_instance_variables - fido = Dog.new - fido.name = "Fido" - assert_equal __, fido.name - assert_equal __, Dog.name - end - - # ------------------------------------------------------------------ - - class Dog - def Dog.a_class_method - :dogs_class_method - end - end - - def test_you_can_define_class_methods_inside_the_class - assert_equal __, Dog.a_class_method - end - - - # ------------------------------------------------------------------ - - LastExpressionInClassStatement = class Dog - 21 - end - - def test_class_statements_return_the_value_of_their_last_expression - assert_equal __, LastExpressionInClassStatement - end - - # ------------------------------------------------------------------ - - SelfInsideOfClassStatement = class Dog - self - end - - def test_self_while_inside_class_is_class_object_not_instance - assert_equal __, Dog == SelfInsideOfClassStatement - end - - # ------------------------------------------------------------------ - - class Dog - def self.class_method2 - :another_way_to_write_class_methods - end - end - - def test_you_can_use_self_instead_of_an_explicit_reference_to_dog - assert_equal __, Dog.class_method2 - end - - # ------------------------------------------------------------------ - - class Dog - class << self - def another_class_method - :still_another_way - end - end - end - - def test_heres_still_another_way_to_write_class_methods - assert_equal __, Dog.another_class_method - end - - # THINK ABOUT IT: - # - # The two major ways to write class methods are: - # class Demo - # def self.method - # end - # - # class << self - # def class_methods - # end - # end - # end - # - # Which do you prefer and why? - # Are there times you might prefer one over the other? - - # ------------------------------------------------------------------ - - def test_heres_an_easy_way_to_call_class_methods_from_instance_methods - fido = Dog.new - assert_equal __, fido.class.another_class_method - end - -end diff --git a/koans/about_classes.rb b/koans/about_classes.rb deleted file mode 100644 index 3fce646..0000000 --- a/koans/about_classes.rb +++ /dev/null @@ -1,190 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutClasses < EdgeCase::Koan - class Dog - end - - def test_instances_of_classes_can_be_created_with_new - fido = Dog.new - assert_equal __, fido.class - end - - # ------------------------------------------------------------------ - - class Dog2 - def set_name(a_name) - @name = a_name - end - end - - def test_instance_variables_can_be_set_by_assigning_to_them - fido = Dog2.new - assert_equal __, fido.instance_variables - - fido.set_name("Fido") - assert_equal __, fido.instance_variables - end - - def test_instance_variables_cannot_be_accessed_outside_the_class - fido = Dog2.new - fido.set_name("Fido") - - assert_raise(___) do - fido.name - end - - assert_raise(___) do - eval "fido.@name" - # NOTE: Using eval because the above line is a syntax error. - end - end - - def test_you_can_politely_ask_for_instance_variable_values - fido = Dog2.new - fido.set_name("Fido") - - assert_equal __, fido.instance_variable_get("@name") - end - - def test_you_can_rip_the_value_out_using_instance_eval - fido = Dog2.new - fido.set_name("Fido") - - assert_equal __, fido.instance_eval("@name") # string version - assert_equal __, fido.instance_eval { @name } # block version - end - - # ------------------------------------------------------------------ - - class Dog3 - def set_name(a_name) - @name = a_name - end - def name - @name - end - end - - def test_you_can_create_accessor_methods_to_return_instance_variables - fido = Dog3.new - fido.set_name("Fido") - - assert_equal __, fido.name - end - - # ------------------------------------------------------------------ - - class Dog4 - attr_reader :name - - def set_name(a_name) - @name = a_name - end - end - - - def test_attr_reader_will_automatically_define_an_accessor - fido = Dog4.new - fido.set_name("Fido") - - assert_equal __, fido.name - end - - # ------------------------------------------------------------------ - - class Dog5 - attr_accessor :name - end - - - def test_attr_accessor_will_automatically_define_both_read_and_write_accessors - fido = Dog5.new - - fido.name = "Fido" - assert_equal __, fido.name - end - - # ------------------------------------------------------------------ - - class Dog6 - attr_reader :name - def initialize(initial_name) - @name = initial_name - end - end - - def test_initialize_provides_initial_values_for_instance_variables - fido = Dog6.new("Fido") - assert_equal __, fido.name - end - - def test_args_to_new_must_match_initialize - assert_raise(___) do - Dog6.new - end - # THINK ABOUT IT: - # Why is this so? - end - - def test_different_objects_have_different_instance_variables - fido = Dog6.new("Fido") - rover = Dog6.new("Rover") - - assert_equal __, rover.name != fido.name - end - - # ------------------------------------------------------------------ - - class Dog7 - attr_reader :name - - def initialize(initial_name) - @name = initial_name - end - - def get_self - self - end - - def to_s - __ - end - - def inspect - "" - end - end - - def test_inside_a_method_self_refers_to_the_containing_object - fido = Dog7.new("Fido") - - fidos_self = fido.get_self - assert_equal __, fidos_self - end - - def test_to_s_provides_a_string_version_of_the_object - fido = Dog7.new("Fido") - 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}" - end - - def test_inspect_provides_a_more_complete_string_version - fido = Dog7.new("Fido") - assert_equal __, fido.inspect - end - - def test_all_objects_support_to_s_and_inspect - array = [1,2,3] - - assert_equal __, array.to_s - assert_equal __, array.inspect - - assert_equal __, "STRING".to_s - assert_equal __, "STRING".inspect - end - -end diff --git a/koans/about_constants.rb b/koans/about_constants.rb deleted file mode 100644 index 41d3f01..0000000 --- a/koans/about_constants.rb +++ /dev/null @@ -1,87 +0,0 @@ -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 hierarchy? - - # ------------------------------------------------------------------ - - 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 hierarchy? Why is it - # different than the previous answer? -end diff --git a/koans/about_control_statements.rb b/koans/about_control_statements.rb deleted file mode 100644 index df503d7..0000000 --- a/koans/about_control_statements.rb +++ /dev/null @@ -1,134 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutControlStatements < EdgeCase::Koan - - def test_if_then_else_statements - if true - result = :true_value - else - result = :false_value - end - assert_equal __, result - end - - def test_if_then_statements - result = :default_value - if true - result = :true_value - end - assert_equal __, result - end - - def test_if_statements_return_values - value = if true - :true_value - else - :false_value - end - assert_equal __, value - - value = if false - :true_value - else - :false_value - end - assert_equal __, value - - # NOTE: Actually, EVERY statement in Ruby will return a value, not - # just if statements. - end - - def test_if_statements_with_no_else_with_false_condition_return_value - value = if false - :true_value - end - assert_equal __, value - end - - def test_condition_operators - assert_equal __, (true ? :true_value : :false_value) - assert_equal __, (false ? :true_value : :false_value) - end - - def test_if_statement_modifiers - result = :default_value - result = :true_value if true - - assert_equal __, result - end - - def test_unless_statement - result = :default_value - unless false # same as saying 'if !false', which evaluates as 'if true' - result = :false_value - end - assert_equal __, result - end - - def test_unless_statement_evaluate_true - result = :default_value - unless true # same as saying 'if !true', which evaluates as 'if false' - result = :true_value - end - assert_equal __, result - end - - def test_unless_statement_modifier - result = :default_value - result = :false_value unless false - - assert_equal __, result - end - - def test_while_statement - i = 1 - result = 1 - while i <= 10 - result = result * i - i += 1 - end - assert_equal __, result - end - - def test_break_statement - i = 1 - result = 1 - while true - break unless i <= 10 - result = result * i - i += 1 - end - assert_equal __, result - end - - def test_break_statement_returns_values - i = 1 - result = while i <= 10 - break i if i % 2 == 0 - i += 1 - end - - assert_equal __, result - end - - def test_next_statement - i = 0 - result = [] - while i < 10 - i += 1 - next if (i % 2) == 0 - result << i - end - assert_equal __, result - end - - def test_for_statement - array = ["fish", "and", "chips"] - result = [] - for item in array - result << item.upcase - end - assert_equal [__, __, __], result - end - -end diff --git a/koans/about_dice_project.rb b/koans/about_dice_project.rb deleted file mode 100644 index ce81715..0000000 --- a/koans/about_dice_project.rb +++ /dev/null @@ -1,63 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -# Implement a DiceSet Class here: -# -# class DiceSet -# code ... -# end - -class AboutDiceProject < EdgeCase::Koan - def test_can_create_a_dice_set - dice = DiceSet.new - assert_not_nil dice - end - - def test_rolling_the_dice_returns_a_set_of_integers_between_1_and_6 - dice = DiceSet.new - - dice.roll(5) - assert dice.values.is_a?(Array), "should be an array" - assert_equal 5, dice.values.size - dice.values.each do |value| - assert value >= 1 && value <= 6, "value #{value} must be between 1 and 6" - end - end - - def test_dice_values_do_not_change_unless_explicitly_rolled - dice = DiceSet.new - dice.roll(5) - first_time = dice.values - second_time = dice.values - assert_equal first_time, second_time - end - - def test_dice_values_should_change_between_rolls - dice = DiceSet.new - - dice.roll(5) - first_time = dice.values - - dice.roll(5) - second_time = dice.values - - assert_not_equal first_time, second_time, - "Two rolls should not be equal" - - # THINK ABOUT IT: - # - # If the rolls are random, then it is possible (although not - # likely) that two consecutive rolls are equal. What would be a - # better way to test this. - end - - def test_you_can_roll_different_numbers_of_dice - dice = DiceSet.new - - dice.roll(3) - assert_equal 3, dice.values.size - - dice.roll(1) - assert_equal 1, dice.values.size - end - -end diff --git a/koans/about_exceptions.rb b/koans/about_exceptions.rb deleted file mode 100644 index d745f96..0000000 --- a/koans/about_exceptions.rb +++ /dev/null @@ -1,68 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutExceptions < EdgeCase::Koan - - class MySpecialError < RuntimeError - end - - def test_exceptions_inherit_from_Exception - assert_equal __, MySpecialError.ancestors[1] - assert_equal __, MySpecialError.ancestors[2] - assert_equal __, MySpecialError.ancestors[3] - assert_equal __, MySpecialError.ancestors[4] - end - - def test_rescue_clause - result = nil - begin - fail "Oops" - rescue StandardError => ex - result = :exception_handled - end - - assert_equal __, result - - assert_equal __, ex.is_a?(StandardError), "Should be a Standard Error" - assert_equal __, ex.is_a?(RuntimeError), "Should be a Runtime Error" - - assert RuntimeError.ancestors.include?(StandardError), - "RuntimeError is a subclass of StandardError" - - assert_equal __, ex.message - end - - def test_raising_a_particular_error - result = nil - begin - # 'raise' and 'fail' are synonyms - raise MySpecialError, "My Message" - rescue MySpecialError => ex - result = :exception_handled - end - - assert_equal __, result - assert_equal __, ex.message - end - - def test_ensure_clause - result = nil - begin - fail "Oops" - rescue StandardError => ex - # no code here - ensure - result = :always_run - end - - assert_equal __, result - end - - # Sometimes, we must know about the unknown - def test_asserting_an_error_is_raised - # A do-end is a block, a topic to explore more later - assert_raise(___) do - raise MySpecialError.new("New instances can be raised directly.") - end - end - -end diff --git a/koans/about_extra_credit.rb b/koans/about_extra_credit.rb deleted file mode 100644 index 5012edf..0000000 --- a/koans/about_extra_credit.rb +++ /dev/null @@ -1,8 +0,0 @@ -# EXTRA CREDIT: -# -# Create a program that will play the Greed Game. -# Rules for the game are in GREED_RULES.TXT. -# -# You already have a DiceSet class and score function you can use. -# Write a player class and a Game class to complete the project. This -# is a free form assignment, so approach it however you desire. diff --git a/koans/about_hashes.rb b/koans/about_hashes.rb deleted file mode 100644 index 511e3c1..0000000 --- a/koans/about_hashes.rb +++ /dev/null @@ -1,116 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutHashes < EdgeCase::Koan - def test_creating_hashes - empty_hash = Hash.new - assert_equal __, empty_hash.class - assert_equal({}, empty_hash) - assert_equal __, empty_hash.size - end - - def test_hash_literals - hash = { :one => "uno", :two => "dos" } - assert_equal __, hash.size - end - - def test_accessing_hashes - hash = { :one => "uno", :two => "dos" } - assert_equal __, hash[:one] - assert_equal __, hash[:two] - assert_equal __, hash[:doesnt_exist] - end - - def test_accessing_hashes_with_fetch - hash = { :one => "uno" } - assert_equal "uno", hash.fetch(:one) - assert_raise(___) do - hash.fetch(:doesnt_exist) - end - - # THINK ABOUT IT: - # - # Why might you want to use #fetch instead of #[] when accessing hash keys? - end - - def test_changing_hashes - hash = { :one => "uno", :two => "dos" } - hash[:one] = "eins" - - expected = { :one => __, :two => "dos" } - assert_equal __, expected == hash - - # Bonus Question: Why was "expected" broken out into a variable - # rather than used as a literal? - end - - def test_hash_is_unordered - hash1 = { :one => "uno", :two => "dos" } - hash2 = { :two => "dos", :one => "uno" } - - assert_equal __, hash1 == hash2 - end - - def test_hash_keys - hash = { :one => "uno", :two => "dos" } - assert_equal __, hash.keys.size - assert_equal __, hash.keys.include?(:one) - assert_equal __, hash.keys.include?(:two) - assert_equal __, hash.keys.class - end - - def test_hash_values - hash = { :one => "uno", :two => "dos" } - assert_equal __, hash.values.size - assert_equal __, hash.values.include?("uno") - assert_equal __, hash.values.include?("dos") - 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_equal __, hash != new_hash - - expected = { "jim" => __, "amy" => 20, "dan" => 23, "jenny" => __ } - assert_equal __, expected == new_hash - end - - def test_default_value - hash1 = Hash.new - hash1[:one] = 1 - - assert_equal __, hash1[:one] - assert_equal __, hash1[:two] - - hash2 = Hash.new("dos") - hash2[:one] = 1 - - assert_equal __, hash2[:one] - assert_equal __, hash2[:two] - end - - def test_default_value_is_the_same_object - hash = Hash.new([]) - - hash[:one] << "uno" - hash[:two] << "dos" - - assert_equal __, hash[:one] - assert_equal __, hash[:two] - assert_equal __, hash[:three] - - assert_equal __, hash[:one].object_id == hash[:two].object_id - end - - def test_default_value_with_block - hash = Hash.new {|hash, key| hash[key] = [] } - - hash[:one] << "uno" - hash[:two] << "dos" - - assert_equal __, hash[:one] - assert_equal __, hash[:two] - assert_equal __, hash[:three] - end -end diff --git a/koans/about_inheritance.rb b/koans/about_inheritance.rb deleted file mode 100644 index 712daca..0000000 --- a/koans/about_inheritance.rb +++ /dev/null @@ -1,85 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutInheritance < EdgeCase::Koan - class Dog - attr_reader :name - - def initialize(name) - @name = name - end - - def bark - "WOOF" - end - end - - class Chihuahua < Dog - def wag - :happy - end - - def bark - "yip" - end - end - - def test_subclasses_have_the_parent_as_an_ancestor - assert_equal __, Chihuahua.ancestors.include?(Dog) - end - - def test_all_classes_ultimately_inherit_from_object - assert_equal __, Chihuahua.ancestors.include?(Object) - end - - def test_subclasses_inherit_behavior_from_parent_class - chico = Chihuahua.new("Chico") - assert_equal __, chico.name - end - - def test_subclasses_add_new_behavior - chico = Chihuahua.new("Chico") - assert_equal __, chico.wag - - assert_raise(___) do - fido = Dog.new("Fido") - fido.wag - end - end - - def test_subclasses_can_modify_existing_behavior - chico = Chihuahua.new("Chico") - assert_equal __, chico.bark - - fido = Dog.new("Fido") - assert_equal __, fido.bark - end - - # ------------------------------------------------------------------ - - class BullDog < Dog - def bark - super + ", GROWL" - end - end - - def test_subclasses_can_invoke_parent_behavior_via_super - ralph = BullDog.new("Ralph") - assert_equal __, ralph.bark - end - - # ------------------------------------------------------------------ - - class GreatDane < Dog - def growl - super.bark + ", GROWL" - end - end - - def test_super_does_not_work_cross_method - george = GreatDane.new("George") - assert_raise(___) do - george.growl - end - end - -end diff --git a/koans/about_iteration.rb b/koans/about_iteration.rb deleted file mode 100644 index fb62b39..0000000 --- a/koans/about_iteration.rb +++ /dev/null @@ -1,124 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutIteration < EdgeCase::Koan - - # -- An Aside ------------------------------------------------------ - # Ruby 1.8 stores names as strings. Ruby 1.9 stores names as - # symbols. So we use a version dependent method "as_name" to convert - # to the right format in the koans. We will use "as_name" whenever - # comparing to lists of methods. - - in_ruby_version("1.8") do - def as_name(name) - name.to_s - end - end - - in_ruby_version("1.9") do - def as_name(name) - name.to_sym - end - end - - # Ok, now back to the Koans. - # ------------------------------------------------------------------- - - def test_each_is_a_method_on_arrays - assert_equal __, [].methods.include?(as_name(:each)) - end - - def test_iterating_with_each - array = [1, 2, 3] - sum = 0 - array.each do |item| - sum += item - end - assert_equal __, sum - end - - def test_each_can_use_curly_brace_blocks_too - array = [1, 2, 3] - sum = 0 - array.each { |item| - sum += item - } - assert_equal __, sum - end - - def test_break_works_with_each_style_iterations - array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - sum = 0 - array.each { |item| - break if item > 3 - sum += item - } - assert_equal __, sum - end - - def test_collect_transforms_elements_of_an_array - array = [1, 2, 3] - new_array = array.collect { |item| item + 10 } - assert_equal __, new_array - - # NOTE: 'map' is another name for the 'collect' operation - another_array = array.map { |item| item + 10 } - assert_equal __, another_array - end - - def test_select_selects_certain_items_from_an_array - array = [1, 2, 3, 4, 5, 6] - - even_numbers = array.select { |item| (item % 2) == 0 } - assert_equal __, even_numbers - - # NOTE: 'find_all' is another name for the 'select' operation - more_even_numbers = array.find_all { |item| (item % 2) == 0 } - assert_equal __, more_even_numbers - end - - def test_find_locates_the_first_element_matching_a_criteria - array = ["Jim", "Bill", "Clarence", "Doug", "Eli"] - - assert_equal __, array.find { |item| item.size > 4 } - end - - def test_inject_will_blow_your_mind - result = [2, 3, 4].inject(0) { |sum, item| sum + item } - assert_equal __, result - - result2 = [2, 3, 4].inject(1) { |sum, item| sum * item } - assert_equal __, result2 - - # Extra Credit: - # Describe in your own words what inject does. - end - - def test_all_iteration_methods_work_on_any_collection_not_just_arrays - # Ranges act like a collection - result = (1..3).map { |item| item + 10 } - assert_equal __, result - - # Files act like a collection of lines - File.open("example_file.txt") do |file| - upcase_lines = file.map { |line| line.strip.upcase } - assert_equal __, upcase_lines - end - - # NOTE: You can create your own collections that work with each, - # map, select, etc. - end - - # Bonus Question: In the previous koan, we saw the construct: - # - # File.open(filename) do |file| - # # code to read 'file' - # end - # - # Why did we do it that way instead of the following? - # - # file = File.open(filename) - # # code to read 'file' - # - # When you get to the "AboutSandwichCode" koan, recheck your answer. - -end diff --git a/koans/about_java_interop.rb b/koans/about_java_interop.rb deleted file mode 100644 index 4d35d5d..0000000 --- a/koans/about_java_interop.rb +++ /dev/null @@ -1,137 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -include Java - -# Concepts -# * Pull in a java class -# * calling a method, Camel vs snake -# * Resolving 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_some_ruby_objects_can_be_coerced_to_java - assert_equal __, "ruby string".to_java.class - assert_equal __, 1.to_java.class - assert_equal __, 9.32.to_java.class - assert_equal __, false.to_java.class - end - - def test_some_ruby_objects_are_not_coerced_to_what_you_might_expect - assert_equal __, [].to_java.class == Java::JavaUtil::ArrayList - assert_equal __, {}.to_java.class == Java::JavaUtil::HashMap - assert_equal __, Object.new.to_java.class == Java::JavaLang::Object - 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 diff --git a/koans/about_message_passing.rb b/koans/about_message_passing.rb deleted file mode 100644 index a978dde..0000000 --- a/koans/about_message_passing.rb +++ /dev/null @@ -1,178 +0,0 @@ -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? - 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? - end - - def test_send_with_underscores_will_also_send_messages - mc = MessageCatcher.new - - assert_equal __, mc.__send__(:caught?) - - # THINK ABOUT IT: - # - # Why does Ruby provide both send and __send__ ? - end - - 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) - 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) - - assert_equal __, mc.add_a_payload(3, 4, nil, 6) - assert_equal __, mc.send(:add_a_payload, 3, 4, nil, 6) - end - - # ------------------------------------------------------------------ - - class TypicalObject - end - - def test_sending_undefined_messages_to_a_typical_object_results_in_errors - typical = TypicalObject.new - - exception = assert_raise(___) do - typical.foobar - end - assert_match(/foobar/, exception.message) - end - - def test_calling_method_missing_causes_the_no_method_error - typical = TypicalObject.new - - exception = assert_raise(___) do - typical.method_missing(:foobar) - end - assert_match(/foobar/, exception.message) - - # THINK ABOUT IT: - # - # 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 scheduled Ruby - # Koans. - end - - # ------------------------------------------------------------------ - - class AllMessageCatcher - def method_missing(method_name, *args, &block) - "Someone called #{method_name} with <#{args.join(", ")}>" - end - end - - def test_all_messages_are_caught - catcher = AllMessageCatcher.new - - assert_equal __, catcher.foobar - assert_equal __, catcher.foobaz(1) - assert_equal __, catcher.sum(1,2,3,4,5,6) - end - - def test_catching_messages_makes_respond_to_lie - catcher = AllMessageCatcher.new - - assert_nothing_raised(NoMethodError) do - catcher.any_method - end - assert_equal __, catcher.respond_to?(:any_method) - end - - # ------------------------------------------------------------------ - - class WellBehavedFooCatcher - def method_missing(method_name, *args, &block) - if method_name.to_s[0,3] == "foo" - "Foo to you too" - else - super(method_name, *args, &block) - end - end - end - - def test_foo_method_are_caught - catcher = WellBehavedFooCatcher.new - - assert_equal __, catcher.foo_bar - assert_equal __, catcher.foo_baz - end - - def test_non_foo_messages_are_treated_normally - catcher = WellBehavedFooCatcher.new - - assert_raise(___) do - catcher.normal_undefined_method - end - end - - # ------------------------------------------------------------------ - - # (note: just reopening class from above) - class WellBehavedFooCatcher - def respond_to?(method_name) - if method_name.to_s[0,3] == "foo" - true - else - super(method_name) - end - end - end - - def test_explicitly_implementing_respond_to_lets_objects_tell_the_truth - catcher = WellBehavedFooCatcher.new - - assert_equal __, catcher.respond_to?(:foo_bar) - assert_equal __, catcher.respond_to?(:something_else) - end - -end diff --git a/koans/about_methods.rb b/koans/about_methods.rb deleted file mode 100644 index 5fd7725..0000000 --- a/koans/about_methods.rb +++ /dev/null @@ -1,151 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -def my_global_method(a,b) - a + b -end - -class AboutMethods < EdgeCase::Koan - - def test_calling_global_methods - assert_equal __, my_global_method(2,3) - end - - 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_parentheses_are_ambiguous - eval "assert_equal 5, my_global_method 2, 3" # ENABLE CHECK - # - # Ruby doesn't know if you mean: - # - # assert_equal(5, my_global_method(2), 3) - # or - # assert_equal(5, my_global_method(2, 3)) - # - # Rewrite the eval string to continue. - # - end - - # NOTE: wrong number of argument is not a SYNTAX error, but a - # runtime error. - def test_calling_global_methods_with_wrong_number_of_arguments - exception = assert_raise(___) do - my_global_method - end - assert_match(/__/, exception.message) - - exception = assert_raise(___) do - my_global_method(1,2,3) - end - assert_match(/__/, exception.message) - end - - # ------------------------------------------------------------------ - - def method_with_defaults(a, b=:default_value) - [a, b] - end - - def test_calling_with_default_values - assert_equal [1, __], method_with_defaults(1) - assert_equal [1, __], method_with_defaults(1, 2) - end - - # ------------------------------------------------------------------ - - def method_with_var_args(*args) - args - end - - def test_calling_with_variable_arguments - assert_equal __, method_with_var_args.class - assert_equal __, method_with_var_args - assert_equal __, method_with_var_args(:one) - assert_equal __, method_with_var_args(:one, :two) - end - - # ------------------------------------------------------------------ - - def method_with_explicit_return - :a_non_return_value - return :return_value - :another_non_return_value - end - - def test_method_with_explicit_return - assert_equal __, method_with_explicit_return - end - - # ------------------------------------------------------------------ - - def method_without_explicit_return - :a_non_return_value - :return_value - end - - def test_method_without_explicit_return - assert_equal __, method_without_explicit_return - end - - # ------------------------------------------------------------------ - - def my_method_in_the_same_class(a, b) - a * b - end - - def test_calling_methods_in_same_class - assert_equal __, my_method_in_the_same_class(3,4) - end - - def test_calling_methods_in_same_class_with_explicit_receiver - assert_equal __, self.my_method_in_the_same_class(3,4) - end - - # ------------------------------------------------------------------ - - def my_private_method - "a secret" - end - private :my_private_method - - def test_calling_private_methods_without_receiver - assert_equal __, my_private_method - end - - def test_calling_private_methods_with_an_explicit_receiver - exception = assert_raise(___) do - self.my_private_method - end - assert_match /__/, exception.message - end - - # ------------------------------------------------------------------ - - class Dog - def name - "Fido" - end - - private - - def tail - "tail" - end - end - - def test_calling_methods_in_other_objects_require_explicit_receiver - rover = Dog.new - assert_equal __, rover.name - end - - def test_calling_private_methods_in_other_objects - rover = Dog.new - assert_raise(___) do - rover.tail - end - end -end diff --git a/koans/about_modules.rb b/koans/about_modules.rb deleted file mode 100644 index 8b56b65..0000000 --- a/koans/about_modules.rb +++ /dev/null @@ -1,63 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutModules < EdgeCase::Koan - module Nameable - def set_name(new_name) - @name = new_name - end - - def here - :in_module - end - end - - def test_cant_instantiate_modules - assert_raise(___) do - Nameable.new - end - end - - # ------------------------------------------------------------------ - - class Dog - include Nameable - - attr_reader :name - - def initialize - @name = "Fido" - end - - def bark - "WOOF" - end - - def here - :in_object - end - end - - def test_normal_methods_are_available_in_the_object - fido = Dog.new - assert_equal __, fido.bark - end - - def test_module_methods_are_also_available_in_the_object - fido = Dog.new - assert_nothing_raised(Exception) do - fido.set_name("Rover") - end - end - - def test_module_methods_can_affect_instance_variables_in_the_object - fido = Dog.new - assert_equal __, fido.name - fido.set_name("Rover") - assert_equal __, fido.name - end - - def test_classes_can_override_module_methods - fido = Dog.new - assert_equal __, fido.here - end -end diff --git a/koans/about_nil.rb b/koans/about_nil.rb deleted file mode 100644 index 1a74ed0..0000000 --- a/koans/about_nil.rb +++ /dev/null @@ -1,38 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutNil < EdgeCase::Koan - def test_nil_is_an_object - assert_equal __, nil.is_a?(Object), "Unlike NULL in other languages" - end - - def test_you_dont_get_null_pointer_errors_when_calling_methods_on_nil - # What happens when you call a method that doesn't exist. The - # following begin/rescue/end code block captures the exception and - # makes some assertions about it. - begin - nil.some_method_nil_doesnt_know_about - rescue Exception => ex - # What exception has been caught? - assert_equal __, ex.class - - # What message was attached to the exception? - # (HINT: replace __ with part of the error message.) - assert_match(/__/, ex.message) - end - end - - def test_nil_has_a_few_methods_defined_on_it - assert_equal __, nil.nil? - assert_equal __, nil.to_s - assert_equal __, nil.inspect - - # THINK ABOUT IT: - # - # Is it better to use - # obj.nil? - # or - # obj == nil - # Why? - end - -end diff --git a/koans/about_objects.rb b/koans/about_objects.rb deleted file mode 100644 index 05c44de..0000000 --- a/koans/about_objects.rb +++ /dev/null @@ -1,56 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutObjects < EdgeCase::Koan - def test_everything_is_an_object - assert_equal __, 1.is_a?(Object) - assert_equal __, 1.5.is_a?(Object) - assert_equal __, "string".is_a?(Object) - assert_equal __, nil.is_a?(Object) - assert_equal __, Object.is_a?(Object) - end - - def test_objects_can_be_converted_to_strings - assert_equal __, 123.to_s - assert_equal __, nil.to_s - end - - def test_objects_can_be_inspected - assert_equal __, 123.inspect - assert_equal __, nil.inspect - end - - def test_every_object_has_an_id - obj = Object.new - assert_equal __, obj.object_id.class - end - - def test_every_object_has_different_id - obj = Object.new - another_obj = Object.new - assert_equal __, obj.object_id != another_obj.object_id - end - - def test_some_system_objects_always_have_the_same_id - assert_equal __, false.object_id - assert_equal __, true.object_id - assert_equal __, nil.object_id - end - - def test_small_integers_have_fixed_ids - assert_equal __, 0.object_id - assert_equal __, 1.object_id - assert_equal __, 2.object_id - assert_equal __, 100.object_id - - # THINK ABOUT IT: - # What pattern do the object IDs for small integers follow? - end - - def test_clone_creates_a_different_object - obj = Object.new - copy = obj.clone - - assert_equal __, obj != copy - assert_equal __, obj.object_id != copy.object_id - end -end diff --git a/koans/about_open_classes.rb b/koans/about_open_classes.rb deleted file mode 100644 index afef1f9..0000000 --- a/koans/about_open_classes.rb +++ /dev/null @@ -1,45 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutOpenClasses < EdgeCase::Koan - class Dog - def bark - "WOOF" - end - end - - def test_as_defined_dogs_do_bark - fido = Dog.new - assert_equal __, fido.bark - end - - # ------------------------------------------------------------------ - - # Open the existing Dog class and add a new method. - class Dog - def wag - "HAPPY" - end - end - - def test_after_reopening_dogs_can_both_wag_and_bark - fido = Dog.new - assert_equal __, fido.wag - assert_equal __, fido.bark - end - - # ------------------------------------------------------------------ - - class ::Integer - def even? - (self % 2) == 0 - end - end - - def test_even_existing_built_in_classes_can_be_reopened - assert_equal __, 1.even? - assert_equal __, 2.even? - end - - # NOTE: To understand why we need the :: before Integer, you need to - # become enlightened about scope. -end diff --git a/koans/about_proxy_object_project.rb b/koans/about_proxy_object_project.rb deleted file mode 100644 index 064eb68..0000000 --- a/koans/about_proxy_object_project.rb +++ /dev/null @@ -1,156 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -# Project: Create a Proxy Class -# -# In this assignment, create a proxy class (one is started for you -# below). You should be able to initialize the proxy object with any -# object. Any messages sent to the proxy object should be forwarded -# to the target object. As each message is sent, the proxy should -# record the name of the method sent. -# -# The proxy class is started for you. You will need to add a method -# missing handler and any other supporting methods. The specification -# of the Proxy class is given in the AboutProxyObjectProject koan. - -class Proxy - def initialize(target_object) - @object = target_object - # ADD MORE CODE HERE - end - - # WRITE CODE HERE -end - -# The proxy object should pass the following Koan: -# -class AboutProxyObjectProject < EdgeCase::Koan - def test_proxy_method_returns_wrapped_object - # NOTE: The Television class is defined below - tv = Proxy.new(Television.new) - - # HINT: Proxy class is defined above, may need tweaking... - - assert tv.instance_of?(Proxy) - end - - def test_tv_methods_still_perform_their_function - tv = Proxy.new(Television.new) - - tv.channel = 10 - tv.power - - assert_equal 10, tv.channel - assert tv.on? - end - - def test_proxy_records_messages_sent_to_tv - tv = Proxy.new(Television.new) - - tv.power - tv.channel = 10 - - assert_equal [:power, :channel=], tv.messages - end - - def test_proxy_handles_invalid_messages - tv = Proxy.new(Television.new) - - assert_raise(NoMethodError) do - tv.no_such_method - end - end - - def test_proxy_reports_methods_have_been_called - tv = Proxy.new(Television.new) - - tv.power - tv.power - - assert tv.called?(:power) - assert ! tv.called?(:channel) - end - - def test_proxy_counts_method_calls - tv = Proxy.new(Television.new) - - tv.power - tv.channel = 48 - tv.power - - assert_equal 2, tv.number_of_times_called(:power) - assert_equal 1, tv.number_of_times_called(:channel=) - assert_equal 0, tv.number_of_times_called(:on?) - end - - def test_proxy_can_record_more_than_just_tv_objects - proxy = Proxy.new("Code Mash 2009") - - proxy.upcase! - result = proxy.split - - assert_equal ["CODE", "MASH", "2009"], result - assert_equal [:upcase!, :split], proxy.messages - end -end - - -# ==================================================================== -# The following code is to support the testing of the Proxy class. No -# changes should be necessary to anything below this comment. - -# Example class using in the proxy testing above. -class Television - attr_accessor :channel - - def power - if @power == :on - @power = :off - else - @power = :on - end - end - - def on? - @power == :on - end -end - -# Tests for the Television class. All of theses tests should pass. -class TelevisionTest < EdgeCase::Koan - def test_it_turns_on - tv = Television.new - - tv.power - assert tv.on? - end - - def test_it_also_turns_off - tv = Television.new - - tv.power - tv.power - - assert ! tv.on? - end - - def test_edge_case_on_off - tv = Television.new - - tv.power - tv.power - tv.power - - assert tv.on? - - tv.power - - assert ! tv.on? - end - - def test_can_set_the_channel - tv = Television.new - - tv.channel = 11 - assert_equal 11, tv.channel - end -end diff --git a/koans/about_regular_expressions.rb b/koans/about_regular_expressions.rb deleted file mode 100644 index 790bea3..0000000 --- a/koans/about_regular_expressions.rb +++ /dev/null @@ -1,161 +0,0 @@ -# -*- 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 __, /pattern/.class - end - - def test_a_regexp_can_search_a_string_for_matching_content - assert_equal __, "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+/] - # ... a programmer would most likely do - assert_equal __, "variable_1 = 42"[/[^a-zA-Z0-9_]+/] - 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 diff --git a/koans/about_sandwich_code.rb b/koans/about_sandwich_code.rb deleted file mode 100644 index 614a374..0000000 --- a/koans/about_sandwich_code.rb +++ /dev/null @@ -1,106 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutSandwichCode < EdgeCase::Koan - - def count_lines(file_name) - file = open(file_name) - count = 0 - while line = file.gets - count += 1 - end - count - ensure - file.close if file - end - - def test_counting_lines - assert_equal __, count_lines("example_file.txt") - end - - # ------------------------------------------------------------------ - - def find_line(file_name) - file = open(file_name) - while line = file.gets - return line if line.match(/e/) - end - ensure - file.close if file - end - - def test_finding_lines - assert_equal __, find_line("example_file.txt") - end - - # ------------------------------------------------------------------ - # THINK ABOUT IT: - # - # The count_lines and find_line are similar, and yet different. - # They both follow the pattern of "sandwich code". - # - # Sandwich code is code that comes in three parts: (1) the top slice - # of bread, (2) the meat, and (3) the bottom slice of bread. The - # the bread part of the sandwich almost always goes together, but - # the meat part changes all the time. - # - # Because the changing part of the sandwich code is in the middle, - # abstracting the top and bottom bread slices to a library can be - # difficult in many languages. - # - # (Aside for C++ programmers: The idiom of capturing allocated - # pointers in a smart pointer constructor is an attempt to deal with - # the problem of sandwich code for resource allocation.) - # - # Consider the following code: - # - - def file_sandwich(file_name) - file = open(file_name) - yield(file) - ensure - file.close if file - end - - # Now we write: - - def count_lines2(file_name) - file_sandwich(file_name) do |file| - count = 0 - while line = file.gets - count += 1 - end - count - end - end - - def test_counting_lines2 - assert_equal __, count_lines2("example_file.txt") - end - - # ------------------------------------------------------------------ - - def find_line2(file_name) - # Rewrite find_line using the file_sandwich library function. - end - - def test_finding_lines2 - assert_equal __, find_line2("example_file.txt") - end - - # ------------------------------------------------------------------ - - def count_lines3(file_name) - open(file_name) do |file| - count = 0 - while line = file.gets - count += 1 - end - count - end - end - - def test_open_handles_the_file_sandwich_when_given_a_block - assert_equal __, count_lines3("example_file.txt") - end - -end diff --git a/koans/about_scope.rb b/koans/about_scope.rb deleted file mode 100644 index d07d2af..0000000 --- a/koans/about_scope.rb +++ /dev/null @@ -1,79 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutScope < EdgeCase::Koan - module Jims - class Dog - def identify - :jims_dog - end - end - end - - module Joes - class Dog - def identify - :joes_dog - end - end - end - - def test_dog_is_not_available_in_the_current_scope - assert_raise(___) do - fido = Dog.new - end - end - - def test_you_can_reference_nested_classes_using_the_scope_operator - fido = Jims::Dog.new - rover = Joes::Dog.new - assert_equal __, fido.identify - assert_equal __, rover.identify - - assert_equal __, fido.class != rover.class - assert_equal __, Jims::Dog != Joes::Dog - end - - # ------------------------------------------------------------------ - - class String - end - - 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 - - def test_use_the_prefix_scope_operator_to_force_the_global_scope - assert_equal __, ::String == "HI".class - end - - # ------------------------------------------------------------------ - - PI = 3.1416 - - def test_constants_are_defined_with_an_initial_uppercase_letter - assert_equal __, PI - end - - # ------------------------------------------------------------------ - - MyString = ::String - - def test_class_names_are_just_constants - assert_equal __, MyString == ::String - assert_equal __, MyString == "HI".class - end - - def test_constants_can_be_looked_up_explicitly - assert_equal __, PI == AboutScope.const_get("PI") - assert_equal __, MyString == AboutScope.const_get("MyString") - end - - def test_you_can_get_a_list_of_constants_for_any_class_or_module - assert_equal __, Jims.constants - assert Object.constants.size > _n_ - end -end diff --git a/koans/about_scoring_project.rb b/koans/about_scoring_project.rb deleted file mode 100644 index bc61785..0000000 --- a/koans/about_scoring_project.rb +++ /dev/null @@ -1,74 +0,0 @@ -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 to calculate the -# score of a single roll of the dice. -# -# A greed roll is scored as follows: -# -# * A set of three ones is 1000 points -# -# * A set of three numbers (other than ones) is worth 100 times the -# number. (e.g. three fives is 500 points). -# -# * A one (that is not part of a set of three) is worth 100 points. -# -# * A five (that is not part of a set of three) is worth 50 points. -# -# * Everything else is worth 0 points. -# -# -# Examples: -# -# score([1,1,1,5,1]) => 1150 points -# score([2,3,4,6,2]) => 0 points -# score([3,4,5,3,3]) => 350 points -# score([1,5,1,2,4]) => 250 points -# -# More scoring examples are given in the tests below: -# -# Your goal is to write the score method. - -def score(dice) - # You need to write this method -end - -class AboutScoringProject < EdgeCase::Koan - def test_score_of_an_empty_list_is_zero - assert_equal 0, score([]) - end - - def test_score_of_a_single_roll_of_5_is_50 - assert_equal 50, score([5]) - end - - def test_score_of_a_single_roll_of_1_is_100 - assert_equal 100, score([1]) - end - - def test_score_of_multiple_1s_and_5s_is_the_sum_of_individual_scores - assert_equal 300, score([1,5,5,1]) - end - - def test_score_of_single_2s_3s_4s_and_6s_are_zero - assert_equal 0, score([2,3,4,6]) - end - - def test_score_of_a_triple_1_is_1000 - assert_equal 1000, score([1,1,1]) - end - - def test_score_of_other_triples_is_100x - assert_equal 200, score([2,2,2]) - assert_equal 300, score([3,3,3]) - assert_equal 400, score([4,4,4]) - assert_equal 500, score([5,5,5]) - assert_equal 600, score([6,6,6]) - end - - def test_score_of_mixed_is_sum - assert_equal 250, score([2,5,2,2,3]) - assert_equal 550, score([5,5,5,5]) - end - -end diff --git a/koans/about_strings.rb b/koans/about_strings.rb deleted file mode 100644 index 34d4a50..0000000 --- a/koans/about_strings.rb +++ /dev/null @@ -1,195 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/edgecase') - -class AboutStrings < EdgeCase::Koan - def test_double_quoted_strings_are_strings - string = "Hello, World" - assert_equal __, string.is_a?(String) - end - - def test_single_quoted_strings_are_also_strings - string = 'Goodbye, World' - assert_equal __, string.is_a?(String) - end - - def test_use_single_quotes_to_create_string_with_double_quotes - string = 'He said, "Go Away."' - assert_equal __, string - end - - def test_use_double_quotes_to_create_strings_with_single_quotes - string = "Don't" - assert_equal __, string - end - - def test_use_backslash_for_those_hard_cases - a = "He said, \"Don't\"" - b = 'He said, "Don\'t"' - assert_equal __, a == b - end - - def test_use_flexible_quoting_to_handle_really_hard_cases - a = %(flexible quotes can handle both ' and " characters) - b = %!flexible quotes can handle both ' and " characters! - c = %{flexible quotes can handle both ' and " characters} - assert_equal __, a == b - assert_equal __, a == c - end - - def test_flexible_quotes_can_handle_multiple_lines - long_string = %{ -It was the best of times, -It was the worst of times. -} - assert_equal __, long_string.length - assert_equal __, long_string.lines.count - end - - def test_here_documents_can_also_handle_multiple_lines - long_string = < 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 use_colors? - color(color_value) + string + color(COLORS[:clear]) - else - string - end - end - - def color(color_value) - "\e[#{color_value}m" - end - - def use_colors? - return false if ENV['NO_COLOR'] - if ENV['ANSI_COLOR'].nil? - if using_windows? - using_win32console - end - else - ENV['ANSI_COLOR'] =~ /^(t|y)/i - end - end - - def using_windows? - File::ALT_SEPARATOR - end - - def using_win32console - defined? Win32::Console - end - end - - class Sensei - attr_reader :failure, :failed_test, :pass_count - - 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 - @failure = nil - @failed_test = nil - @observations = [] - end - - PROGRESS_FILE_NAME = '.path_progress' - - def add_progress(prog) - @_contents = nil - exists = File.exists?(PROGRESS_FILE_NAME) - File.open(PROGRESS_FILE_NAME,'a+') do |f| - f.print "#{',' if exists}#{prog}" - end - end - - def progress - if @_contents.nil? - if File.exists?(PROGRESS_FILE_NAME) - File.open(PROGRESS_FILE_NAME,'r') do |f| - @_contents = f.read.to_s.gsub(/\s/,'').split(',') - end - else - @_contents = [] - end - end - @_contents - end - - def observe(step) - 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.") - end - else - @failed_test = step - @failure = step.failure - add_progress(@pass_count) - @observations << Color.red("#{step.koan_file}##{step.name} has damaged your karma.") - throw :edgecase_exit - end - end - - def failed? - ! @failure.nil? - end - - def assert_failed? - failure.is_a?(AssertionError) - end - - def instruct - if failed? - @observations.each{|c| puts c } - encourage - guide_through_error - a_zenlike_statement - show_progress - else - end_screen - end - end - - def show_progress - bar_width = 50 - total_tests = EdgeCase::Koan.total_tests - scale = bar_width.to_f/total_tests - print Color.green("your path thus far [") - happy_steps = (pass_count*scale).to_i - happy_steps = 1 if happy_steps == 0 && pass_count > 0 - print Color.green('.'*happy_steps) - if failed? - print Color.red('X') - print Color.cyan('_'*(bar_width-1-happy_steps)) - end - print Color.green(']') - print " #{pass_count}/#{total_tests}" - puts - end - - def end_screen - if EdgeCase.simple_output - boring_end_screen - else - artistic_end_screen - end - end - - def boring_end_screen - puts "Mountains are again merely mountains" - 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 - ,, , ,, - : ::::, :::, - , ,,: :::::::::::::,, :::: : , - , ,,, ,:::::::::::::::::::, ,: ,: ,, - :, ::, , , :, ,::::::::::::::::::, ::: ,:::: - : : ::, ,:::::::: ::, ,:::: - , ,::::: :,:::::::,::::, - ,: , ,:,,: ::::::::::::: - ::,: ,,:::, ,::::::::::::, - ,:::, :,,::: ::::::::::::, - ,::: :::::::, Mountains are again merely mountains ,:::::::::::: - :::,,,:::::: :::::::::::: - ,:::::::::::, ::::::::::::, - :::::::::::, ,:::::::::::: -::::::::::::: ,:::::::::::: -:::::::::::: Ruby Koans ::::::::::::, -::::::::::::#{ ruby_version },::::::::::::, -:::::::::::, , :::::::::::: -,:::::::::::::, brought to you by ,,::::::::::::, -:::::::::::::: ,:::::::::::: - ::::::::::::::, ,::::::::::::: - ::::::::::::, EdgeCase Software Artisans , :::::::::::: - :,::::::::: :::: ::::::::::::: - ,::::::::::: ,: ,,:::::::::::::, - :::::::::::: ,::::::::::::::, - :::::::::::::::::, :::::::::::::::: - :::::::::::::::::::, :::::::::::::::: - ::::::::::::::::::::::, ,::::,:, , ::::,::: - :::::::::::::::::::::::, ::,: ::,::, ,,: :::: - ,:::::::::::::::::::: ::,, , ,, ,:::: - ,:::::::::::::::: ::,, , ,:::, - ,:::: , ,, - ,,, -ENDTEXT - puts completed - end - - def encourage - puts - puts "The Master says:" - puts Color.cyan(" You have not yet reached enlightenment.") - if ((recents = progress.last(5)) && recents.size == 5 && recents.uniq.size == 1) - puts Color.cyan(" I sense frustration. Do not be afraid to ask for help.") - elsif progress.last(2).size == 2 && progress.last(2).uniq.size == 1 - puts Color.cyan(" Do not lose hope.") - elsif progress.last.to_i > 0 - puts Color.cyan(" You are progressing. Excellent. #{progress.last} completed.") - end - end - - def guide_through_error - puts - puts "The answers you seek..." - puts Color.red(indent(failure.message).join) - puts - puts "Please meditate on the following code:" - if assert_failed? - puts embolden_first_line_only(indent(find_interesting_lines(failure.backtrace))) - else - puts embolden_first_line_only(indent(failure.backtrace)) - end - puts - end - - def embolden_first_line_only(text) - first_line = true - text.collect { |t| - if first_line - first_line = false - Color.red(t) - else - Color.cyan(t) - end - } - end - - def indent(text) - text = text.split(/\n/) if text.is_a?(String) - text.collect{|t| " #{t}"} - end - - def find_interesting_lines(backtrace) - backtrace.reject { |line| - line =~ /test\/unit\/|edgecase\.rb|minitest/ - } - end - - # Hat's tip to Ara T. Howard for the zen statements from his - # metakoans Ruby Quiz (http://rubyquiz.com/quiz67.html) - def a_zenlike_statement - if !failed? - zen_statement = "Mountains are again merely mountains" - else - zen_statement = case (@pass_count % 10) - when 0 - "mountains are merely mountains" - when 1, 2 - "learn the rules so you know how to break them properly" - when 3, 4 - "remember that silence is sometimes the best answer" - when 5, 6 - "sleep is the best meditation" - when 7, 8 - "when you lose, don't lose the lesson" - else - "things are not what they appear to be: nor are they otherwise" - end - end - puts Color.green(zen_statement) - end - end - - class Koan - include Test::Unit::Assertions - - attr_reader :name, :failure, :koan_count, :step_count, :koan_file - - def initialize(name, koan_file=nil, koan_count=0, step_count=0) - @name = name - @failure = nil - @koan_count = koan_count - @step_count = step_count - @koan_file = koan_file - end - - def passed? - @failure.nil? - end - - def failed(failure) - @failure = failure - end - - def setup - end - - def teardown - end - - def meditate - setup - begin - send(name) - rescue StandardError, EdgeCase::Sensei::AssertionError => ex - failed(ex) - ensure - begin - teardown - rescue StandardError, EdgeCase::Sensei::AssertionError => ex - failed(ex) if passed? - end - end - self - end - - # Class methods for the EdgeCase test suite. - class << self - def inherited(subclass) - subclasses << subclass - end - - def method_added(name) - testmethods << name if !tests_disabled? && Koan.test_pattern =~ name.to_s - end - - def end_of_enlightenment - @tests_disabled = true - end - - def command_line(args) - args.each do |arg| - case arg - when /^-n\/(.*)\/$/ - @test_pattern = Regexp.new($1) - when /^-n(.*)$/ - @test_pattern = Regexp.new(Regexp.quote($1)) - else - if File.exist?(arg) - load(arg) - else - fail "Unknown command line argument '#{arg}'" - end - end - end - end - - # Lazy initialize list of subclasses - def subclasses - @subclasses ||= [] - end - - # Lazy initialize list of test methods. - def testmethods - @test_methods ||= [] - end - - def tests_disabled? - @tests_disabled ||= false - end - - def test_pattern - @test_pattern ||= /^test_/ - end - - def total_tests - self.subclasses.inject(0){|total, k| total + k.testmethods.size } - end - end - end - - class ThePath - def walk - sensei = EdgeCase::Sensei.new - 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| - 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 - -END { - EdgeCase::Koan.command_line(ARGV) - EdgeCase::ThePath.new.walk -} diff --git a/koans/example_file.txt b/koans/example_file.txt deleted file mode 100644 index ffe7cbd..0000000 --- a/koans/example_file.txt +++ /dev/null @@ -1,4 +0,0 @@ -this -is -a -test diff --git a/koans/first_test.rb b/koans/first_test.rb deleted file mode 100644 index 708baf1..0000000 --- a/koans/first_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'test/unit' - -class TestSomething < Test::Unit::TestCase - def test_assert - assert true - assert_equal 1, 1 - assert_equal 1, 1.0 - end -end - - diff --git a/koans/path_to_enlightenment.rb b/koans/path_to_enlightenment.rb deleted file mode 100644 index 64621bf..0000000 --- a/koans/path_to_enlightenment.rb +++ /dev/null @@ -1,38 +0,0 @@ -# The path to Ruby Enlightenment starts with the following: - -$LOAD_PATH << File.dirname(__FILE__) - -require 'about_asserts' -require 'about_nil' -require 'about_objects' -require 'about_arrays' -require 'about_array_assignment' -require 'about_hashes' -require 'about_strings' -require 'about_symbols' -require 'about_regular_expressions' -require 'about_methods' -require 'about_constants' -require 'about_control_statements' -require 'about_true_and_false' -require 'about_triangle_project' -require 'about_exceptions' -require 'about_triangle_project_2' -require 'about_iteration' -require 'about_blocks' -require 'about_sandwich_code' -require 'about_scoring_project' -require 'about_classes' -require 'about_open_classes' -require 'about_dice_project' -require 'about_inheritance' -require 'about_modules' -require 'about_scope' -require 'about_class_methods' -require 'about_message_passing' -require 'about_proxy_object_project' -require 'about_to_str' -in_ruby_version("jruby") do - require 'about_java_interop' -end -require 'about_extra_credit' diff --git a/koans/test_helper.rb b/koans/test_helper.rb deleted file mode 100644 index 9accf96..0000000 --- a/koans/test_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'test/unit' - -def __ - "FILL ME IN" -end - -EdgeCase = Test::Unit diff --git a/koans/triangle.rb b/koans/triangle.rb deleted file mode 100644 index 8df052a..0000000 --- a/koans/triangle.rb +++ /dev/null @@ -1,22 +0,0 @@ -# Triangle Project Code. - -# Triangle analyzes the lengths of the sides of a triangle -# (represented by a, b and c) and returns the type of triangle. -# -# It returns: -# :equilateral if all sides are equal -# :isosceles if exactly 2 sides are equal -# :scalene if no sides are equal -# -# The tests for this method can be found in -# about_triangle_project.rb -# and -# about_triangle_project_2.rb -# -def triangle(a, b, c) - # WRITE THIS CODE -end - -# Error class used in part 2. No need to change this code. -class TriangleError < StandardError -end