Last active
February 10, 2021 18:07
-
-
Save josh-works/6eb437670b66a67675c23352c787e66d to your computer and use it in GitHub Desktop.
test, and the code that makes the test pass, to understand whole values and exceptional values, from Avdi Grim's https://avdi.codes/courses/moom/, based on https://josh.works/primative-obsession-and-exceptional-values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Object | |
def exceptional? | |
false | |
end | |
end | |
Course = Struct.new(:name, :duration) do | |
def duration=(new_duration) | |
self[:duration] = Duration(new_duration) | |
end | |
end | |
class Duration | |
def self.[](magnitude) | |
new(magnitude) | |
end | |
attr_reader :magnitude | |
def initialize(magnitude) | |
@magnitude = magnitude | |
freeze | |
end | |
def to_s | |
"#{self.magnitude} #{self.class.name.downcase}" | |
end | |
def inspect | |
"#{self.class}[#{self.magnitude}]" | |
end | |
alias_method :to_i, :magnitude | |
end | |
class Days < Duration; end | |
class Weeks < Duration; end | |
class Months < Duration; end | |
class ExceptionalValue | |
attr_reader :raw_value, :reason | |
def initialize(raw_value, reason: "Unspecified") | |
@raw_value = raw_value | |
@reason = reason | |
end | |
def exceptional? | |
true | |
end | |
def to_s | |
@raw_value.to_s | |
end | |
end | |
# helper methods | |
def render_course_info(course) | |
"#{course.name} (#{render_value(course.duration)})" | |
end | |
def render_value(value) | |
case value | |
when Months | |
"#{value.to_i} gruling months" | |
when Weeks | |
"#{value.to_i} delightful weeks" | |
when Days | |
"a paultry #{value.to_i} days" | |
end | |
end | |
# in the video, this method was capitalized, I don't know why but I imagine | |
# it was for a good reason | |
def Duration(raw_value) | |
case raw_value | |
when Duration | |
raw_value | |
when /\A(\d+)\s+months\z/i | |
Months[$1.to_i] | |
when /\A(\d+)\s+weeks\z/i | |
Weeks[$1.to_i] | |
when /\A(\d+)\s+days\z/i | |
Days[$1.to_i] | |
else | |
ExceptionalValue.new(raw_value, reason: "unrecognized format") | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative './exceptional_values' | |
gem 'minitest' | |
require 'minitest/autorun' | |
class DurationTest < MiniTest::Test | |
def setup | |
@math = Course.new("Math", Months[4]) | |
@grammar = Course.new("Grammar", Days[50]) | |
@skrying = Course.new("Skrying", Weeks[7]) | |
end | |
def test_create_new_duration | |
assert @math | |
assert_equal "Math", @math.name | |
end | |
def test_duration_has_magnitude | |
assert_equal 4, @math.duration.magnitude | |
end | |
def test_duration_is_months_object | |
assert_instance_of Months, @math.duration | |
end | |
def test_duration_formatting_is_not_string | |
refute_equal String, @math.duration.class | |
end | |
def test_duration_to_i_is_aliased_to_magnitude | |
assert_equal 4, @math.duration.to_i | |
end | |
def test_duration_to_string | |
assert_equal "4 months", @math.duration.to_s | |
end | |
def test_duration_inspect | |
assert_equal "Months[4]", @math.duration.inspect | |
end | |
def test_duration_can_change | |
@math.duration = Weeks[3] | |
assert_instance_of Weeks, @math.duration | |
end | |
def test_duration_can_be_denominated_in_days | |
assert_instance_of Days, @grammar.duration | |
assert_equal 50, @grammar.duration.magnitude | |
end | |
def test_duration_can_be_denominated_in_weeks | |
assert_instance_of Weeks, @skrying.duration | |
assert_equal 7, @skrying.duration.magnitude | |
end | |
def test_duration_can_be_denominated_in_months | |
potions = Course.new("Potions", Months[3]) | |
assert_instance_of Months, potions.duration | |
assert_equal 3, potions.duration.magnitude | |
end | |
# test helper methods | |
def test_render_months_class | |
results = render_value(@math.duration) | |
assert_equal "4 gruling months", results | |
end | |
def test_render_weeks_class | |
results = render_value(@skrying.duration) | |
assert_equal "7 delightful weeks", results | |
end | |
def test_render_days_class | |
results = render_value(@grammar.duration) | |
assert_equal "a paultry 50 days", results | |
end | |
def test_render_course_info_returns_nicely_formatted_strings | |
assert_equal "Math (4 gruling months)", render_course_info(@math) | |
assert_equal "Grammar (a paultry 50 days)", render_course_info(@grammar) | |
assert_equal "Skrying (7 delightful weeks)", render_course_info(@skrying) | |
end | |
def test_freeze_magnitude_in_initialize | |
skip | |
# not sure what I can assert to make sure value is frozen | |
# https://blog.honeybadger.io/when-to-use-freeze-and-frozen-in-ruby/ | |
end | |
# testing exceptional values | |
def test_Duration_converts_months_string_to_duration_object | |
math = Course.new("Math") | |
math.duration = "4 months" | |
assert_equal Months, math.duration.class | |
assert_equal 4, math.duration.magnitude | |
end | |
def test_Duration_convert_weeks_string_to_duration_object | |
math = Course.new("Math") | |
math.duration = "7 days" | |
assert_equal Days, math.duration.class | |
assert_equal 7, math.duration.magnitude | |
end | |
def test_convert_weeks_string_to_duration | |
math = Course.new("Math") | |
math.duration = "3 weeks" | |
assert_instance_of Weeks, math.duration | |
assert_equal 3, math.duration.magnitude | |
end | |
def test_exceptional_values | |
math = Course.new("Math") | |
math.duration = "a blink of an eye" | |
assert_instance_of ExceptionalValue, math.duration | |
assert_equal "a blink of an eye", math.duration.to_s | |
end | |
def test_exceptional_values_know_they_are_exceptional | |
math = Course.new("Math") | |
math.duration = "a blink of an eye" | |
assert math.duration.exceptional? | |
refute math.name.exceptional? | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment