Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate canonical data methods from ExerciseCase #648

Merged
merged 10 commits into from
May 31, 2017
2 changes: 1 addition & 1 deletion exercises/anagram/.meta/generator/anagram_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def indent_lines(code, indent = 2)
end

def show_comment
"# #{comment}" unless comment.nil?
"# #{comment}" if respond_to?(:comment)
end

def detector
Expand Down
2 changes: 1 addition & 1 deletion exercises/beer-song/.meta/generator/beer_song_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def beer_song_arguments
if property == 'verse'
number
else
"%s, %s" % [self["beginning"], self["end"]]
"%s, %s" % [self.beginning, self.end]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... beginning and ending would be a match here, and would avoid the 'stroop effect' caused by the standard use of begin and end in Ruby.

Something to consider. Not a required change for bringing this in though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These names come from the canonical data so we're constrained by what it provides.

end
end
end
2 changes: 1 addition & 1 deletion exercises/clock/.meta/generator/clock_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def simple_test
end

def add_to_clock
" + #{add}" if add
" + #{add}" if respond_to?(:add)
end

end
3 changes: 0 additions & 3 deletions exercises/connect/.meta/generator/connect_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,4 @@ def single_quote(string)
string.inspect.tr('"', "'")
end

def ignore_method_length
"# rubocop:disable MethodLength\n " if board.length > 8
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay! This is gone!

end
2 changes: 1 addition & 1 deletion exercises/connect/.meta/generator/test_template.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require_relative 'connect'
# Common test data version: <%= canonical_data_version %> <%= abbreviated_commit_hash %>
class ConnectTest < Minitest::Test
<% test_cases.each_with_index do |test_case, idx| %>
<%= test_case.ignore_method_length%>def <%= test_case.name %>
def <%= test_case.name %>
<%= test_case.skipped(idx) %><% test_case.test_body.each do |line| %>
<%= line %><% end %>
end
Expand Down
2 changes: 1 addition & 1 deletion exercises/wordy/.meta/generator/wordy_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def indent(size, lines)
end

def assertion
return error_assertion unless expected
return error_assertion if expected == false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return error_assertion unless expected

Or

return error_assertion if expected.false?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do the other cases address the assertions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is false? defined?

Neither of these will work.

expected comes from the canonical data and is either not present or an integer or false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That answers that then. 👍 Thanks.

return message_assertion if message

"assert_equal(#{expected}, WordProblem.new(question).answer)"
Expand Down
2 changes: 1 addition & 1 deletion lib/generator/case_values.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def initialize(case_class:)

def cases(exercise_data)
extract_test_cases(data: JSON.parse(exercise_data)['cases'])
.map { |test| @case_class.new(test) }
.map { |case_properties| @case_class.new(canonical: OpenStruct.new(case_properties)) }
end

private
Expand Down
18 changes: 16 additions & 2 deletions lib/generator/exercise_case.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
require 'ostruct'

module Generator
class ExerciseCase < OpenStruct
class ExerciseCase
using Generator::Underscore
include CaseHelpers
include Assertion

attr_reader :canonical
def initialize(canonical:)
@canonical = canonical
end

def name
'test_%s' % description.underscore
'test_%s' % canonical.description.underscore
end

def skipped(index)
index.zero? ? '# skip' : 'skip'
end

def method_missing(sym, *args, &block)
return canonical.send(sym) if canonical.respond_to?(sym)
super(sym, *args, &block)
end

def respond_to?(sym, include_private = false)
canonical.respond_to?(sym) || super
end
end
end
8 changes: 4 additions & 4 deletions lib/generator/exercise_case/assertion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module Assertion
# "#{assert} Luhn.valid?(#{input.inspect})"
#
def assert
expected ? 'assert' : 'refute'
canonical.expected ? 'assert' : 'refute'
end

# generates assertions of the form
Expand All @@ -29,8 +29,8 @@ def assert
# assert_equal { "PigLatin.translate(#{input.inspect})" }
#
def assert_equal
assertion = expected.nil? ? 'assert_nil' :
"assert_equal #{expected.inspect},"
assertion = canonical.expected.nil? ? 'assert_nil' :
"assert_equal #{canonical.expected.inspect},"
"#{assertion} #{yield}"
end

Expand All @@ -43,7 +43,7 @@ def assert_equal
# end
#
def raises_error?
expected.to_i == -1
canonical.expected.to_i == -1
end

# generates assertions of the form
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class AlphaCase < Generator::ExerciseCase
def name
format('test_%s', description.downcase.gsub(/[ -]/, '_'))
format('test_%s', canonical.description.downcase.gsub(/[ -]/, '_'))
end

def workload
Expand Down
35 changes: 28 additions & 7 deletions test/generator/case_values_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,35 @@ def test_multi_level_auto_extraction
).cases(canonical_data)

expected = [
ComplexCase.new(description: 'first generic verse', property: 'verse', number: 99,
expected: '99 bottles of beer on the wall, YAAAR'),
ComplexCase.new(description: 'last generic verse', property: 'verse', number: 3,
expected: '3 bottles of beer on the wall, YAAAR'),
ComplexCase.new(description: 'first two verses', property: 'verses', beginning: 99, end: 98,
expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT")
ComplexCase.new(
canonical: {
'description' => 'first generic verse',
'property' => 'verse',
'number' => 99,
'expected' => '99 bottles of beer on the wall, YAAAR'
}
),
ComplexCase.new(
canonical: {
'description' => 'last generic verse',
'property' => 'verse',
'number' => 3,
'expected' => '3 bottles of beer on the wall, YAAAR'
}
),
ComplexCase.new(
canonical: {
'description' => 'first two verses',
'property' => 'verses',
'beginning' => 99,
'end' => 98,
'expected' => "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT"
}
)
]
assert_equal expected, cases
assert expected.zip(cases).all? do |exp, cs|
assert_equal exp.canonical, cs.canonical
end
end
end
end
Expand Down
14 changes: 7 additions & 7 deletions test/generator/exercise_case/assertion_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,43 @@ module Generator
class ExerciseCase
class AssertionTest < Minitest::Test
def test_assert
test_case = OpenStruct.new(expected: true)
test_case = ExerciseCase.new(canonical: OpenStruct.new({'expected' => true}))
test_case.extend(Assertion)
assert_equal 'assert', test_case.assert
end

def test_refute
test_case = OpenStruct.new(expected: false)
test_case = ExerciseCase.new(canonical: OpenStruct.new({'expected' => false}))
test_case.extend(Assertion)
assert_equal 'refute', test_case.assert
end

def test_assert_equal
test_case = OpenStruct.new(expected: 2)
test_case = ExerciseCase.new(canonical: OpenStruct.new({'expected' => 2}))
test_case.extend(Assertion)
assert_equal "assert_equal 2, 4", test_case.assert_equal { 1 + 3 }
end

def test_assert_equal_when_nil
test_case = OpenStruct.new(expected: nil)
test_case = ExerciseCase.new(canonical: OpenStruct.new({'expected' => nil}))
test_case.extend(Assertion)
assert_equal "assert_nil 4", test_case.assert_equal { 1 + 3 }
end

def test_raises_error
test_case = OpenStruct.new(expected: -1)
test_case = ExerciseCase.new(canonical: OpenStruct.new({'expected' => -1}))
test_case.extend(Assertion)
assert test_case.raises_error?
end

def test_does_not_raise_error
test_case = OpenStruct.new(expected: 'cute kitties')
test_case = ExerciseCase.new(canonical: OpenStruct.new({'expected' => 'cute kitties'}))
test_case.extend(Assertion)
refute test_case.raises_error?
end

def test_assert_raises
test_case = OpenStruct.new
test_case = ExerciseCase.new(canonical: OpenStruct.new({}))
test_case.extend(Assertion)
assert_equal(
"assert_raises(ArgumentError) { 4 }",
Expand Down
46 changes: 21 additions & 25 deletions test/generator/exercise_case_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,41 @@
module Generator
class ExerciseCaseTest < Minitest::Test
def test_name
assert_equal 'test_foo', ExerciseCase.new(description: 'foo').name
subject = ExerciseCase.new(canonical: OpenStruct.new(description: 'foo'))
assert_equal 'test_foo', subject.name
end

def test_skipped_index_zero
assert_equal '# skip', ExerciseCase.new.skipped(0)
assert_equal '# skip', ExerciseCase.new(canonical: nil).skipped(0)
end

def test_skipped_index_nonzero
assert_equal 'skip', ExerciseCase.new.skipped(1)
assert_equal 'skip', ExerciseCase.new(canonical: nil).skipped(1)
end

class MultiLineCase < ExerciseCase
def workload
indent_lines(['foo', 'bar'], 1)
end
end
def test_indent_multiline_workloads
expected = "foo\n bar"
assert_equal expected, MultiLineCase.new.workload
def test_forwarding_to_canonical
mock_canonical = Minitest::Mock.new
mock_canonical.expect :key, 'fake value'
subject = ExerciseCase.new(canonical: mock_canonical)
subject.key
mock_canonical.verify
end

class BlankLineCase < ExerciseCase
def workload
indent_text(2, "foo\n\nbar\n")
def test_method_mising_calls_super
subject = ExerciseCase.new(canonical: nil)
assert_raises NoMethodError do
subject.key
end
end
def test_indent_multiline_workloads_with_blank_lines
expected = "foo\n\n bar\n"
assert_equal expected, BlankLineCase.new.workload
end

class HeredocCase < ExerciseCase
def workload
indent_heredoc(["foo", "bar"], 'TEXT', 1)
end
def test_true_respond_to?
subject = ExerciseCase.new(canonical: OpenStruct.new(key: 'value'))
assert subject.respond_to?(:key)
end
def test_heredoc
expected = "<<-TEXT\n foo\n bar\nTEXT"
assert_equal expected, HeredocCase.new.workload

def test_false_respond_to?
subject = ExerciseCase.new(canonical: OpenStruct.new())
refute subject.respond_to?(:key)
end
end
end
8 changes: 4 additions & 4 deletions test/wordy_cases_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class WordyCaseTest < Minitest::Test
def test_workload_with_expected_and_no_message
test_case = WordyCase.new(expected: 1, input: 1)
test_case = WordyCase.new(canonical: OpenStruct.new(expected: 1, input: 1))

expected_workload = [
'question = \'1\'',
Expand All @@ -15,7 +15,7 @@ def test_workload_with_expected_and_no_message
end

def test_workload_with_expected_and_message
test_case = WordyCase.new(expected: 1, input: 'What is -3 plus 7 multiplied by -2?')
test_case = WordyCase.new(canonical: OpenStruct.new(expected: 1, input: 'What is -3 plus 7 multiplied by -2?'))
message = test_case.send(:message)

expected_workload = [
Expand All @@ -28,8 +28,8 @@ def test_workload_with_expected_and_message
assert_equal expected_workload, test_case.workload
end

def test_workload_without_expected
test_case = WordyCase.new(input: 1)
def test_workload_with_expected_false
test_case = WordyCase.new(canonical: OpenStruct.new(input: 1, expected: false))

expected_workload = [
'question = \'1\'',
Expand Down