From e30946e48968b13b42e3117663f0c2f0fbf191a0 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 16:37:24 -0700 Subject: [PATCH 01/61] add class_name to GeneratorCases --- lib/generator/files/track_files.rb | 6 +++++- test/generator/files/track_files_test.rb | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/generator/files/track_files.rb b/lib/generator/files/track_files.rb index d54430180c..2ae19d81fe 100644 --- a/lib/generator/files/track_files.rb +++ b/lib/generator/files/track_files.rb @@ -14,8 +14,12 @@ def filename(exercise_name) "#{exercise_name.tr('-', '_')}_cases" end + def class_name(exercise_name) + filename(exercise_name)[0..-2].split('_').map(&:capitalize).join + end + def proc_name(exercise_name) - filename(exercise_name).split('_').map(&:capitalize).join + "#{class_name(exercise_name)}s" end def exercise_name(filename) diff --git a/test/generator/files/track_files_test.rb b/test/generator/files/track_files_test.rb index 39311b765e..8b30a70420 100644 --- a/test/generator/files/track_files_test.rb +++ b/test/generator/files/track_files_test.rb @@ -25,6 +25,10 @@ def test_filename assert_equal 'two_parter_cases', GeneratorCases.filename(exercise_name) end + def test_class_name + assert_equal 'TwoParterCase', GeneratorCases.class_name('two-parter') + end + def test_proc_name exercise_name = 'two-parter' assert_equal 'TwoParterCases', GeneratorCases.proc_name(exercise_name) From 77cac072539b22aeb23d94d27ced1d459451a88b Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 16:59:21 -0700 Subject: [PATCH 02/61] programmatically generate cases --- lib/generator/template_values.rb | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index a1aac124f5..e01f833592 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -21,7 +21,7 @@ def template_values TemplateValues.new( abbreviated_commit_hash: canonical_data.abbreviated_commit_hash, version: version, - test_cases: test_cases_proc.call(canonical_data.to_s) + test_cases: test_cases ) end @@ -31,8 +31,40 @@ def cases_require_name Files::GeneratorCases.filename(exercise_name) end + def test_cases + if test_cases_proc? + test_cases_proc.call(canonical_data.to_s) + else + test_cases_with_index + end + end + + def test_cases_with_index + extract_test_cases.compact. + map.with_index {|test, index| test_case_class.new(test.merge('index' => index)) } + end + + def extract_test_cases(data = JSON.parse(canonical_data.to_s)['cases']) + data.flat_map do |entry| + entry.key?('cases') ? extract_test_cases(entry['cases']) : entry + end + end + + def test_cases_proc? + Object.const_defined?(test_cases_procname) + end + def test_cases_proc - Object.const_get(Files::GeneratorCases.proc_name(exercise_name)) + Object.const_get(test_cases_procname) + end + + def test_case_class + Object.const_get(Files::GeneratorCases.class_name(exercise_name)) end + + def test_cases_procname + @test_cases_procname ||= Files::GeneratorCases.proc_name(exercise_name) + end + end end From 6134c4804cb1e40bc00c5eebb86a6c78f4dfa2e5 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Mon, 24 Apr 2017 15:17:45 -0700 Subject: [PATCH 03/61] extract CaseValues from TemplateValuesFactory --- lib/generator/files/track_files.rb | 3 +- lib/generator/template_values.rb | 57 +++++++----- test/fixtures/xruby/lib/gamma_cases.rb | 7 ++ test/generator/files/track_files_test.rb | 2 +- test/generator/template_values_test.rb | 111 +++++++++++++++++++++++ 5 files changed, 153 insertions(+), 27 deletions(-) create mode 100644 test/fixtures/xruby/lib/gamma_cases.rb diff --git a/lib/generator/files/track_files.rb b/lib/generator/files/track_files.rb index 2ae19d81fe..8f02def91a 100644 --- a/lib/generator/files/track_files.rb +++ b/lib/generator/files/track_files.rb @@ -18,8 +18,9 @@ def class_name(exercise_name) filename(exercise_name)[0..-2].split('_').map(&:capitalize).join end + # TODO: for backwards compatibility, remove post-conversion def proc_name(exercise_name) - "#{class_name(exercise_name)}s" + class_name(exercise_name) + 's' end def exercise_name(filename) diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index e01f833592..cbf64a934b 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -16,55 +16,62 @@ def get_binding module TemplateValuesFactory def template_values - require cases_require_name - TemplateValues.new( abbreviated_commit_hash: canonical_data.abbreviated_commit_hash, version: version, - test_cases: test_cases + test_cases: CaseValues.extract(exercise_name: exercise_name, exercise_data: canonical_data.to_s) ) end + end - private - - def cases_require_name - Files::GeneratorCases.filename(exercise_name) + class CaseValues + def self.extract(exercise_name:, exercise_data:) + CaseValues.new(exercise_name: exercise_name, exercise_data: exercise_data).extract end - def test_cases - if test_cases_proc? - test_cases_proc.call(canonical_data.to_s) - else - test_cases_with_index - end + def initialize(exercise_name:, exercise_data:) + @exercise_name = exercise_name + @exercise_data = exercise_data + + require cases_require_name end - def test_cases_with_index - extract_test_cases.compact. + attr_reader :exercise_name, :exercise_data + + def extract + # TODO: for backwards compatibility, remove post-conversion + return test_cases_proc.call(exercise_data) if test_cases_proc + + extract_test_cases. map.with_index {|test, index| test_case_class.new(test.merge('index' => index)) } end - def extract_test_cases(data = JSON.parse(canonical_data.to_s)['cases']) - data.flat_map do |entry| - entry.key?('cases') ? extract_test_cases(entry['cases']) : entry + private + + # TODO: for backwards compatibility, remove post-conversion + def test_cases_proc + if Object.const_defined?(test_cases_procname) + Object.const_get(test_cases_procname) end end - def test_cases_proc? - Object.const_defined?(test_cases_procname) + # TODO: for backwards compatibility, remove post-conversion + def test_cases_procname + @test_cases_procname ||= Files::GeneratorCases.proc_name(exercise_name) end - def test_cases_proc - Object.const_get(test_cases_procname) + def extract_test_cases(data: JSON.parse(exercise_data)['cases']) + data.flat_map do |entry| + entry.key?('cases') ? extract_test_cases(data: entry['cases']) : entry + end end def test_case_class Object.const_get(Files::GeneratorCases.class_name(exercise_name)) end - def test_cases_procname - @test_cases_procname ||= Files::GeneratorCases.proc_name(exercise_name) + def cases_require_name + Files::GeneratorCases.filename(exercise_name) end - end end diff --git a/test/fixtures/xruby/lib/gamma_cases.rb b/test/fixtures/xruby/lib/gamma_cases.rb new file mode 100644 index 0000000000..40cc9b7884 --- /dev/null +++ b/test/fixtures/xruby/lib/gamma_cases.rb @@ -0,0 +1,7 @@ +class GammaCase < ExerciseCase + + def workload + assert { Gamma.foo(bar) } + end + +end diff --git a/test/generator/files/track_files_test.rb b/test/generator/files/track_files_test.rb index 8b30a70420..05e24a714c 100644 --- a/test/generator/files/track_files_test.rb +++ b/test/generator/files/track_files_test.rb @@ -10,7 +10,7 @@ def test_no_cases_found def test_cases_found track_path = 'test/fixtures/xruby' - assert_equal %w(alpha beta), GeneratorCases.available(track_path).sort + assert_equal %w(alpha beta gamma), GeneratorCases.available(track_path).sort end def test_available_returns_exercise_names diff --git a/test/generator/template_values_test.rb b/test/generator/template_values_test.rb index 75abf8abf9..ae76e465d9 100644 --- a/test/generator/template_values_test.rb +++ b/test/generator/template_values_test.rb @@ -56,4 +56,115 @@ def teardown $LOAD_PATH.delete 'test/fixtures/xruby/lib' end end + + class CaseValuesTest < Minitest::Test + def setup + $LOAD_PATH.unshift 'test/fixtures/xruby/lib' + end + + def simple_canonical_data + simple_canonical_data = Minitest::Mock.new + simple_canonical_data.expect( + :to_s, + <<-TEXT +{ + "description": "Test canonical data", + "cases": [ + { + "description": "add 2 numbers", + "input": [1,1], + "expected": 2 + } + ] +} +TEXT + ) + simple_canonical_data + end + + def complex_canonical_data + complex_canonical_data = Minitest::Mock.new + complex_canonical_data.expect( + :to_s, + <<-TEXT +{ + "exercise": "beer-song", + "version": "1.0.0", + "cases": [ + { + "description": "verse", + "cases": [ + { + "description": "single verse", + "cases": [ + { + "description": "first generic verse", + "property": "verse", + "number": 99, + "expected": "99 bottles of beer on the wall, YAAAR" + }, + { + "description": "last generic verse", + "property": "verse", + "number": 3, + "expected": "3 bottles of beer on the wall, YAAAR" + } + ] + } + ] + }, + { + "description": "lyrics", + "cases": [ + { + "description": "multiple verses", + "cases": [ + { + "description": "first two verses", + "property": "verses", + "beginning": 99, + "end": 98, + "expected": "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT" + } + ] + } + ] + } + ] +} +TEXT + ) + complex_canonical_data + end + + def test_extract_via_proc + cases = CaseValues.extract(exercise_name: 'alpha', exercise_data: simple_canonical_data.to_s) + expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def test_simple_auto_extraction + cases = CaseValues.extract(exercise_name: 'gamma', exercise_data: simple_canonical_data.to_s) + expected = [GammaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def test_multi_level_auto_extraction + cases = CaseValues.extract(exercise_name: 'gamma', exercise_data: complex_canonical_data.to_s) + expected = [ + GammaCase.new(description: 'first generic verse', property: 'verse', number: 99, + expected: '99 bottles of beer on the wall, YAAAR', index: 0), + GammaCase.new(description: 'last generic verse', property: 'verse', number: 3, + expected: '3 bottles of beer on the wall, YAAAR', index: 1), + GammaCase.new(description: 'first two verses', property: 'verses', beginning: 99, end: 98, + expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT", index: 2), + + ] + assert_equal expected.to_s, cases.to_s + end + + def teardown + $LOAD_PATH.delete 'test/fixtures/xruby/lib' + end + end end From 982e9b313c25d10a8c90b76dd7d4ef220da9418b Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 13:22:35 -0700 Subject: [PATCH 04/61] separate logic for proc and auto extraction --- lib/generator/case_values.rb | 88 +++++++++++++ lib/generator/template_values.rb | 54 +------- .../case_values_auto_extractor_test.rb | 116 ++++++++++++++++++ test/generator/case_values_extract_test.rb | 65 ++++++++++ .../case_values_proc_extractor_test.rb | 46 +++++++ test/generator/template_values_test.rb | 110 ----------------- 6 files changed, 318 insertions(+), 161 deletions(-) create mode 100644 lib/generator/case_values.rb create mode 100644 test/generator/case_values_auto_extractor_test.rb create mode 100644 test/generator/case_values_extract_test.rb create mode 100644 test/generator/case_values_proc_extractor_test.rb diff --git a/lib/generator/case_values.rb b/lib/generator/case_values.rb new file mode 100644 index 0000000000..4a47bdc139 --- /dev/null +++ b/lib/generator/case_values.rb @@ -0,0 +1,88 @@ +module Generator + module CaseValues + + module Extract + + def extract + extractor.extract( + exercise_name: exercise_name, + exercise_data: canonical_data.to_s + ) + end + + private + + def extractor + Object.const_defined?(test_cases_procname) ? ProcExtractor : AutoExtractor + end + + def test_cases_procname + Files::GeneratorCases.proc_name(exercise_name) + end + end + + class Extractor + attr_reader :exercise_name, :exercise_data + + def self.extract(exercise_name:, exercise_data:) + self.new( + exercise_name: exercise_name, + exercise_data: exercise_data + ).extract + end + + def initialize(exercise_name:, exercise_data:) + @exercise_name = exercise_name + @exercise_data = exercise_data + + require cases_require_name + end + + def extract + fail NotImplementedError, 'Should return an array of ProblemNameCase' + end + + private + + def cases_require_name + Files::GeneratorCases.filename(exercise_name) + end + end + + class AutoExtractor < Extractor + + def extract + extract_test_cases.map.with_index do |test, index| + test_case_class.new(test.merge('index' => index)) + end + end + + private + + def extract_test_cases(data: JSON.parse(exercise_data)['cases']) + data.flat_map do |entry| + entry.key?('cases') ? extract_test_cases(data: entry['cases']) : entry + end + end + + def test_case_class + Object.const_get(Files::GeneratorCases.class_name(exercise_name)) + end + end + + class ProcExtractor < Extractor + + def extract + test_cases_proc.call(exercise_data) + end + + private + + def test_cases_proc + Object.const_get(Files::GeneratorCases.proc_name(exercise_name)) + end + + end + + end +end diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index cbf64a934b..ccfa152f36 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -15,63 +15,15 @@ def get_binding end module TemplateValuesFactory + include CaseValues::Extract + def template_values TemplateValues.new( abbreviated_commit_hash: canonical_data.abbreviated_commit_hash, version: version, - test_cases: CaseValues.extract(exercise_name: exercise_name, exercise_data: canonical_data.to_s) + test_cases: extract ) end end - class CaseValues - def self.extract(exercise_name:, exercise_data:) - CaseValues.new(exercise_name: exercise_name, exercise_data: exercise_data).extract - end - - def initialize(exercise_name:, exercise_data:) - @exercise_name = exercise_name - @exercise_data = exercise_data - - require cases_require_name - end - - attr_reader :exercise_name, :exercise_data - - def extract - # TODO: for backwards compatibility, remove post-conversion - return test_cases_proc.call(exercise_data) if test_cases_proc - - extract_test_cases. - map.with_index {|test, index| test_case_class.new(test.merge('index' => index)) } - end - - private - - # TODO: for backwards compatibility, remove post-conversion - def test_cases_proc - if Object.const_defined?(test_cases_procname) - Object.const_get(test_cases_procname) - end - end - - # TODO: for backwards compatibility, remove post-conversion - def test_cases_procname - @test_cases_procname ||= Files::GeneratorCases.proc_name(exercise_name) - end - - def extract_test_cases(data: JSON.parse(exercise_data)['cases']) - data.flat_map do |entry| - entry.key?('cases') ? extract_test_cases(data: entry['cases']) : entry - end - end - - def test_case_class - Object.const_get(Files::GeneratorCases.class_name(exercise_name)) - end - - def cases_require_name - Files::GeneratorCases.filename(exercise_name) - end - end end diff --git a/test/generator/case_values_auto_extractor_test.rb b/test/generator/case_values_auto_extractor_test.rb new file mode 100644 index 0000000000..cdf77f8191 --- /dev/null +++ b/test/generator/case_values_auto_extractor_test.rb @@ -0,0 +1,116 @@ +require_relative '../test_helper' + +module Generator + module CaseValues + class AutoExtractorTest < Minitest::Test + + def setup + $LOAD_PATH.unshift 'test/fixtures/xruby/lib' + end + + def test_simple_auto_extraction + cases = AutoExtractor.new( + exercise_name: 'gamma', exercise_data: simple_canonical_data.to_s + ).extract + expected = [GammaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def test_multi_level_auto_extraction + cases = AutoExtractor.new( + exercise_name: 'gamma', exercise_data: complex_canonical_data.to_s + ).extract + + expected = [ + GammaCase.new(description: 'first generic verse', property: 'verse', number: 99, + expected: '99 bottles of beer on the wall, YAAAR', index: 0), + GammaCase.new(description: 'last generic verse', property: 'verse', number: 3, + expected: '3 bottles of beer on the wall, YAAAR', index: 1), + GammaCase.new(description: 'first two verses', property: 'verses', beginning: 99, end: 98, + expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT", index: 2), + + ] + assert_equal expected.to_s, cases.to_s + end + + def teardown + $LOAD_PATH.delete 'test/fixtures/xruby/lib' + end + + def simple_canonical_data + simple_canonical_data = Minitest::Mock.new + simple_canonical_data.expect( + :to_s, + <<-TEXT +{ + "description": "Test canonical data", + "cases": [ + { + "description": "add 2 numbers", + "input": [1,1], + "expected": 2 + } + ] +} +TEXT + ) + simple_canonical_data + end + + def complex_canonical_data + complex_canonical_data = Minitest::Mock.new + complex_canonical_data.expect( + :to_s, + <<-TEXT +{ + "exercise": "beer-song", + "version": "1.0.0", + "cases": [ + { + "description": "verse", + "cases": [ + { + "description": "single verse", + "cases": [ + { + "description": "first generic verse", + "property": "verse", + "number": 99, + "expected": "99 bottles of beer on the wall, YAAAR" + }, + { + "description": "last generic verse", + "property": "verse", + "number": 3, + "expected": "3 bottles of beer on the wall, YAAAR" + } + ] + } + ] + }, + { + "description": "lyrics", + "cases": [ + { + "description": "multiple verses", + "cases": [ + { + "description": "first two verses", + "property": "verses", + "beginning": 99, + "end": 98, + "expected": "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT" + } + ] + } + ] + } + ] +} +TEXT + ) + complex_canonical_data + end + end + end +end diff --git a/test/generator/case_values_extract_test.rb b/test/generator/case_values_extract_test.rb new file mode 100644 index 0000000000..ba3785a292 --- /dev/null +++ b/test/generator/case_values_extract_test.rb @@ -0,0 +1,65 @@ +require_relative '../test_helper' + +module Generator + module CaseValues + class TestExtract + include Extract + + def canonical_data + simple_canonical_data = Minitest::Mock.new + simple_canonical_data.expect( + :to_s, + <<-TEXT +{ + "description": "Test canonical data", + "cases": [ + { + "description": "add 2 numbers", + "input": [1,1], + "expected": 2 + } + ] +} +TEXT + ) + simple_canonical_data + end + end + + class TestProcExtract < TestExtract + def exercise_name + 'alpha' + end + end + + class TestAutoExtract < TestExtract + def exercise_name + 'gamma' + end + end + + class ExtractTest < Minitest::Test + + def setup + $LOAD_PATH.unshift 'test/fixtures/xruby/lib' + end + + def test_extract_via_proc + cases = TestProcExtract.new.extract + expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def test_auto_extract + cases = TestAutoExtract.new.extract + expected = [GammaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def teardown + $LOAD_PATH.delete 'test/fixtures/xruby/lib' + end + + end + end +end diff --git a/test/generator/case_values_proc_extractor_test.rb b/test/generator/case_values_proc_extractor_test.rb new file mode 100644 index 0000000000..d26a5604ab --- /dev/null +++ b/test/generator/case_values_proc_extractor_test.rb @@ -0,0 +1,46 @@ +require_relative '../test_helper' + +module Generator + module CaseValues + class ProcExtractorTest < Minitest::Test + + def setup + $LOAD_PATH.unshift 'test/fixtures/xruby/lib' + end + + def test_extract_via_proc + cases = ProcExtractor.new( + exercise_name: 'alpha', + exercise_data: simple_canonical_data.to_s + ).extract + expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def teardown + $LOAD_PATH.delete 'test/fixtures/xruby/lib' + end + + def simple_canonical_data + simple_canonical_data = Minitest::Mock.new + simple_canonical_data.expect( + :to_s, + <<-TEXT +{ + "description": "Test canonical data", + "cases": [ + { + "description": "add 2 numbers", + "input": [1,1], + "expected": 2 + } + ] +} +TEXT + ) + simple_canonical_data + end + + end + end +end diff --git a/test/generator/template_values_test.rb b/test/generator/template_values_test.rb index ae76e465d9..aa5c47ff44 100644 --- a/test/generator/template_values_test.rb +++ b/test/generator/template_values_test.rb @@ -57,114 +57,4 @@ def teardown end end - class CaseValuesTest < Minitest::Test - def setup - $LOAD_PATH.unshift 'test/fixtures/xruby/lib' - end - - def simple_canonical_data - simple_canonical_data = Minitest::Mock.new - simple_canonical_data.expect( - :to_s, - <<-TEXT -{ - "description": "Test canonical data", - "cases": [ - { - "description": "add 2 numbers", - "input": [1,1], - "expected": 2 - } - ] -} -TEXT - ) - simple_canonical_data - end - - def complex_canonical_data - complex_canonical_data = Minitest::Mock.new - complex_canonical_data.expect( - :to_s, - <<-TEXT -{ - "exercise": "beer-song", - "version": "1.0.0", - "cases": [ - { - "description": "verse", - "cases": [ - { - "description": "single verse", - "cases": [ - { - "description": "first generic verse", - "property": "verse", - "number": 99, - "expected": "99 bottles of beer on the wall, YAAAR" - }, - { - "description": "last generic verse", - "property": "verse", - "number": 3, - "expected": "3 bottles of beer on the wall, YAAAR" - } - ] - } - ] - }, - { - "description": "lyrics", - "cases": [ - { - "description": "multiple verses", - "cases": [ - { - "description": "first two verses", - "property": "verses", - "beginning": 99, - "end": 98, - "expected": "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT" - } - ] - } - ] - } - ] -} -TEXT - ) - complex_canonical_data - end - - def test_extract_via_proc - cases = CaseValues.extract(exercise_name: 'alpha', exercise_data: simple_canonical_data.to_s) - expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s - end - - def test_simple_auto_extraction - cases = CaseValues.extract(exercise_name: 'gamma', exercise_data: simple_canonical_data.to_s) - expected = [GammaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s - end - - def test_multi_level_auto_extraction - cases = CaseValues.extract(exercise_name: 'gamma', exercise_data: complex_canonical_data.to_s) - expected = [ - GammaCase.new(description: 'first generic verse', property: 'verse', number: 99, - expected: '99 bottles of beer on the wall, YAAAR', index: 0), - GammaCase.new(description: 'last generic verse', property: 'verse', number: 3, - expected: '3 bottles of beer on the wall, YAAAR', index: 1), - GammaCase.new(description: 'first two verses', property: 'verses', beginning: 99, end: 98, - expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT", index: 2), - - ] - assert_equal expected.to_s, cases.to_s - end - - def teardown - $LOAD_PATH.delete 'test/fixtures/xruby/lib' - end - end end From 263e233351e4792e54ae36fa5b7356a6880cae11 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 13:41:39 -0700 Subject: [PATCH 05/61] add #proc? to GeneratorCases --- lib/generator/case_values.rb | 5 +---- lib/generator/files/track_files.rb | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/generator/case_values.rb b/lib/generator/case_values.rb index 4a47bdc139..9c76ee431a 100644 --- a/lib/generator/case_values.rb +++ b/lib/generator/case_values.rb @@ -13,12 +13,9 @@ def extract private def extractor - Object.const_defined?(test_cases_procname) ? ProcExtractor : AutoExtractor + Files::GeneratorCases.proc?(exercise_name) ? ProcExtractor : AutoExtractor end - def test_cases_procname - Files::GeneratorCases.proc_name(exercise_name) - end end class Extractor diff --git a/lib/generator/files/track_files.rb b/lib/generator/files/track_files.rb index 8f02def91a..8c19b96955 100644 --- a/lib/generator/files/track_files.rb +++ b/lib/generator/files/track_files.rb @@ -18,7 +18,10 @@ def class_name(exercise_name) filename(exercise_name)[0..-2].split('_').map(&:capitalize).join end - # TODO: for backwards compatibility, remove post-conversion + def proc?(exercise_name) + Object.const_defined?(proc_name(exercise_name)) + end + def proc_name(exercise_name) class_name(exercise_name) + 's' end From 068d1f5854346ab33991d625ba01a77746d58dcd Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 14:11:34 -0700 Subject: [PATCH 06/61] fold Extract into TemplateValuesFactory --- lib/generator/case_values.rb | 25 ------- lib/generator/template_values.rb | 22 ++++++- .../case_values_auto_extractor_test.rb | 2 + test/generator/case_values_extract_test.rb | 65 ------------------- .../case_values_proc_extractor_test.rb | 1 + 5 files changed, 23 insertions(+), 92 deletions(-) delete mode 100644 test/generator/case_values_extract_test.rb diff --git a/lib/generator/case_values.rb b/lib/generator/case_values.rb index 9c76ee431a..55091d4a4f 100644 --- a/lib/generator/case_values.rb +++ b/lib/generator/case_values.rb @@ -1,23 +1,6 @@ module Generator module CaseValues - module Extract - - def extract - extractor.extract( - exercise_name: exercise_name, - exercise_data: canonical_data.to_s - ) - end - - private - - def extractor - Files::GeneratorCases.proc?(exercise_name) ? ProcExtractor : AutoExtractor - end - - end - class Extractor attr_reader :exercise_name, :exercise_data @@ -31,19 +14,11 @@ def self.extract(exercise_name:, exercise_data:) def initialize(exercise_name:, exercise_data:) @exercise_name = exercise_name @exercise_data = exercise_data - - require cases_require_name end def extract fail NotImplementedError, 'Should return an array of ProblemNameCase' end - - private - - def cases_require_name - Files::GeneratorCases.filename(exercise_name) - end end class AutoExtractor < Extractor diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index ccfa152f36..4dc1251c89 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -15,15 +15,33 @@ def get_binding end module TemplateValuesFactory - include CaseValues::Extract + include CaseValues def template_values + require cases_require_name + TemplateValues.new( abbreviated_commit_hash: canonical_data.abbreviated_commit_hash, version: version, test_cases: extract ) end - end + private + + def extract + extractor.extract( + exercise_name: exercise_name, + exercise_data: canonical_data.to_s + ) + end + + def extractor + Files::GeneratorCases.proc?(exercise_name) ? ProcExtractor : AutoExtractor + end + + def cases_require_name + Files::GeneratorCases.filename(exercise_name) + end + end end diff --git a/test/generator/case_values_auto_extractor_test.rb b/test/generator/case_values_auto_extractor_test.rb index cdf77f8191..c55c1ca35d 100644 --- a/test/generator/case_values_auto_extractor_test.rb +++ b/test/generator/case_values_auto_extractor_test.rb @@ -9,6 +9,7 @@ def setup end def test_simple_auto_extraction + require Files::GeneratorCases.filename('gamma') cases = AutoExtractor.new( exercise_name: 'gamma', exercise_data: simple_canonical_data.to_s ).extract @@ -17,6 +18,7 @@ def test_simple_auto_extraction end def test_multi_level_auto_extraction + require Files::GeneratorCases.filename('gamma') cases = AutoExtractor.new( exercise_name: 'gamma', exercise_data: complex_canonical_data.to_s ).extract diff --git a/test/generator/case_values_extract_test.rb b/test/generator/case_values_extract_test.rb deleted file mode 100644 index ba3785a292..0000000000 --- a/test/generator/case_values_extract_test.rb +++ /dev/null @@ -1,65 +0,0 @@ -require_relative '../test_helper' - -module Generator - module CaseValues - class TestExtract - include Extract - - def canonical_data - simple_canonical_data = Minitest::Mock.new - simple_canonical_data.expect( - :to_s, - <<-TEXT -{ - "description": "Test canonical data", - "cases": [ - { - "description": "add 2 numbers", - "input": [1,1], - "expected": 2 - } - ] -} -TEXT - ) - simple_canonical_data - end - end - - class TestProcExtract < TestExtract - def exercise_name - 'alpha' - end - end - - class TestAutoExtract < TestExtract - def exercise_name - 'gamma' - end - end - - class ExtractTest < Minitest::Test - - def setup - $LOAD_PATH.unshift 'test/fixtures/xruby/lib' - end - - def test_extract_via_proc - cases = TestProcExtract.new.extract - expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s - end - - def test_auto_extract - cases = TestAutoExtract.new.extract - expected = [GammaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s - end - - def teardown - $LOAD_PATH.delete 'test/fixtures/xruby/lib' - end - - end - end -end diff --git a/test/generator/case_values_proc_extractor_test.rb b/test/generator/case_values_proc_extractor_test.rb index d26a5604ab..90ab5fabb4 100644 --- a/test/generator/case_values_proc_extractor_test.rb +++ b/test/generator/case_values_proc_extractor_test.rb @@ -9,6 +9,7 @@ def setup end def test_extract_via_proc + require Files::GeneratorCases.filename('alpha') cases = ProcExtractor.new( exercise_name: 'alpha', exercise_data: simple_canonical_data.to_s From 75b81d7f4a73be650f36f6605d0e5f467f102604 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 09:24:04 +0100 Subject: [PATCH 07/61] Minor: Remove unnecessary whitespace changes. --- test/generator/case_values_auto_extractor_test.rb | 4 +--- test/generator/template_values_test.rb | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/test/generator/case_values_auto_extractor_test.rb b/test/generator/case_values_auto_extractor_test.rb index c55c1ca35d..15fb344e58 100644 --- a/test/generator/case_values_auto_extractor_test.rb +++ b/test/generator/case_values_auto_extractor_test.rb @@ -3,7 +3,6 @@ module Generator module CaseValues class AutoExtractorTest < Minitest::Test - def setup $LOAD_PATH.unshift 'test/fixtures/xruby/lib' end @@ -29,8 +28,7 @@ def test_multi_level_auto_extraction GammaCase.new(description: 'last generic verse', property: 'verse', number: 3, expected: '3 bottles of beer on the wall, YAAAR', index: 1), GammaCase.new(description: 'first two verses', property: 'verses', beginning: 99, end: 98, - expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT", index: 2), - + expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT", index: 2) ] assert_equal expected.to_s, cases.to_s end diff --git a/test/generator/template_values_test.rb b/test/generator/template_values_test.rb index aa5c47ff44..75abf8abf9 100644 --- a/test/generator/template_values_test.rb +++ b/test/generator/template_values_test.rb @@ -56,5 +56,4 @@ def teardown $LOAD_PATH.delete 'test/fixtures/xruby/lib' end end - end From 9f6a9e3c674ff139aee460369998fff9c663a02e Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 09:40:34 +0100 Subject: [PATCH 08/61] Remove redundant test. --- .../case_values_auto_extractor_test.rb | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/test/generator/case_values_auto_extractor_test.rb b/test/generator/case_values_auto_extractor_test.rb index 15fb344e58..cd3ab579ee 100644 --- a/test/generator/case_values_auto_extractor_test.rb +++ b/test/generator/case_values_auto_extractor_test.rb @@ -7,15 +7,6 @@ def setup $LOAD_PATH.unshift 'test/fixtures/xruby/lib' end - def test_simple_auto_extraction - require Files::GeneratorCases.filename('gamma') - cases = AutoExtractor.new( - exercise_name: 'gamma', exercise_data: simple_canonical_data.to_s - ).extract - expected = [GammaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s - end - def test_multi_level_auto_extraction require Files::GeneratorCases.filename('gamma') cases = AutoExtractor.new( @@ -37,26 +28,6 @@ def teardown $LOAD_PATH.delete 'test/fixtures/xruby/lib' end - def simple_canonical_data - simple_canonical_data = Minitest::Mock.new - simple_canonical_data.expect( - :to_s, - <<-TEXT -{ - "description": "Test canonical data", - "cases": [ - { - "description": "add 2 numbers", - "input": [1,1], - "expected": 2 - } - ] -} -TEXT - ) - simple_canonical_data - end - def complex_canonical_data complex_canonical_data = Minitest::Mock.new complex_canonical_data.expect( From 1700748d7a101916051bd0bc6135653f83b952ea Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 09:43:29 +0100 Subject: [PATCH 09/61] Inline the GammaCase rather than reading it from a file. --- test/fixtures/xruby/lib/gamma_cases.rb | 7 ------- test/generator/case_values_auto_extractor_test.rb | 15 ++++++--------- test/generator/files/track_files_test.rb | 2 +- 3 files changed, 7 insertions(+), 17 deletions(-) delete mode 100644 test/fixtures/xruby/lib/gamma_cases.rb diff --git a/test/fixtures/xruby/lib/gamma_cases.rb b/test/fixtures/xruby/lib/gamma_cases.rb deleted file mode 100644 index 40cc9b7884..0000000000 --- a/test/fixtures/xruby/lib/gamma_cases.rb +++ /dev/null @@ -1,7 +0,0 @@ -class GammaCase < ExerciseCase - - def workload - assert { Gamma.foo(bar) } - end - -end diff --git a/test/generator/case_values_auto_extractor_test.rb b/test/generator/case_values_auto_extractor_test.rb index cd3ab579ee..f2952b562b 100644 --- a/test/generator/case_values_auto_extractor_test.rb +++ b/test/generator/case_values_auto_extractor_test.rb @@ -1,14 +1,15 @@ require_relative '../test_helper' +class GammaCase < ExerciseCase + def workload + assert { Gamma.foo(bar) } + end +end + module Generator module CaseValues class AutoExtractorTest < Minitest::Test - def setup - $LOAD_PATH.unshift 'test/fixtures/xruby/lib' - end - def test_multi_level_auto_extraction - require Files::GeneratorCases.filename('gamma') cases = AutoExtractor.new( exercise_name: 'gamma', exercise_data: complex_canonical_data.to_s ).extract @@ -24,10 +25,6 @@ def test_multi_level_auto_extraction assert_equal expected.to_s, cases.to_s end - def teardown - $LOAD_PATH.delete 'test/fixtures/xruby/lib' - end - def complex_canonical_data complex_canonical_data = Minitest::Mock.new complex_canonical_data.expect( diff --git a/test/generator/files/track_files_test.rb b/test/generator/files/track_files_test.rb index 05e24a714c..8b30a70420 100644 --- a/test/generator/files/track_files_test.rb +++ b/test/generator/files/track_files_test.rb @@ -10,7 +10,7 @@ def test_no_cases_found def test_cases_found track_path = 'test/fixtures/xruby' - assert_equal %w(alpha beta gamma), GeneratorCases.available(track_path).sort + assert_equal %w(alpha beta), GeneratorCases.available(track_path).sort end def test_available_returns_exercise_names From 33e0881683ce159ada8ce8f4b44011009aa56c7b Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 09:49:35 +0100 Subject: [PATCH 10/61] Move case values tests into a single file. --- .../case_values_proc_extractor_test.rb | 47 ------------------- ..._extractor_test.rb => case_values_test.rb} | 40 ++++++++++++++++ 2 files changed, 40 insertions(+), 47 deletions(-) delete mode 100644 test/generator/case_values_proc_extractor_test.rb rename test/generator/{case_values_auto_extractor_test.rb => case_values_test.rb} (71%) diff --git a/test/generator/case_values_proc_extractor_test.rb b/test/generator/case_values_proc_extractor_test.rb deleted file mode 100644 index 90ab5fabb4..0000000000 --- a/test/generator/case_values_proc_extractor_test.rb +++ /dev/null @@ -1,47 +0,0 @@ -require_relative '../test_helper' - -module Generator - module CaseValues - class ProcExtractorTest < Minitest::Test - - def setup - $LOAD_PATH.unshift 'test/fixtures/xruby/lib' - end - - def test_extract_via_proc - require Files::GeneratorCases.filename('alpha') - cases = ProcExtractor.new( - exercise_name: 'alpha', - exercise_data: simple_canonical_data.to_s - ).extract - expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s - end - - def teardown - $LOAD_PATH.delete 'test/fixtures/xruby/lib' - end - - def simple_canonical_data - simple_canonical_data = Minitest::Mock.new - simple_canonical_data.expect( - :to_s, - <<-TEXT -{ - "description": "Test canonical data", - "cases": [ - { - "description": "add 2 numbers", - "input": [1,1], - "expected": 2 - } - ] -} -TEXT - ) - simple_canonical_data - end - - end - end -end diff --git a/test/generator/case_values_auto_extractor_test.rb b/test/generator/case_values_test.rb similarity index 71% rename from test/generator/case_values_auto_extractor_test.rb rename to test/generator/case_values_test.rb index f2952b562b..ba446dc399 100644 --- a/test/generator/case_values_auto_extractor_test.rb +++ b/test/generator/case_values_test.rb @@ -80,5 +80,45 @@ def complex_canonical_data complex_canonical_data end end + + class ProcExtractorTest < Minitest::Test + def setup + $LOAD_PATH.unshift 'test/fixtures/xruby/lib' + end + + def test_extract_via_proc + require Files::GeneratorCases.filename('alpha') + cases = ProcExtractor.new( + exercise_name: 'alpha', + exercise_data: simple_canonical_data.to_s + ).extract + expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] + assert_equal expected.to_s, cases.to_s + end + + def teardown + $LOAD_PATH.delete 'test/fixtures/xruby/lib' + end + + def simple_canonical_data + simple_canonical_data = Minitest::Mock.new + simple_canonical_data.expect( + :to_s, + <<-TEXT +{ + "description": "Test canonical data", + "cases": [ + { + "description": "add 2 numbers", + "input": [1,1], + "expected": 2 + } + ] +} +TEXT + ) + simple_canonical_data + end + end end end From f088d24d720bbda5d2b7f02fa573b163162ccf1e Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 09:55:21 +0100 Subject: [PATCH 11/61] Remove redundant Mocks. --- test/generator/case_values_test.rb | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index ba446dc399..8b5bc0f8a2 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -11,7 +11,7 @@ module CaseValues class AutoExtractorTest < Minitest::Test def test_multi_level_auto_extraction cases = AutoExtractor.new( - exercise_name: 'gamma', exercise_data: complex_canonical_data.to_s + exercise_name: 'gamma', exercise_data: complex_canonical_data ).extract expected = [ @@ -26,10 +26,7 @@ def test_multi_level_auto_extraction end def complex_canonical_data - complex_canonical_data = Minitest::Mock.new - complex_canonical_data.expect( - :to_s, - <<-TEXT + <<-TEXT { "exercise": "beer-song", "version": "1.0.0", @@ -76,8 +73,6 @@ def complex_canonical_data ] } TEXT - ) - complex_canonical_data end end @@ -90,7 +85,7 @@ def test_extract_via_proc require Files::GeneratorCases.filename('alpha') cases = ProcExtractor.new( exercise_name: 'alpha', - exercise_data: simple_canonical_data.to_s + exercise_data: simple_canonical_data ).extract expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] assert_equal expected.to_s, cases.to_s @@ -101,10 +96,7 @@ def teardown end def simple_canonical_data - simple_canonical_data = Minitest::Mock.new - simple_canonical_data.expect( - :to_s, - <<-TEXT + <<-TEXT { "description": "Test canonical data", "cases": [ @@ -116,8 +108,6 @@ def simple_canonical_data ] } TEXT - ) - simple_canonical_data end end end From 001e60833ad39f37b4242c726dd7c5aceed769c9 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 10:01:06 +0100 Subject: [PATCH 12/61] Add test coverage for unimplmented extract method. --- test/generator/case_values_test.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index 8b5bc0f8a2..7f042f4e5e 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -8,6 +8,14 @@ def workload module Generator module CaseValues + class ExtractorTest < Minitest::Test + def test_not_implemented_error + assert_raises NotImplementedError do + Extractor.extract(exercise_name: nil, exercise_data: nil) + end + end + end + class AutoExtractorTest < Minitest::Test def test_multi_level_auto_extraction cases = AutoExtractor.new( From 012ce13e582ed808ec965cd64d8bdac3e1f11541 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 10:13:40 +0100 Subject: [PATCH 13/61] Eliminte LOAD_PATH modifications. Just load the alpha_cases file direcly, we know where it is. --- test/generator/case_values_test.rb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index 7f042f4e5e..fedd9c79fe 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -85,12 +85,8 @@ def complex_canonical_data end class ProcExtractorTest < Minitest::Test - def setup - $LOAD_PATH.unshift 'test/fixtures/xruby/lib' - end - def test_extract_via_proc - require Files::GeneratorCases.filename('alpha') + require_relative '../fixtures/xruby/lib/alpha_cases.rb' cases = ProcExtractor.new( exercise_name: 'alpha', exercise_data: simple_canonical_data @@ -99,10 +95,6 @@ def test_extract_via_proc assert_equal expected.to_s, cases.to_s end - def teardown - $LOAD_PATH.delete 'test/fixtures/xruby/lib' - end - def simple_canonical_data <<-TEXT { From 9547152f587c9593c56bee772a88c913316e78e1 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 10:17:26 +0100 Subject: [PATCH 14/61] Use fixture data we already have. test/fixtures/metadata/exercises/alpha/canonical-data.json We are the only user of this fixture data. --- test/generator/case_values_test.rb | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index fedd9c79fe..915d86c68b 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -89,26 +89,11 @@ def test_extract_via_proc require_relative '../fixtures/xruby/lib/alpha_cases.rb' cases = ProcExtractor.new( exercise_name: 'alpha', - exercise_data: simple_canonical_data + exercise_data: File.read('test/fixtures/metadata/exercises/alpha/canonical-data.json') ).extract expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] assert_equal expected.to_s, cases.to_s end - - def simple_canonical_data - <<-TEXT -{ - "description": "Test canonical data", - "cases": [ - { - "description": "add 2 numbers", - "input": [1,1], - "expected": 2 - } - ] -} -TEXT - end end end end From d29bceb50329ced75633fdedd6b54f14041da50f Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 10:25:00 +0100 Subject: [PATCH 15/61] Remove unnecessary inclusion of CaseValues --- lib/generator/template_values.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index 4dc1251c89..11b809844f 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -15,8 +15,6 @@ def get_binding end module TemplateValuesFactory - include CaseValues - def template_values require cases_require_name @@ -37,7 +35,7 @@ def extract end def extractor - Files::GeneratorCases.proc?(exercise_name) ? ProcExtractor : AutoExtractor + Files::GeneratorCases.proc?(exercise_name) ? CaseValues::ProcExtractor : CaseValues::AutoExtractor end def cases_require_name From 8b2ae2afb7479b12c8bef042e6dbe2419b9de222 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 11:02:29 +0100 Subject: [PATCH 16/61] Extract complex json to fixture file. Renamed 'gamma' to 'complex'. --- .../exercises/complex/canonical-data.json | 45 ++++++++++++ test/generator/case_values_test.rb | 69 +++---------------- 2 files changed, 55 insertions(+), 59 deletions(-) create mode 100644 test/fixtures/metadata/exercises/complex/canonical-data.json diff --git a/test/fixtures/metadata/exercises/complex/canonical-data.json b/test/fixtures/metadata/exercises/complex/canonical-data.json new file mode 100644 index 0000000000..699953ed5a --- /dev/null +++ b/test/fixtures/metadata/exercises/complex/canonical-data.json @@ -0,0 +1,45 @@ +{ + "exercise": "beer-song", + "version": "1.0.0", + "cases": [ + { + "description": "verse", + "cases": [ + { + "description": "single verse", + "cases": [ + { + "description": "first generic verse", + "property": "verse", + "number": 99, + "expected": "99 bottles of beer on the wall, YAAAR" + }, + { + "description": "last generic verse", + "property": "verse", + "number": 3, + "expected": "3 bottles of beer on the wall, YAAAR" + } + ] + } + ] + }, + { + "description": "lyrics", + "cases": [ + { + "description": "multiple verses", + "cases": [ + { + "description": "first two verses", + "property": "verses", + "beginning": 99, + "end": 98, + "expected": "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT" + } + ] + } + ] + } + ] +} diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index 915d86c68b..319242898e 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -1,8 +1,8 @@ require_relative '../test_helper' -class GammaCase < ExerciseCase +class ComplexCase < ExerciseCase def workload - assert { Gamma.foo(bar) } + assert { Complex.foo(bar) } end end @@ -19,69 +19,20 @@ def test_not_implemented_error class AutoExtractorTest < Minitest::Test def test_multi_level_auto_extraction cases = AutoExtractor.new( - exercise_name: 'gamma', exercise_data: complex_canonical_data + exercise_name: 'complex', + exercise_data: File.read('test/fixtures/metadata/exercises/complex/canonical-data.json') ).extract expected = [ - GammaCase.new(description: 'first generic verse', property: 'verse', number: 99, - expected: '99 bottles of beer on the wall, YAAAR', index: 0), - GammaCase.new(description: 'last generic verse', property: 'verse', number: 3, - expected: '3 bottles of beer on the wall, YAAAR', index: 1), - GammaCase.new(description: 'first two verses', property: 'verses', beginning: 99, end: 98, - expected: "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT", index: 2) + ComplexCase.new(description: 'first generic verse', property: 'verse', number: 99, + expected: '99 bottles of beer on the wall, YAAAR', index: 0), + ComplexCase.new(description: 'last generic verse', property: 'verse', number: 3, + expected: '3 bottles of beer on the wall, YAAAR', index: 1), + 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", index: 2) ] assert_equal expected.to_s, cases.to_s end - - def complex_canonical_data - <<-TEXT -{ - "exercise": "beer-song", - "version": "1.0.0", - "cases": [ - { - "description": "verse", - "cases": [ - { - "description": "single verse", - "cases": [ - { - "description": "first generic verse", - "property": "verse", - "number": 99, - "expected": "99 bottles of beer on the wall, YAAAR" - }, - { - "description": "last generic verse", - "property": "verse", - "number": 3, - "expected": "3 bottles of beer on the wall, YAAAR" - } - ] - } - ] - }, - { - "description": "lyrics", - "cases": [ - { - "description": "multiple verses", - "cases": [ - { - "description": "first two verses", - "property": "verses", - "beginning": 99, - "end": 98, - "expected": "99 bottles of beer on the wall, YAR, PIRATES CAN'T COUNT" - } - ] - } - ] - } - ] -} -TEXT - end end class ProcExtractorTest < Minitest::Test From 8fb05bf4cb47c2f53952af7fb10902668b59f244 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 11:04:07 +0100 Subject: [PATCH 17/61] Remove unnecessary string conversions. --- test/generator/case_values_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index 319242898e..91a6f032f0 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -31,7 +31,7 @@ def test_multi_level_auto_extraction 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", index: 2) ] - assert_equal expected.to_s, cases.to_s + assert_equal expected, cases end end @@ -43,7 +43,7 @@ def test_extract_via_proc exercise_data: File.read('test/fixtures/metadata/exercises/alpha/canonical-data.json') ).extract expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected.to_s, cases.to_s + assert_equal expected, cases end end end From 45511ff154c0835f3a8f8870a706be64d01b530e Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Wed, 26 Apr 2017 18:48:41 +0100 Subject: [PATCH 18/61] Explicitly load the ProblemCases file we need. Add test that template_values loads problem cases Remove commented out code. Make everything that loads AlphaCase(s) clean up after itself. Undefine AlphaCase(s) during teardown. Remove redundant setup. Check for both classes. Add tests for class based test generation squash Remove TODO comment --- lib/generator/files/track_files.rb | 5 +++ lib/generator/template_values.rb | 13 ++++--- test/fixtures/xruby/lib/beta_cases.rb | 7 ++++ test/generator/case_values_test.rb | 10 ++++- test/generator/template_values_test.rb | 52 ++++++++++++++++++++++++-- 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lib/generator/files/track_files.rb b/lib/generator/files/track_files.rb index 8c19b96955..7238115f4d 100644 --- a/lib/generator/files/track_files.rb +++ b/lib/generator/files/track_files.rb @@ -29,6 +29,11 @@ def proc_name(exercise_name) def exercise_name(filename) %r{([^/]*)_cases\.rb$}.match(filename).captures[0].tr('_', '-') end + + def load_filename(track_path, exercise_name) + path = File.join(track_path, 'lib') + "%s/%s.rb" % [ path, filename(exercise_name) ] + end end module TrackFiles diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index 11b809844f..516e4406a8 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -16,8 +16,6 @@ def get_binding module TemplateValuesFactory def template_values - require cases_require_name - TemplateValues.new( abbreviated_commit_hash: canonical_data.abbreviated_commit_hash, version: version, @@ -35,11 +33,16 @@ def extract end def extractor - Files::GeneratorCases.proc?(exercise_name) ? CaseValues::ProcExtractor : CaseValues::AutoExtractor + load cases_load_name + if Files::GeneratorCases.proc?(exercise_name) + CaseValues::ProcExtractor + else + CaseValues::AutoExtractor + end end - def cases_require_name - Files::GeneratorCases.filename(exercise_name) + def cases_load_name + Files::GeneratorCases.load_filename(paths.track, exercise_name) end end end diff --git a/test/fixtures/xruby/lib/beta_cases.rb b/test/fixtures/xruby/lib/beta_cases.rb index e69de29bb2..e442b4e531 100644 --- a/test/fixtures/xruby/lib/beta_cases.rb +++ b/test/fixtures/xruby/lib/beta_cases.rb @@ -0,0 +1,7 @@ +require 'exercise_cases' + +class BetaCase < ExerciseCase + def workload + assert_equal { "Beta.call('#{input}')" } + end +end diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index 91a6f032f0..250408242f 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -36,8 +36,11 @@ def test_multi_level_auto_extraction end class ProcExtractorTest < Minitest::Test + def setup + load 'test/fixtures/xruby/lib/alpha_cases.rb' + end + def test_extract_via_proc - require_relative '../fixtures/xruby/lib/alpha_cases.rb' cases = ProcExtractor.new( exercise_name: 'alpha', exercise_data: File.read('test/fixtures/metadata/exercises/alpha/canonical-data.json') @@ -45,6 +48,11 @@ def test_extract_via_proc expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] assert_equal expected, cases end + + def teardown + Object.send(:remove_const, :AlphaCases) + Object.send(:remove_const, :AlphaCase) + end end end end diff --git a/test/generator/template_values_test.rb b/test/generator/template_values_test.rb index 75abf8abf9..c13260eceb 100644 --- a/test/generator/template_values_test.rb +++ b/test/generator/template_values_test.rb @@ -43,17 +43,63 @@ def canonical_data mock_canonical_data end + def paths + mock_paths = Minitest::Mock.new + mock_paths.expect :track, 'test/fixtures/xruby' + mock_paths + end + include TemplateValuesFactory end - def test_template_values - $LOAD_PATH.unshift 'test/fixtures/xruby/lib' + def test_template_values_from_proc subject = TestTemplateValuesFactory.new assert_instance_of TemplateValues, subject.template_values end + class ClassBasedTestTemplateValuesFactory + def exercise_name + 'beta' + end + + def version + 2 + end + + def canonical_data + mock_canonical_data = Minitest::Mock.new + mock_canonical_data.expect :abbreviated_commit_hash, nil + mock_canonical_data.expect :to_s, '{"cases":[]}' + mock_canonical_data + end + + def paths + mock_paths = Minitest::Mock.new + mock_paths.expect :track, 'test/fixtures/xruby' + mock_paths + end + + include TemplateValuesFactory + end + + def test_template_values_from_class + subject = ClassBasedTestTemplateValuesFactory.new + assert_instance_of TemplateValues, subject.template_values + end + + def test_template_values_loads_problem_case_classes + subject = TestTemplateValuesFactory.new + assert_instance_of TemplateValues, subject.template_values + assert Object.const_defined?(:AlphaCase) + assert Object.const_defined?(:AlphaCases) + end + def teardown - $LOAD_PATH.delete 'test/fixtures/xruby/lib' + [:AlphaCase, :AlphaCases].each do |classname| + if Object.const_defined?(classname) + Object.send(:remove_const, classname) + end + end end end end From 0b47df337785a0310708f26deecd83c17a0b60fa Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 14:28:35 -0700 Subject: [PATCH 19/61] remove proc support (not needed) all generators converted to use auto extraction in https://github.com/exercism/xruby/pull/567 --- lib/generator/case_values.rb | 21 ----------------- lib/generator/files/track_files.rb | 8 ------- lib/generator/template_values.rb | 13 +++------- test/generator/case_values_test.rb | 30 +----------------------- test/generator/files/track_files_test.rb | 5 ---- test/generator/template_values_test.rb | 5 ---- 6 files changed, 4 insertions(+), 78 deletions(-) diff --git a/lib/generator/case_values.rb b/lib/generator/case_values.rb index 55091d4a4f..9d109d9edc 100644 --- a/lib/generator/case_values.rb +++ b/lib/generator/case_values.rb @@ -16,13 +16,6 @@ def initialize(exercise_name:, exercise_data:) @exercise_data = exercise_data end - def extract - fail NotImplementedError, 'Should return an array of ProblemNameCase' - end - end - - class AutoExtractor < Extractor - def extract extract_test_cases.map.with_index do |test, index| test_case_class.new(test.merge('index' => index)) @@ -42,19 +35,5 @@ def test_case_class end end - class ProcExtractor < Extractor - - def extract - test_cases_proc.call(exercise_data) - end - - private - - def test_cases_proc - Object.const_get(Files::GeneratorCases.proc_name(exercise_name)) - end - - end - end end diff --git a/lib/generator/files/track_files.rb b/lib/generator/files/track_files.rb index 7238115f4d..9fe130368b 100644 --- a/lib/generator/files/track_files.rb +++ b/lib/generator/files/track_files.rb @@ -18,14 +18,6 @@ def class_name(exercise_name) filename(exercise_name)[0..-2].split('_').map(&:capitalize).join end - def proc?(exercise_name) - Object.const_defined?(proc_name(exercise_name)) - end - - def proc_name(exercise_name) - class_name(exercise_name) + 's' - end - def exercise_name(filename) %r{([^/]*)_cases\.rb$}.match(filename).captures[0].tr('_', '-') end diff --git a/lib/generator/template_values.rb b/lib/generator/template_values.rb index 516e4406a8..b4dceeaa63 100644 --- a/lib/generator/template_values.rb +++ b/lib/generator/template_values.rb @@ -26,21 +26,14 @@ def template_values private def extract - extractor.extract( + load cases_load_name + + CaseValues::Extractor.extract( exercise_name: exercise_name, exercise_data: canonical_data.to_s ) end - def extractor - load cases_load_name - if Files::GeneratorCases.proc?(exercise_name) - CaseValues::ProcExtractor - else - CaseValues::AutoExtractor - end - end - def cases_load_name Files::GeneratorCases.load_filename(paths.track, exercise_name) end diff --git a/test/generator/case_values_test.rb b/test/generator/case_values_test.rb index 250408242f..7f57e8f80a 100644 --- a/test/generator/case_values_test.rb +++ b/test/generator/case_values_test.rb @@ -9,16 +9,8 @@ def workload module Generator module CaseValues class ExtractorTest < Minitest::Test - def test_not_implemented_error - assert_raises NotImplementedError do - Extractor.extract(exercise_name: nil, exercise_data: nil) - end - end - end - - class AutoExtractorTest < Minitest::Test def test_multi_level_auto_extraction - cases = AutoExtractor.new( + cases = Extractor.new( exercise_name: 'complex', exercise_data: File.read('test/fixtures/metadata/exercises/complex/canonical-data.json') ).extract @@ -34,25 +26,5 @@ def test_multi_level_auto_extraction assert_equal expected, cases end end - - class ProcExtractorTest < Minitest::Test - def setup - load 'test/fixtures/xruby/lib/alpha_cases.rb' - end - - def test_extract_via_proc - cases = ProcExtractor.new( - exercise_name: 'alpha', - exercise_data: File.read('test/fixtures/metadata/exercises/alpha/canonical-data.json') - ).extract - expected = [AlphaCase.new(description: 'add 2 numbers', input: [1, 1], expected: 2, index: 0)] - assert_equal expected, cases - end - - def teardown - Object.send(:remove_const, :AlphaCases) - Object.send(:remove_const, :AlphaCase) - end - end end end diff --git a/test/generator/files/track_files_test.rb b/test/generator/files/track_files_test.rb index 8b30a70420..7ea9f9af30 100644 --- a/test/generator/files/track_files_test.rb +++ b/test/generator/files/track_files_test.rb @@ -28,11 +28,6 @@ def test_filename def test_class_name assert_equal 'TwoParterCase', GeneratorCases.class_name('two-parter') end - - def test_proc_name - exercise_name = 'two-parter' - assert_equal 'TwoParterCases', GeneratorCases.proc_name(exercise_name) - end end class TrackFilesTest < Minitest::Test diff --git a/test/generator/template_values_test.rb b/test/generator/template_values_test.rb index c13260eceb..57a4e27afe 100644 --- a/test/generator/template_values_test.rb +++ b/test/generator/template_values_test.rb @@ -52,11 +52,6 @@ def paths include TemplateValuesFactory end - def test_template_values_from_proc - subject = TestTemplateValuesFactory.new - assert_instance_of TemplateValues, subject.template_values - end - class ClassBasedTestTemplateValuesFactory def exercise_name 'beta' From fcec4abc030e675214e89aaf405dffdfc1cc03ec Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 16:59:58 -0700 Subject: [PATCH 20/61] remove manual case extraction from clean generators --- lib/hamming_cases.rb | 6 ------ lib/luhn_cases.rb | 6 ------ lib/ocr_numbers_cases.rb | 5 ----- lib/pig_latin_cases.rb | 5 ----- 4 files changed, 22 deletions(-) diff --git a/lib/hamming_cases.rb b/lib/hamming_cases.rb index d6d8832831..9126ab8d23 100644 --- a/lib/hamming_cases.rb +++ b/lib/hamming_cases.rb @@ -13,9 +13,3 @@ def test_case "Hamming.compute('#{strand1}', '#{strand2}')" end end - -HammingCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - HammingCase.new(row.merge('index' => i)) - end -end diff --git a/lib/luhn_cases.rb b/lib/luhn_cases.rb index 377519f199..c72013c8fb 100644 --- a/lib/luhn_cases.rb +++ b/lib/luhn_cases.rb @@ -3,9 +3,3 @@ def workload "#{assert} Luhn.valid?(#{input.inspect})" end end - -LuhnCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - LuhnCase.new(row.merge('index' => i)) - end -end diff --git a/lib/ocr_numbers_cases.rb b/lib/ocr_numbers_cases.rb index fea8e4f2e8..8b4df05161 100644 --- a/lib/ocr_numbers_cases.rb +++ b/lib/ocr_numbers_cases.rb @@ -13,8 +13,3 @@ def test_case %Q(OcrNumbers.convert(#{(input.join("\n")).inspect})) end end - -OcrNumbersCases = proc do |data| - JSON.parse(data)['cases'].flat_map {|section| section['cases'] }. - map.with_index {|test, index| OcrNumbersCase.new(test.merge('index' => index)) } -end diff --git a/lib/pig_latin_cases.rb b/lib/pig_latin_cases.rb index c6b9b701f6..b2dbcbd839 100644 --- a/lib/pig_latin_cases.rb +++ b/lib/pig_latin_cases.rb @@ -3,8 +3,3 @@ def workload assert_equal { "PigLatin.translate(#{input.inspect})" } end end - -PigLatinCases = proc do |data| - JSON.parse(data)['cases'].flat_map {|section| section['cases'] }. # extract all the cases into a single array - map.with_index { |test, index| PigLatinCase.new(test.merge('index' => index)) } -end From 6e535a9b430d36e64f8d63c8b85e526b05d6e54c Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 17:05:01 -0700 Subject: [PATCH 21/61] update gigasecond tests (was not generatable) --- exercises/gigasecond/.meta/.version | 2 +- exercises/gigasecond/example.rb | 2 +- exercises/gigasecond/example.tt | 12 ++++++----- exercises/gigasecond/gigasecond_test.rb | 27 ++++++++++--------------- lib/gigasecond_cases.rb | 22 ++++---------------- 5 files changed, 24 insertions(+), 41 deletions(-) diff --git a/exercises/gigasecond/.meta/.version b/exercises/gigasecond/.meta/.version index 7813681f5b..62f9457511 100644 --- a/exercises/gigasecond/.meta/.version +++ b/exercises/gigasecond/.meta/.version @@ -1 +1 @@ -5 \ No newline at end of file +6 \ No newline at end of file diff --git a/exercises/gigasecond/example.rb b/exercises/gigasecond/example.rb index 5f7aeda515..2baf5de483 100644 --- a/exercises/gigasecond/example.rb +++ b/exercises/gigasecond/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 5 + VERSION = 6 end class Gigasecond diff --git a/exercises/gigasecond/example.tt b/exercises/gigasecond/example.tt index 6f2e64f18a..927d39cb45 100644 --- a/exercises/gigasecond/example.tt +++ b/exercises/gigasecond/example.tt @@ -2,12 +2,13 @@ require 'minitest/autorun' require_relative 'gigasecond' # Common test data version: <%= abbreviated_commit_hash %> -class GigasecondTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %> - result = Gigasecond.from(<%= test_case.got %>) - assert_equal <%= test_case.want %>, result +class GigasecondTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> # Test your 1Gs anniversary def test_with_your_birthday @@ -15,6 +16,7 @@ class GigasecondTest < Minitest::Test<% test_cases.each do |test_case| %> end <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping assert_equal <%= version %>, BookKeeping::VERSION end diff --git a/exercises/gigasecond/gigasecond_test.rb b/exercises/gigasecond/gigasecond_test.rb index 1117bdbd6f..826d16afa7 100755 --- a/exercises/gigasecond/gigasecond_test.rb +++ b/exercises/gigasecond/gigasecond_test.rb @@ -1,36 +1,31 @@ require 'minitest/autorun' require_relative 'gigasecond' -# Test data version: 9049dc7 - +# Common test data version: 61e7d70 class GigasecondTest < Minitest::Test - def test_2011_04_25 - result = Gigasecond.from(Time.utc(2011, 4, 25, 0, 0, 0)) - assert_equal Time.utc(2043, 1, 1, 1, 46, 40), result + def test_date_only_specification_of_time + # skip + assert_equal Time.utc(2043, 1, 1, 1, 46, 40), Gigasecond.from(Time.utc(2011, 4, 25, 0, 0, 0)) end - def test_1977_06_13 + def test_second_test_for_date_only_specification_of_time skip - result = Gigasecond.from(Time.utc(1977, 6, 13, 0, 0, 0)) - assert_equal Time.utc(2009, 2, 19, 1, 46, 40), result + assert_equal Time.utc(2009, 2, 19, 1, 46, 40), Gigasecond.from(Time.utc(1977, 6, 13, 0, 0, 0)) end - def test_1959_07_19 + def test_third_test_for_date_only_specification_of_time skip - result = Gigasecond.from(Time.utc(1959, 7, 19, 0, 0, 0)) - assert_equal Time.utc(1991, 3, 27, 1, 46, 40), result + assert_equal Time.utc(1991, 3, 27, 1, 46, 40), Gigasecond.from(Time.utc(1959, 7, 19, 0, 0, 0)) end def test_full_time_specified skip - result = Gigasecond.from(Time.utc(2015, 1, 24, 22, 0, 0)) - assert_equal Time.utc(2046, 10, 2, 23, 46, 40), result + assert_equal Time.utc(2046, 10, 2, 23, 46, 40), Gigasecond.from(Time.utc(2015, 1, 24, 22, 0, 0)) end def test_full_time_with_day_roll_over skip - result = Gigasecond.from(Time.utc(2015, 1, 24, 23, 59, 59)) - assert_equal Time.utc(2046, 10, 3, 1, 46, 39), result + assert_equal Time.utc(2046, 10, 3, 1, 46, 39), Gigasecond.from(Time.utc(2015, 1, 24, 23, 59, 59)) end # Test your 1Gs anniversary @@ -56,6 +51,6 @@ def test_with_your_birthday # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html def test_bookkeeping - assert_equal 5, BookKeeping::VERSION + assert_equal 6, BookKeeping::VERSION end end diff --git a/lib/gigasecond_cases.rb b/lib/gigasecond_cases.rb index 6ffb88aa67..31de9e80fc 100644 --- a/lib/gigasecond_cases.rb +++ b/lib/gigasecond_cases.rb @@ -1,15 +1,11 @@ -require 'exercise_cases' - require 'time' -class GigasecondCase < OpenStruct - def name - 'test_%s' % description.gsub(/[ :-]/, '_') +class GigasecondCase < ExerciseCase + def workload + %Q(assert_equal #{want}, Gigasecond.from(#{got})) end - def description - send(:'#') || input - end + private def got "Time.utc(#{start_values.join(', ')})" @@ -28,14 +24,4 @@ def stop_values ts = Time.parse(expected) [ts.year, ts.month, ts.day, ts.hour, ts.min, ts.sec] end - - def skipped? - index > 0 - end -end - -GigasecondCases = proc do |data| - JSON.parse(data)['add']['cases'].map.with_index do |row, i| - GigasecondCase.new(row.merge('index' => i)) - end end From 3c313deb11a18172f0c527df9f16681a53a23b59 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 17:11:08 -0700 Subject: [PATCH 22/61] remove instructions re ProblemNameCases from README --- README.md | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/README.md b/README.md index 40ecbb0111..d91a15eacb 100644 --- a/README.md +++ b/README.md @@ -157,39 +157,6 @@ and any setup required. The base class provides a variety of assertion and helper methods. Beyond that, you can implement any helper methods that you need as private methods in your derived class. See below for more information about [the intention of workload](#workload-philosophy) -Below this class, implement a small loop that will generate all the test cases by reading the -`canonical-data.json` file, and looping through the test cases. - -You will need to adjust the logic to match the structure of the canonical data. - -For example, if there is a single top-level key named "cases", then you can loop through -them as follows: - -``` -ProblemNameCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - ProblemNameCase.new(row.merge('index' => i)) - end -end -``` - -If there are multiple sections, then you will need to loop through the sections, and then -loop through each of the cases in an inner loop: - -``` -ProblemNameCases = proc do |data| - json = JSON.parse(data) - cases = [] - %w(section1 section2 etc).each do |section| - json[section]['cases'].each do |row| - row = row.merge(row.merge('index' => cases.size, 'section' => section)) - cases << ProblemNameCase.new(row) - end - end - cases -end -``` - Finally, you need to create a text template, `example.tt`, as the bases for the test suite. Start with the following boilerplate, and adjust as necessary. Remember, however, to strive From 1add0ee543a1dfbbff7b2250ca1bb8c11c5736a8 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 18:55:48 -0700 Subject: [PATCH 23/61] convert pangram to auto extract cases --- exercises/pangram/example.tt | 8 +++++--- exercises/pangram/pangram_test.rb | 3 ++- lib/pangram_cases.rb | 21 ++------------------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/exercises/pangram/example.tt b/exercises/pangram/example.tt index f90bcdd2b1..93a17413ef 100644 --- a/exercises/pangram/example.tt +++ b/exercises/pangram/example.tt @@ -5,14 +5,16 @@ require 'minitest/autorun' require_relative 'pangram' # Common test data version: <%= abbreviated_commit_hash %> -class PangramTest < Minitest::Test<% test_cases.each do |test_case| %> +class PangramTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> - <%= test_case.skipped? %> + <%= test_case.skipped %> <%= test_case.workload %> end -<% end %> +<% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/pangram/pangram_test.rb b/exercises/pangram/pangram_test.rb index 7d8beb8c82..445767b33a 100755 --- a/exercises/pangram/pangram_test.rb +++ b/exercises/pangram/pangram_test.rb @@ -4,7 +4,7 @@ require 'minitest/autorun' require_relative 'pangram' -# Test data version: # f04fb3d +# Common test data version: f375051 class PangramTest < Minitest::Test def test_sentence_empty # skip @@ -85,6 +85,7 @@ def test_upper_and_lower_case_versions_of_the_same_character_should_not_be_count # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip assert_equal 4, BookKeeping::VERSION diff --git a/lib/pangram_cases.rb b/lib/pangram_cases.rb index 744f90aed1..9193632b29 100644 --- a/lib/pangram_cases.rb +++ b/lib/pangram_cases.rb @@ -1,15 +1,11 @@ require 'exercise_cases' -class PangramCase < OpenStruct - def name - 'test_%s' % description.downcase.tr_s(" -'", '_').sub(/_$/, '') - end - +class PangramCase < ExerciseCase def workload [ "phrase = '#{input}'", " result = Pangram.pangram?(phrase)", - " #{assertion} result, \"#{message}\"" + " #{assert} result, \"#{message}\"" ].join("\n") end @@ -21,17 +17,4 @@ def is_or_isnt expected ? 'IS' : 'is NOT' end - def assertion - expected ? 'assert' : 'refute' - end - - def skipped? - index.zero? ? '# skip' : 'skip' - end -end - -PangramCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - PangramCase.new(row.merge('index' => i)) - end end From 465903bcabe574ee0f74b3461eb748e2a2699e7e Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 19:01:46 -0700 Subject: [PATCH 24/61] update acronym tests --- exercises/acronym/.meta/.version | 2 +- exercises/acronym/acronym_test.rb | 23 ++++++++++++++--------- exercises/acronym/example.rb | 2 +- exercises/acronym/example.tt | 11 +++++++---- lib/acronym_cases.rb | 18 +++--------------- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/exercises/acronym/.meta/.version b/exercises/acronym/.meta/.version index d8263ee986..e440e5c842 100644 --- a/exercises/acronym/.meta/.version +++ b/exercises/acronym/.meta/.version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/exercises/acronym/acronym_test.rb b/exercises/acronym/acronym_test.rb index 66ae69f20b..f3eeb64587 100755 --- a/exercises/acronym/acronym_test.rb +++ b/exercises/acronym/acronym_test.rb @@ -3,36 +3,41 @@ require 'minitest/autorun' require_relative 'acronym' -# Test data version: -# 5b5e807 +# Common test data version: dcfe476 class AcronymTest < Minitest::Test def test_basic - assert_equal 'PNG', Acronym.abbreviate('Portable Network Graphics') + # skip + assert_equal "PNG", Acronym.abbreviate('Portable Network Graphics') end def test_lowercase_words skip - assert_equal 'ROR', Acronym.abbreviate('Ruby on Rails') + assert_equal "ROR", Acronym.abbreviate('Ruby on Rails') end def test_camelcase skip - assert_equal 'HTML', Acronym.abbreviate('HyperText Markup Language') + assert_equal "HTML", Acronym.abbreviate('HyperText Markup Language') end def test_punctuation skip - assert_equal 'FIFO', Acronym.abbreviate('First In, First Out') + assert_equal "FIFO", Acronym.abbreviate('First In, First Out') end def test_all_caps_words skip - assert_equal 'PHP', Acronym.abbreviate('PHP: Hypertext Preprocessor') + assert_equal "PHP", Acronym.abbreviate('PHP: Hypertext Preprocessor') + end + + def test_non_acronym_all_caps_word + skip + assert_equal "GIMP", Acronym.abbreviate('GNU Image Manipulation Program') end def test_hyphenated skip - assert_equal 'CMOS', Acronym.abbreviate('Complementary metal-oxide semiconductor') + assert_equal "CMOS", Acronym.abbreviate('Complementary metal-oxide semiconductor') end # Problems in exercism evolve over time, as we find better ways to ask @@ -54,6 +59,6 @@ def test_hyphenated def test_bookkeeping skip - assert_equal 2, BookKeeping::VERSION + assert_equal 3, BookKeeping::VERSION end end diff --git a/exercises/acronym/example.rb b/exercises/acronym/example.rb index 321119854e..92be1b9377 100644 --- a/exercises/acronym/example.rb +++ b/exercises/acronym/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 2 + VERSION = 3 end class Acronym diff --git a/exercises/acronym/example.tt b/exercises/acronym/example.tt index 74f2aca885..b6c0e11022 100644 --- a/exercises/acronym/example.tt +++ b/exercises/acronym/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'acronym' # Common test data version: <%= abbreviated_commit_hash %> -class AcronymTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %> - assert_equal '<%= test_case.expected %>', <%= test_case.assertion %> +class AcronymTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/acronym_cases.rb b/lib/acronym_cases.rb index 3399b83655..7cfa98c46a 100644 --- a/lib/acronym_cases.rb +++ b/lib/acronym_cases.rb @@ -1,21 +1,9 @@ require 'exercise_cases' -class AcronymCase < OpenStruct - def name - 'test_%s' % description.tr(' ', '_') - end +class AcronymCase < ExerciseCase - def assertion - "Acronym.abbreviate('#{phrase}')" + def workload + assert_equal { "Acronym.abbreviate('#{phrase}')" } end - def skipped? - index > 0 - end -end - -AcronymCases = proc do |data| - JSON.parse(data)['abbreviate']['cases'].map.with_index do |row, i| - AcronymCase.new(row.merge('index' => i)) - end end From ae5a4d1c4ea3895acd39d0bfc7478de3a39115bf Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 19:10:19 -0700 Subject: [PATCH 25/61] fix alphametics generator --- exercises/alphametics/alphametics_test.rb | 3 ++- exercises/alphametics/example.tt | 1 + lib/alphametics_cases.rb | 13 +++---------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/exercises/alphametics/alphametics_test.rb b/exercises/alphametics/alphametics_test.rb index 60ebd17754..64ad8d75d2 100755 --- a/exercises/alphametics/alphametics_test.rb +++ b/exercises/alphametics/alphametics_test.rb @@ -3,7 +3,7 @@ require 'minitest/autorun' require_relative 'alphametics' -# Test data version: 9dab356 +# Common test data version: b9bada8 class AlphameticsTest < Minitest::Test def test_puzzle_with_three_letters @@ -89,6 +89,7 @@ def test_puzzle_with_ten_letters # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip assert_equal 4, BookKeeping::VERSION diff --git a/exercises/alphametics/example.tt b/exercises/alphametics/example.tt index ae98127ea3..599577165a 100644 --- a/exercises/alphametics/example.tt +++ b/exercises/alphametics/example.tt @@ -15,6 +15,7 @@ class AlphameticsTest < Minitest::Test <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/alphametics_cases.rb b/lib/alphametics_cases.rb index 7824aa4381..b99ef5f46c 100644 --- a/lib/alphametics_cases.rb +++ b/lib/alphametics_cases.rb @@ -18,7 +18,7 @@ def expect end def workload - body = + body = "input = %s\n" % input, "expected = %s\n" % expect, "assert_equal expected, Alphametics.solve(input)" @@ -27,7 +27,7 @@ def workload def runtime_comment if slow? - comments = + comments = '', "# The obvious algorithm can take a long time to solve this puzzle,\n", "# but an optimised solution can solve it fairly quickly.\n", @@ -39,7 +39,7 @@ def runtime_comment private def slow? - (expected||{}).size > 7 + (expected||{}).size > 7 end def expected_values @@ -64,10 +64,3 @@ def indent(lines, spaces) end end - -AlphameticsCases = proc do |data| - JSON.parse(data)['solve']['cases'].map.with_index do |row, i| - row = row.merge('index' => i) - AlphameticsCase.new(row) - end -end From 423dfc534038dc9ef4037623255a7f773baab56f Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 19:16:59 -0700 Subject: [PATCH 26/61] convert alphametics to use ExerciseCase --- exercises/alphametics/example.tt | 2 +- lib/alphametics_cases.rb | 26 +++++++++----------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/exercises/alphametics/example.tt b/exercises/alphametics/example.tt index 599577165a..2ab41aefbe 100644 --- a/exercises/alphametics/example.tt +++ b/exercises/alphametics/example.tt @@ -8,7 +8,7 @@ class AlphameticsTest < Minitest::Test <% test_cases.each do |test_case| %> <%= test_case.runtime_comment %> - def <%= test_case.test_name %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end diff --git a/lib/alphametics_cases.rb b/lib/alphametics_cases.rb index b99ef5f46c..16dd543c82 100644 --- a/lib/alphametics_cases.rb +++ b/lib/alphametics_cases.rb @@ -1,22 +1,6 @@ require 'exercise_cases' -class AlphameticsCase < OpenStruct - def test_name - "test_#{description.tr(' ', '_')}" - end - - def skipped - index.zero? ? '# skip' : 'skip' - end - - def input - "'#{puzzle}'" - end - - def expect - expected.nil? ? {} : expected_values - end - +class AlphameticsCase < ExerciseCase def workload body = "input = %s\n" % input, @@ -38,6 +22,14 @@ def runtime_comment private + def input + "'#{puzzle}'" + end + + def expect + expected.nil? ? {} : expected_values + end + def slow? (expected||{}).size > 7 end From 78d448bc3c18130320f9d23132be103273ac4c48 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 19:30:48 -0700 Subject: [PATCH 27/61] update and convert anagram --- exercises/anagram/.meta/.version | 2 +- exercises/anagram/anagram_test.rb | 73 +++++++++---------------------- exercises/anagram/example.rb | 2 +- exercises/anagram/example.tt | 7 ++- lib/anagram_cases.rb | 39 +---------------- 5 files changed, 29 insertions(+), 94 deletions(-) diff --git a/exercises/anagram/.meta/.version b/exercises/anagram/.meta/.version index d8263ee986..e440e5c842 100644 --- a/exercises/anagram/.meta/.version +++ b/exercises/anagram/.meta/.version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/exercises/anagram/anagram_test.rb b/exercises/anagram/anagram_test.rb index cc106de0b1..c5c3b1de3a 100755 --- a/exercises/anagram/anagram_test.rb +++ b/exercises/anagram/anagram_test.rb @@ -3,119 +3,86 @@ require 'minitest/autorun' require_relative 'anagram' -# Test data version: -# 6a886e0 +# Common test data version: 196fc1a class AnagramTest < Minitest::Test def test_no_matches # skip - detector = Anagram.new('diaper') - anagrams = detector.match(["hello", "world", "zombies", "pants"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('diaper').match(["hello", "world", "zombies", "pants"]).sort end def test_detects_simple_anagram skip - detector = Anagram.new('ant') - anagrams = detector.match(["tan", "stand", "at"]) - assert_equal ["tan"], anagrams + assert_equal ["tan"], Anagram.new('ant').match(["tan", "stand", "at"]).sort end def test_does_not_detect_false_positives skip - detector = Anagram.new('galea') - anagrams = detector.match(["eagle"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('galea').match(["eagle"]).sort end - def test_detects_multiple_anagrams + def test_detects_two_anagrams skip - detector = Anagram.new('master') - anagrams = detector.match(["stream", "pigeon", "maters"]) - assert_equal ["maters", "stream"], anagrams.sort + assert_equal ["maters", "stream"], Anagram.new('master').match(["stream", "pigeon", "maters"]).sort end def test_does_not_detect_anagram_subsets skip - detector = Anagram.new('good') - anagrams = detector.match(["dog", "goody"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('good').match(["dog", "goody"]).sort end def test_detects_anagram skip - detector = Anagram.new('listen') - anagrams = detector.match(["enlists", "google", "inlets", "banana"]) - assert_equal ["inlets"], anagrams + assert_equal ["inlets"], Anagram.new('listen').match(["enlists", "google", "inlets", "banana"]).sort end - def test_detects_multiple_anagrams + def test_detects_three_anagrams skip - detector = Anagram.new('allergy') - anagrams = detector.match(["gallery", "ballerina", "regally", "clergy", "largely", "leading"]) - assert_equal ["gallery", "largely", "regally"], anagrams.sort + assert_equal ["gallery", "largely", "regally"], Anagram.new('allergy').match(["gallery", "ballerina", "regally", "clergy", "largely", "leading"]).sort end def test_does_not_detect_identical_words skip - detector = Anagram.new('corn') - anagrams = detector.match(["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]) - assert_equal ["cron"], anagrams + assert_equal ["cron"], Anagram.new('corn').match(["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]).sort end def test_does_not_detect_non_anagrams_with_identical_checksum skip - detector = Anagram.new('mass') - anagrams = detector.match(["last"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('mass').match(["last"]).sort end def test_detects_anagrams_case_insensitively skip - detector = Anagram.new('Orchestra') - anagrams = detector.match(["cashregister", "Carthorse", "radishes"]) - assert_equal ["Carthorse"], anagrams + assert_equal ["Carthorse"], Anagram.new('Orchestra').match(["cashregister", "Carthorse", "radishes"]).sort end def test_detects_anagrams_using_case_insensitive_subject skip - detector = Anagram.new('Orchestra') - anagrams = detector.match(["cashregister", "carthorse", "radishes"]) - assert_equal ["carthorse"], anagrams + assert_equal ["carthorse"], Anagram.new('Orchestra').match(["cashregister", "carthorse", "radishes"]).sort end def test_detects_anagrams_using_case_insensitive_possible_matches skip - detector = Anagram.new('orchestra') - anagrams = detector.match(["cashregister", "Carthorse", "radishes"]) - assert_equal ["Carthorse"], anagrams + assert_equal ["Carthorse"], Anagram.new('orchestra').match(["cashregister", "Carthorse", "radishes"]).sort end def test_does_not_detect_a_word_as_its_own_anagram skip - detector = Anagram.new('banana') - anagrams = detector.match(["Banana"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('banana').match(["Banana"]).sort end def test_does_not_detect_a_anagram_if_the_original_word_is_repeated skip - detector = Anagram.new('go') - anagrams = detector.match(["go Go GO"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('go').match(["go Go GO"]).sort end def test_anagrams_must_use_all_letters_exactly_once skip - detector = Anagram.new('tapper') - anagrams = detector.match(["patter"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('tapper').match(["patter"]).sort end def test_capital_word_is_not_own_anagram skip - detector = Anagram.new('BANANA') - anagrams = detector.match(["Banana"]) - assert_equal [], anagrams + assert_equal [], Anagram.new('BANANA').match(["Banana"]).sort end # Problems in exercism evolve over time, as we find better ways to ask @@ -137,6 +104,6 @@ def test_capital_word_is_not_own_anagram def test_bookkeeping skip - assert_equal 2, BookKeeping::VERSION + assert_equal 3, BookKeeping::VERSION end end diff --git a/exercises/anagram/example.rb b/exercises/anagram/example.rb index c6ba632cff..13e88bc171 100644 --- a/exercises/anagram/example.rb +++ b/exercises/anagram/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION=2 + VERSION = 3 end class Anagram diff --git a/exercises/anagram/example.tt b/exercises/anagram/example.tt index 85f1e70d66..7430cbf537 100644 --- a/exercises/anagram/example.tt +++ b/exercises/anagram/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'anagram' # Common test data version: <%= abbreviated_commit_hash %> -class AnagramTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class AnagramTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/anagram_cases.rb b/lib/anagram_cases.rb index 79e970f1f6..0a6de9204a 100644 --- a/lib/anagram_cases.rb +++ b/lib/anagram_cases.rb @@ -1,44 +1,9 @@ require 'exercise_cases' -class AnagramCase < OpenStruct - def test_name - 'test_%s' % description.gsub(/[ -]/, '_') - end +class AnagramCase < ExerciseCase def workload - indent_lines([show_comment, detector, anagram, assert].compact) - end - - def skipped - index.zero? ? '# skip' : 'skip' - end - - private - - def indent_lines(code, indent = 2) - code.join("\n" + ' '*2*indent) - end - - def show_comment - "# #{comment}" unless comment.nil? + %Q(assert_equal #{expected.sort}, Anagram.new('#{subject}').match(#{candidates}).sort) end - def detector - "detector = Anagram.new('#{subject}')" - end - - def anagram - "anagrams = detector.match(#{candidates})" - end - - def assert - actual = expected.size > 1 ? 'anagrams.sort' : 'anagrams' - "assert_equal #{expected.sort}, #{actual}" - end -end - -AnagramCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - AnagramCase.new(row.merge('index' => i)) - end end From be4c5287e8c31b67be4c89ded3e7d3e57d8e972e Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Sun, 23 Apr 2017 19:49:42 -0700 Subject: [PATCH 28/61] convert beer-song --- exercises/beer-song/beer_song_test.rb | 1 + exercises/beer-song/example.tt | 10 +++++---- lib/beer_song_cases.rb | 31 ++++++--------------------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/exercises/beer-song/beer_song_test.rb b/exercises/beer-song/beer_song_test.rb index 4bbc0dee99..ed0c8a99b4 100755 --- a/exercises/beer-song/beer_song_test.rb +++ b/exercises/beer-song/beer_song_test.rb @@ -383,6 +383,7 @@ def test_all_verses TEXT assert_equal expected, BeerSong.new.verses(99, 0) end + # Problems in exercism evolve over time, as we find better ways to ask # questions. # The version number refers to the version of the problem you solved, diff --git a/exercises/beer-song/example.tt b/exercises/beer-song/example.tt index 0827d1a20d..ee61904db6 100644 --- a/exercises/beer-song/example.tt +++ b/exercises/beer-song/example.tt @@ -5,14 +5,16 @@ require 'minitest/autorun' require_relative 'beer_song' # Common test data version: <%= abbreviated_commit_hash %> -class BeerSongTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class BeerSongTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> expected = <<-TEXT <%= test_case.expected %> - TEXT - assert_equal expected, <%= test_case.workload %> +TEXT + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> def test_bookkeeping diff --git a/lib/beer_song_cases.rb b/lib/beer_song_cases.rb index d3111e51e1..156f476396 100644 --- a/lib/beer_song_cases.rb +++ b/lib/beer_song_cases.rb @@ -1,25 +1,22 @@ require 'exercise_cases' -class BeerSongCase < OpenStruct - def test_name - 'test_%s' % description.tr(' ', '_') - end +class BeerSongCase < ExerciseCase def workload - "BeerSong.new.%s(%s)" % [property, workload_arguments] + "assert_equal expected, #{beer_song}" end def expected self["expected"].gsub('\n', '"\n" \\') end - def skipped - index.zero? ? '# skip' : 'skip' - end - private - def workload_arguments + def beer_song + "BeerSong.new.%s(%s)" % [property, beer_song_arguments] + end + + def beer_song_arguments if property == 'verse' number else @@ -27,17 +24,3 @@ def workload_arguments end end end - -BeerSongCases = proc do |data| - i = 0 - cases = [] - JSON.parse(data)["cases"].each do |section| - section["cases"].each do |tests| - tests["cases"].each do |test| - cases << BeerSongCase.new(test.merge('index' => i)) - i += 1 - end - end - end - cases -end From 28c3161d95ba1611237395f0321c958f407e14a2 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Mon, 24 Apr 2017 15:37:29 -0700 Subject: [PATCH 29/61] revert unnecessary anagram version bump --- exercises/anagram/.meta/.version | 2 +- exercises/anagram/anagram_test.rb | 2 +- exercises/anagram/example.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/anagram/.meta/.version b/exercises/anagram/.meta/.version index e440e5c842..d8263ee986 100644 --- a/exercises/anagram/.meta/.version +++ b/exercises/anagram/.meta/.version @@ -1 +1 @@ -3 \ No newline at end of file +2 \ No newline at end of file diff --git a/exercises/anagram/anagram_test.rb b/exercises/anagram/anagram_test.rb index c5c3b1de3a..e300fe0595 100755 --- a/exercises/anagram/anagram_test.rb +++ b/exercises/anagram/anagram_test.rb @@ -104,6 +104,6 @@ def test_capital_word_is_not_own_anagram def test_bookkeeping skip - assert_equal 3, BookKeeping::VERSION + assert_equal 2, BookKeeping::VERSION end end diff --git a/exercises/anagram/example.rb b/exercises/anagram/example.rb index 13e88bc171..3d633ba475 100644 --- a/exercises/anagram/example.rb +++ b/exercises/anagram/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 3 + VERSION = 2 end class Anagram From a816e0b80ee1b272d5bb8add0bb4565d135ebe2a Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 14:25:16 -0700 Subject: [PATCH 30/61] convert anagram workload to four line --- exercises/anagram/anagram_test.rb | 80 ++++++++++++++++++++++++------- lib/anagram_cases.rb | 29 ++++++++++- 2 files changed, 92 insertions(+), 17 deletions(-) diff --git a/exercises/anagram/anagram_test.rb b/exercises/anagram/anagram_test.rb index e300fe0595..22a5f71411 100755 --- a/exercises/anagram/anagram_test.rb +++ b/exercises/anagram/anagram_test.rb @@ -7,82 +7,130 @@ class AnagramTest < Minitest::Test def test_no_matches # skip - assert_equal [], Anagram.new('diaper').match(["hello", "world", "zombies", "pants"]).sort + detector = Anagram.new('diaper') + anagrams = detector.match(["hello", "world", "zombies", "pants"]) + expected = [] + assert_equal expected, anagrams end def test_detects_simple_anagram skip - assert_equal ["tan"], Anagram.new('ant').match(["tan", "stand", "at"]).sort + detector = Anagram.new('ant') + anagrams = detector.match(["tan", "stand", "at"]) + expected = ["tan"] + assert_equal expected, anagrams end def test_does_not_detect_false_positives skip - assert_equal [], Anagram.new('galea').match(["eagle"]).sort + detector = Anagram.new('galea') + anagrams = detector.match(["eagle"]) + expected = [] + assert_equal expected, anagrams end def test_detects_two_anagrams skip - assert_equal ["maters", "stream"], Anagram.new('master').match(["stream", "pigeon", "maters"]).sort + detector = Anagram.new('master') + anagrams = detector.match(["stream", "pigeon", "maters"]) + expected = ["maters", "stream"] + assert_equal expected, anagrams.sort end def test_does_not_detect_anagram_subsets skip - assert_equal [], Anagram.new('good').match(["dog", "goody"]).sort + detector = Anagram.new('good') + anagrams = detector.match(["dog", "goody"]) + expected = [] + assert_equal expected, anagrams end def test_detects_anagram skip - assert_equal ["inlets"], Anagram.new('listen').match(["enlists", "google", "inlets", "banana"]).sort + detector = Anagram.new('listen') + anagrams = detector.match(["enlists", "google", "inlets", "banana"]) + expected = ["inlets"] + assert_equal expected, anagrams end def test_detects_three_anagrams skip - assert_equal ["gallery", "largely", "regally"], Anagram.new('allergy').match(["gallery", "ballerina", "regally", "clergy", "largely", "leading"]).sort + detector = Anagram.new('allergy') + anagrams = detector.match(["gallery", "ballerina", "regally", "clergy", "largely", "leading"]) + expected = ["gallery", "largely", "regally"] + assert_equal expected, anagrams.sort end def test_does_not_detect_identical_words skip - assert_equal ["cron"], Anagram.new('corn').match(["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]).sort + detector = Anagram.new('corn') + anagrams = detector.match(["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]) + expected = ["cron"] + assert_equal expected, anagrams end def test_does_not_detect_non_anagrams_with_identical_checksum skip - assert_equal [], Anagram.new('mass').match(["last"]).sort + detector = Anagram.new('mass') + anagrams = detector.match(["last"]) + expected = [] + assert_equal expected, anagrams end def test_detects_anagrams_case_insensitively skip - assert_equal ["Carthorse"], Anagram.new('Orchestra').match(["cashregister", "Carthorse", "radishes"]).sort + detector = Anagram.new('Orchestra') + anagrams = detector.match(["cashregister", "Carthorse", "radishes"]) + expected = ["Carthorse"] + assert_equal expected, anagrams end def test_detects_anagrams_using_case_insensitive_subject skip - assert_equal ["carthorse"], Anagram.new('Orchestra').match(["cashregister", "carthorse", "radishes"]).sort + detector = Anagram.new('Orchestra') + anagrams = detector.match(["cashregister", "carthorse", "radishes"]) + expected = ["carthorse"] + assert_equal expected, anagrams end def test_detects_anagrams_using_case_insensitive_possible_matches skip - assert_equal ["Carthorse"], Anagram.new('orchestra').match(["cashregister", "Carthorse", "radishes"]).sort + detector = Anagram.new('orchestra') + anagrams = detector.match(["cashregister", "Carthorse", "radishes"]) + expected = ["Carthorse"] + assert_equal expected, anagrams end def test_does_not_detect_a_word_as_its_own_anagram skip - assert_equal [], Anagram.new('banana').match(["Banana"]).sort + detector = Anagram.new('banana') + anagrams = detector.match(["Banana"]) + expected = [] + assert_equal expected, anagrams end def test_does_not_detect_a_anagram_if_the_original_word_is_repeated skip - assert_equal [], Anagram.new('go').match(["go Go GO"]).sort + detector = Anagram.new('go') + anagrams = detector.match(["go Go GO"]) + expected = [] + assert_equal expected, anagrams end def test_anagrams_must_use_all_letters_exactly_once skip - assert_equal [], Anagram.new('tapper').match(["patter"]).sort + detector = Anagram.new('tapper') + anagrams = detector.match(["patter"]) + expected = [] + assert_equal expected, anagrams end def test_capital_word_is_not_own_anagram skip - assert_equal [], Anagram.new('BANANA').match(["Banana"]).sort + detector = Anagram.new('BANANA') + anagrams = detector.match(["Banana"]) + expected = [] + assert_equal expected, anagrams end # Problems in exercism evolve over time, as we find better ways to ask diff --git a/lib/anagram_cases.rb b/lib/anagram_cases.rb index 0a6de9204a..e6d07dcf0c 100644 --- a/lib/anagram_cases.rb +++ b/lib/anagram_cases.rb @@ -3,7 +3,34 @@ class AnagramCase < ExerciseCase def workload - %Q(assert_equal #{expected.sort}, Anagram.new('#{subject}').match(#{candidates}).sort) + indent_lines([show_comment, detector, anagram, wanted, assert].compact) + end + + private + + def indent_lines(code, indent = 2) + code.join("\n" + ' '*2*indent) + end + + def show_comment + "# #{comment}" unless comment.nil? + end + + def detector + "detector = Anagram.new('#{subject}')" + end + + def anagram + "anagrams = detector.match(#{candidates})" + end + + def wanted + "expected = #{expected.sort}" + end + + def assert + actual = expected.size > 1 ? 'anagrams.sort' : 'anagrams' + "assert_equal expected, #{actual}" end end From 7d6ab33c5e3fb0b56d1ed15da409f3ac31552c29 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 14:38:31 -0700 Subject: [PATCH 31/61] convert (and fix) two-bucket generator --- exercises/two-bucket/example.tt | 11 +++++++---- exercises/two-bucket/two_bucket_test.rb | 18 +++++++++--------- lib/two_bucket_cases.rb | 24 +++++++----------------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/exercises/two-bucket/example.tt b/exercises/two-bucket/example.tt index 06328aadaa..30a412c249 100644 --- a/exercises/two-bucket/example.tt +++ b/exercises/two-bucket/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'two_bucket' # Common test data version: <%= abbreviated_commit_hash %> -class TwoBucketTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %><% if test_case.skipped? %> - skip<% end %> - <%= test_case.test_body %> +class TwoBucketTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/two-bucket/two_bucket_test.rb b/exercises/two-bucket/two_bucket_test.rb index 62fcb62104..fe8fa8732e 100755 --- a/exercises/two-bucket/two_bucket_test.rb +++ b/exercises/two-bucket/two_bucket_test.rb @@ -3,18 +3,17 @@ require 'minitest/autorun' require_relative 'two_bucket' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: 7aa0b42 class TwoBucketTest < Minitest::Test - def test_bucket_one_3_bucket_two_5_goal_1_starting_one + def test_bucket_one_size_3_bucket_two_size_5_goal_1_start_with_bucket_one + # skip two_bucket = TwoBucket.new(3, 5, 1, 'one') assert_equal 4, two_bucket.moves assert_equal 'one', two_bucket.goal_bucket assert_equal 5, two_bucket.other_bucket end - def test_bucket_one_3_bucket_two_5_goal_1_starting_two + def test_bucket_one_size_3_bucket_two_size_5_goal_1_start_with_bucket_two skip two_bucket = TwoBucket.new(3, 5, 1, 'two') assert_equal 8, two_bucket.moves @@ -22,7 +21,7 @@ def test_bucket_one_3_bucket_two_5_goal_1_starting_two assert_equal 3, two_bucket.other_bucket end - def test_bucket_one_7_bucket_two_11_goal_2_starting_one + def test_bucket_one_size_7_bucket_two_size_11_goal_2_start_with_bucket_one skip two_bucket = TwoBucket.new(7, 11, 2, 'one') assert_equal 14, two_bucket.moves @@ -30,7 +29,7 @@ def test_bucket_one_7_bucket_two_11_goal_2_starting_one assert_equal 11, two_bucket.other_bucket end - def test_bucket_one_7_bucket_two_11_goal_2_starting_two + def test_bucket_one_size_7_bucket_two_size_11_goal_2_start_with_bucket_two skip two_bucket = TwoBucket.new(7, 11, 2, 'two') assert_equal 18, two_bucket.moves @@ -44,8 +43,9 @@ def test_bucket_one_7_bucket_two_11_goal_2_starting_two # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. diff --git a/lib/two_bucket_cases.rb b/lib/two_bucket_cases.rb index c1350552f7..548f4b9071 100644 --- a/lib/two_bucket_cases.rb +++ b/lib/two_bucket_cases.rb @@ -1,30 +1,20 @@ require 'exercise_cases' -class TwoBucketCase < OpenStruct - def test_name - "test_bucket_one_#{bucket_one}_bucket_two_"\ - "#{bucket_two}_goal_#{goal}_starting_#{start_bucket}" +class TwoBucketCase < ExerciseCase + def name + "test_bucket_one_size_#{bucket_one}_bucket_two_"\ + "size_#{bucket_two}_goal_#{goal}_start_with_bucket_#{start_bucket}" end - def do - "TwoBucket.new(#{bucket_one}, #{bucket_two}, #{goal}, '#{start_bucket}')" - end - - def test_body + def workload "two_bucket = #{self.do} assert_equal #{expected['moves']}, two_bucket.moves assert_equal '#{expected['goal_bucket']}', two_bucket.goal_bucket assert_equal #{expected['other_bucket']}, two_bucket.other_bucket" end - def skipped? - index > 0 + def do + "TwoBucket.new(#{bucket_one}, #{bucket_two}, #{goal}, '#{start_bucket}')" end -end -TwoBucketCases = proc do |data| - JSON.parse(data)['two_bucket']['cases'].map.with_index do |row, i| - row = row.merge('index' => i) - TwoBucketCase.new(row) - end end From 3f9d7d3fca3c37cd65066a118a5c7df05e74c1ac Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 15:16:02 -0700 Subject: [PATCH 32/61] convert (and fix) bowling generator --- exercises/bowling/bowling_test.rb | 79 +++++++++++++++---------------- exercises/bowling/example.tt | 4 +- lib/bowling_cases.rb | 48 +++++++++---------- 3 files changed, 65 insertions(+), 66 deletions(-) diff --git a/exercises/bowling/bowling_test.rb b/exercises/bowling/bowling_test.rb index e8a257c166..7ed3eb50fb 100755 --- a/exercises/bowling/bowling_test.rb +++ b/exercises/bowling/bowling_test.rb @@ -3,207 +3,206 @@ require 'minitest/autorun' require_relative 'bowling' -# Test data version: c59c2c4 -# +# Common test data version: 3cf5eb9 class BowlingTest < Minitest::Test def setup @game = Game.new end - def roll(rolls) + def record(rolls) rolls.each { |pins| @game.roll(pins) } end def test_should_be_able_to_score_a_game_with_all_zeros # skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 0, @game.score end def test_should_be_able_to_score_a_game_with_no_strikes_or_spares skip - roll([3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6]) + record([3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6]) assert_equal 90, @game.score end def test_a_spare_followed_by_zeros_is_worth_ten_points skip - roll([6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 10, @game.score end def test_points_scored_in_the_roll_after_a_spare_are_counted_twice skip - roll([6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 16, @game.score end def test_consecutive_spares_each_get_a_one_roll_bonus skip - roll([5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 31, @game.score end def test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7]) assert_equal 17, @game.score end def test_a_strike_earns_ten_points_in_a_frame_with_a_single_roll skip - roll([10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 10, @game.score end def test_points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus skip - roll([10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 26, @game.score end def test_consecutive_strikes_each_get_the_two_roll_bonus skip - roll([10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + record([10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_equal 81, @game.score end def test_a_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1]) assert_equal 18, @game.score end def test_rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3]) assert_equal 20, @game.score end def test_strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10]) assert_equal 30, @game.score end def test_a_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10]) assert_equal 20, @game.score end def test_all_strikes_is_a_perfect_game skip - roll([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]) + record([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]) assert_equal 300, @game.score end def test_rolls_can_not_score_negative_points skip + record([]) assert_raises Game::BowlingError do - roll([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - @game.score + @game.roll(-1) end end def test_a_roll_can_not_score_more_than_10_points skip + record([]) assert_raises Game::BowlingError do - roll([11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - @game.score + @game.roll(11) end end def test_two_rolls_in_a_frame_can_not_score_more_than_10_points skip + record([5]) assert_raises Game::BowlingError do - roll([5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - @game.score + @game.roll(6) end end def test_bonus_roll_after_a_strike_in_the_last_frame_can_not_score_more_than_10_points skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11]) - @game.score + @game.roll(11) end end def test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_not_score_more_than_10_points skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6]) - @game.score + @game.roll(6) end end def test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike skip - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6]) + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6]) assert_equal 26, @game.score end def test_the_second_bonus_rolls_after_a_strike_in_the_last_frame_can_not_be_a_strike_if_the_first_one_is_not_a_strike skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 10]) - @game.score + @game.roll(10) end end def test_second_bonus_roll_after_a_strike_in_the_last_frame_can_not_score_than_10_points skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 11]) - @game.score + @game.roll(11) end end def test_an_unstarted_game_can_not_be_scored skip + record([]) assert_raises Game::BowlingError do - roll([]) @game.score end end def test_an_incomplete_game_can_not_be_scored skip + record([0, 0]) assert_raises Game::BowlingError do - roll([0, 0]) @game.score end end - def test_a_game_with_more_than_ten_frames_can_not_be_scored + def test_cannot_roll_if_game_already_has_ten_frames skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - @game.score + @game.roll(0) end end def test_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10]) @game.score end end def test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10]) @game.score end end def test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated skip + record([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3]) assert_raises Game::BowlingError do - roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3]) @game.score end end diff --git a/exercises/bowling/example.tt b/exercises/bowling/example.tt index ff04d7e256..dd5c29e766 100644 --- a/exercises/bowling/example.tt +++ b/exercises/bowling/example.tt @@ -9,12 +9,12 @@ class BowlingTest < Minitest::Test @game = Game.new end - def roll(rolls) + def record(rolls) rolls.each { |pins| @game.roll(pins) } end <% test_cases.each do |test_case| %> - def <%= test_case.test_name %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end diff --git a/lib/bowling_cases.rb b/lib/bowling_cases.rb index 8a6a732f02..e0773c47ce 100644 --- a/lib/bowling_cases.rb +++ b/lib/bowling_cases.rb @@ -1,13 +1,6 @@ require 'exercise_cases' -class BowlingCase < OpenStruct - def test_name - "test_#{description.downcase.tr(' ', '_')}" - end - - def skipped - index.zero? ? '# skip' : 'skip' - end +class BowlingCase < ExerciseCase def workload indent_lines(assert) @@ -15,34 +8,41 @@ def workload private - def roll - "roll(#{rolls})" + def roll_previous + "record(#{previous_rolls})" end def assert if assert_error? - [ - 'assert_raises Game::BowlingError do', - " #{roll}", - ' @game.score', - 'end' - ] + property == 'score' ? score_raises : roll_raises else - [roll, "assert_equal #{expected}, @game.score"] + [roll_previous, "assert_equal #{expected}, @game.score"] end end + def roll_raises + [ + roll_previous, + 'assert_raises Game::BowlingError do', + ' @game.roll(' + roll.to_s + ')', + 'end' + ] + end + + def score_raises + [ + roll_previous, + 'assert_raises Game::BowlingError do', + ' @game.score', + 'end' + ] + end + def assert_error? - expected == -1 + expected.respond_to?(:key?) && expected.key?('error') end def indent_lines(code) code.join("\n" + ' ' * 4) end end - -BowlingCases = proc do |data| - JSON.parse(data)['score']['cases'].map.with_index do |row, i| - BowlingCase.new(row.merge('index' => i)) - end -end From 2983e26c602101211541b18ccba9c371be4c78d3 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 16:06:14 -0700 Subject: [PATCH 33/61] convert bracket-push --- exercises/bracket-push/.meta/.version | 2 +- exercises/bracket-push/bracket_push_test.rb | 10 +++++--- exercises/bracket-push/example.rb | 2 +- exercises/bracket-push/example.tt | 7 ++++-- lib/bracket_push_cases.rb | 27 +++++---------------- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/exercises/bracket-push/.meta/.version b/exercises/bracket-push/.meta/.version index e440e5c842..bf0d87ab1b 100644 --- a/exercises/bracket-push/.meta/.version +++ b/exercises/bracket-push/.meta/.version @@ -1 +1 @@ -3 \ No newline at end of file +4 \ No newline at end of file diff --git a/exercises/bracket-push/bracket_push_test.rb b/exercises/bracket-push/bracket_push_test.rb index 852250a835..454407adce 100755 --- a/exercises/bracket-push/bracket_push_test.rb +++ b/exercises/bracket-push/bracket_push_test.rb @@ -3,8 +3,7 @@ require 'minitest/autorun' require_relative 'bracket_push' -# Test data version: -# 306975e +# Common test data version: 855c591 class BracketsTest < Minitest::Test def test_paired_square_brackets # skip @@ -26,6 +25,11 @@ def test_wrong_ordered_brackets refute Brackets.paired?('}{') end + def test_wrong_closing_bracket + skip + refute Brackets.paired?('{]') + end + def test_paired_with_whitespace skip assert Brackets.paired?('{ }') @@ -92,6 +96,6 @@ def test_complex_latex_expression def test_bookkeeping skip - assert_equal 3, BookKeeping::VERSION + assert_equal 4, BookKeeping::VERSION end end diff --git a/exercises/bracket-push/example.rb b/exercises/bracket-push/example.rb index 4a27258fa4..453715787a 100644 --- a/exercises/bracket-push/example.rb +++ b/exercises/bracket-push/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 3 + VERSION = 4 end module Brackets diff --git a/exercises/bracket-push/example.tt b/exercises/bracket-push/example.tt index f6c41d329c..c848e9c86d 100644 --- a/exercises/bracket-push/example.tt +++ b/exercises/bracket-push/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'bracket_push' # Common test data version: <%= abbreviated_commit_hash %> -class BracketsTest < Minitest::Test<% test_cases.each do |test_case| %> +class BracketsTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> <%= test_case.skipped %> - <%= test_case.test_body %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/bracket_push_cases.rb b/lib/bracket_push_cases.rb index 52c8ce6941..b4a6e0aa34 100644 --- a/lib/bracket_push_cases.rb +++ b/lib/bracket_push_cases.rb @@ -1,43 +1,28 @@ require 'exercise_cases' -class BracketPushCase < OpenStruct - def name - 'test_%s' % description.gsub(/[ -]/, '_') - end - - def skipped - index.zero? ? '# skip' : 'skip' - end +class BracketPushCase < ExerciseCase - def test_body + def workload long_input? ? split_test : simple_test end + private + def long_input? input.length > 80 end def simple_test - "#{assert_or_refute} Brackets.paired?('#{input}')" + "#{assert} Brackets.paired?('#{input}')" end def split_test "str = '#{split_input[0]}'\\ '#{split_input[1]}' - #{assert_or_refute} Brackets.paired?(str)" - end - - def assert_or_refute - expected ? 'assert' : 'refute' + #{assert} Brackets.paired?(str)" end def split_input @split_input ||= input.scan(/.{1,#{input.length / 2}}/) end end - -BracketPushCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - BracketPushCase.new(row.merge('index' => i)) - end -end From 372f0b69f57552675594f4654f0def53bf87fc70 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 16:12:48 -0700 Subject: [PATCH 34/61] convert clock --- exercises/clock/clock_test.rb | 81 +++++++++++++++++------------------ exercises/clock/example.tt | 7 ++- lib/clock_cases.rb | 31 +++----------- 3 files changed, 51 insertions(+), 68 deletions(-) diff --git a/exercises/clock/clock_test.rb b/exercises/clock/clock_test.rb index 4534f5f40a..03f7b703d0 100755 --- a/exercises/clock/clock_test.rb +++ b/exercises/clock/clock_test.rb @@ -3,183 +3,181 @@ require 'minitest/autorun' require_relative 'clock' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: 8c7fc0c class ClockTest < Minitest::Test def test_on_the_hour # skip - assert_equal '08:00', Clock.at(8, 0).to_s + assert_equal "08:00", Clock.at(8, 0).to_s end def test_past_the_hour skip - assert_equal '11:09', Clock.at(11, 9).to_s + assert_equal "11:09", Clock.at(11, 9).to_s end def test_midnight_is_zero_hours skip - assert_equal '00:00', Clock.at(24, 0).to_s + assert_equal "00:00", Clock.at(24, 0).to_s end def test_hour_rolls_over skip - assert_equal '01:00', Clock.at(25, 0).to_s + assert_equal "01:00", Clock.at(25, 0).to_s end def test_hour_rolls_over_continuously skip - assert_equal '04:00', Clock.at(100, 0).to_s + assert_equal "04:00", Clock.at(100, 0).to_s end def test_sixty_minutes_is_next_hour skip - assert_equal '02:00', Clock.at(1, 60).to_s + assert_equal "02:00", Clock.at(1, 60).to_s end def test_minutes_roll_over skip - assert_equal '02:40', Clock.at(0, 160).to_s + assert_equal "02:40", Clock.at(0, 160).to_s end def test_minutes_roll_over_continuously skip - assert_equal '04:43', Clock.at(0, 1723).to_s + assert_equal "04:43", Clock.at(0, 1723).to_s end def test_hour_and_minutes_roll_over skip - assert_equal '03:40', Clock.at(25, 160).to_s + assert_equal "03:40", Clock.at(25, 160).to_s end def test_hour_and_minutes_roll_over_continuously skip - assert_equal '11:01', Clock.at(201, 3001).to_s + assert_equal "11:01", Clock.at(201, 3001).to_s end def test_hour_and_minutes_roll_over_to_exactly_midnight skip - assert_equal '00:00', Clock.at(72, 8640).to_s + assert_equal "00:00", Clock.at(72, 8640).to_s end def test_negative_hour skip - assert_equal '23:15', Clock.at(-1, 15).to_s + assert_equal "23:15", Clock.at(-1, 15).to_s end def test_negative_hour_rolls_over skip - assert_equal '23:00', Clock.at(-25, 0).to_s + assert_equal "23:00", Clock.at(-25, 0).to_s end def test_negative_hour_rolls_over_continuously skip - assert_equal '05:00', Clock.at(-91, 0).to_s + assert_equal "05:00", Clock.at(-91, 0).to_s end def test_negative_minutes skip - assert_equal '00:20', Clock.at(1, -40).to_s + assert_equal "00:20", Clock.at(1, -40).to_s end def test_negative_minutes_roll_over skip - assert_equal '22:20', Clock.at(1, -160).to_s + assert_equal "22:20", Clock.at(1, -160).to_s end def test_negative_minutes_roll_over_continuously skip - assert_equal '16:40', Clock.at(1, -4820).to_s + assert_equal "16:40", Clock.at(1, -4820).to_s end def test_negative_hour_and_minutes_both_roll_over skip - assert_equal '20:20', Clock.at(-25, -160).to_s + assert_equal "20:20", Clock.at(-25, -160).to_s end def test_negative_hour_and_minutes_both_roll_over_continuously skip - assert_equal '22:10', Clock.at(-121, -5810).to_s + assert_equal "22:10", Clock.at(-121, -5810).to_s end def test_add_minutes skip - assert_equal '10:03', (Clock.at(10, 0) + 3).to_s + assert_equal "10:03", (Clock.at(10, 0) + 3).to_s end def test_add_no_minutes skip - assert_equal '06:41', (Clock.at(6, 41) + 0).to_s + assert_equal "06:41", (Clock.at(6, 41) + 0).to_s end def test_add_to_next_hour skip - assert_equal '01:25', (Clock.at(0, 45) + 40).to_s + assert_equal "01:25", (Clock.at(0, 45) + 40).to_s end def test_add_more_than_one_hour skip - assert_equal '11:01', (Clock.at(10, 0) + 61).to_s + assert_equal "11:01", (Clock.at(10, 0) + 61).to_s end def test_add_more_than_two_hours_with_carry skip - assert_equal '03:25', (Clock.at(0, 45) + 160).to_s + assert_equal "03:25", (Clock.at(0, 45) + 160).to_s end def test_add_across_midnight skip - assert_equal '00:01', (Clock.at(23, 59) + 2).to_s + assert_equal "00:01", (Clock.at(23, 59) + 2).to_s end def test_add_more_than_one_day__1500_min_is_equal_to_25_hrs skip - assert_equal '06:32', (Clock.at(5, 32) + 1500).to_s + assert_equal "06:32", (Clock.at(5, 32) + 1500).to_s end def test_add_more_than_two_days skip - assert_equal '11:21', (Clock.at(1, 1) + 3500).to_s + assert_equal "11:21", (Clock.at(1, 1) + 3500).to_s end def test_subtract_minutes skip - assert_equal '10:00', (Clock.at(10, 3) + -3).to_s + assert_equal "10:00", (Clock.at(10, 3) + -3).to_s end def test_subtract_to_previous_hour skip - assert_equal '09:33', (Clock.at(10, 3) + -30).to_s + assert_equal "09:33", (Clock.at(10, 3) + -30).to_s end def test_subtract_more_than_an_hour skip - assert_equal '08:53', (Clock.at(10, 3) + -70).to_s + assert_equal "08:53", (Clock.at(10, 3) + -70).to_s end def test_subtract_across_midnight skip - assert_equal '23:59', (Clock.at(0, 3) + -4).to_s + assert_equal "23:59", (Clock.at(0, 3) + -4).to_s end def test_subtract_more_than_two_hours skip - assert_equal '21:20', (Clock.at(0, 0) + -160).to_s + assert_equal "21:20", (Clock.at(0, 0) + -160).to_s end def test_subtract_more_than_two_hours_with_borrow skip - assert_equal '03:35', (Clock.at(6, 15) + -160).to_s + assert_equal "03:35", (Clock.at(6, 15) + -160).to_s end def test_subtract_more_than_one_day__1500_min_is_equal_to_25_hrs skip - assert_equal '04:32', (Clock.at(5, 32) + -1500).to_s + assert_equal "04:32", (Clock.at(5, 32) + -1500).to_s end def test_subtract_more_than_two_days skip - assert_equal '00:20', (Clock.at(2, 20) + -3000).to_s + assert_equal "00:20", (Clock.at(2, 20) + -3000).to_s end def test_clocks_with_same_time @@ -283,7 +281,7 @@ def test_clocks_with_negative_hours_and_minutes def test_clocks_with_negative_hours_and_minutes_that_wrap skip clock1 = Clock.at(18, 7) - clock2 = Clock.at(-54, -11_513) + clock2 = Clock.at(-54, -11513) assert clock1 == clock2 end @@ -293,8 +291,9 @@ def test_clocks_with_negative_hours_and_minutes_that_wrap # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. diff --git a/exercises/clock/example.tt b/exercises/clock/example.tt index c52ce99610..9f09fb7410 100644 --- a/exercises/clock/example.tt +++ b/exercises/clock/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'clock' # Common test data version: <%= abbreviated_commit_hash %> -class ClockTest < Minitest::Test<% test_cases.each do |test_case| %> +class ClockTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> <%= test_case.skipped %> - <%= test_case.test_body %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/clock_cases.rb b/lib/clock_cases.rb index bc09e811b0..feed3a528e 100644 --- a/lib/clock_cases.rb +++ b/lib/clock_cases.rb @@ -1,6 +1,6 @@ require 'exercise_cases' -class ClockCase < OpenStruct +class ClockCase < ExerciseCase def name 'test_%s' % description .gsub(/[() -]/, '_') @@ -8,14 +8,16 @@ def name .chomp('_') end - def test_body - section == 'equal' ? compare_clocks : simple_test + def workload + property == 'equal' ? compare_clocks : simple_test end + private + def compare_clocks "clock1 = Clock.at(#{clock1['hour']}, #{clock1['minute']}) clock2 = Clock.at(#{clock2['hour']}, #{clock2['minute']}) - #{assert_or_refute} clock1 == clock2" + #{assert} clock1 == clock2" end def simple_test @@ -26,29 +28,8 @@ def simple_test ].join end - def assert_or_refute - expected ? 'assert' : 'refute' - end - def add_to_clock " + #{add}" if add end - def skipped - index.zero? ? '# skip' : 'skip' - end -end - -ClockCases = proc do |data| - i = 0 - json = JSON.parse(data) - cases = [] - %w(create add equal).each do |section| - json[section]['cases'].each do |row| - row = row.merge(row.merge('index' => i, 'section' => section)) - cases << ClockCase.new(row) - i += 1 - end - end - cases end From 0f35d9130f897cb4d5e1ff2a43b86d14810bae64 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 16:18:37 -0700 Subject: [PATCH 35/61] convert (and update) connect --- exercises/connect/.meta/.version | 2 +- exercises/connect/connect_test.rb | 23 ++++++++++++++++++++--- exercises/connect/example.rb | 2 +- exercises/connect/example.tt | 4 +++- lib/connect_cases.rb | 22 ++-------------------- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/exercises/connect/.meta/.version b/exercises/connect/.meta/.version index 56a6051ca2..d8263ee986 100644 --- a/exercises/connect/.meta/.version +++ b/exercises/connect/.meta/.version @@ -1 +1 @@ -1 \ No newline at end of file +2 \ No newline at end of file diff --git a/exercises/connect/connect_test.rb b/exercises/connect/connect_test.rb index a517fe948f..a8d702cc8f 100755 --- a/exercises/connect/connect_test.rb +++ b/exercises/connect/connect_test.rb @@ -3,7 +3,7 @@ require 'minitest/autorun' require_relative 'connect' -# Test data version commit id: 6c6a395 +# Common test data version: 327db7f class ConnectTest < Minitest::Test def test_an_empty_board_has_no_winner # skip @@ -18,6 +18,24 @@ def test_an_empty_board_has_no_winner assert_equal '', game.winner, 'an empty board has no winner' end + def test_x_can_win_on_a_1x1_board + skip + board = [ + 'X' + ] + game = Board.new(board) + assert_equal 'X', game.winner, 'X can win on a 1x1 board' + end + + def test_o_can_win_on_a_1x1_board + skip + board = [ + 'O' + ] + game = Board.new(board) + assert_equal 'O', game.winner, 'O can win on a 1x1 board' + end + def test_only_edges_does_not_make_a_winner skip board = [ @@ -128,9 +146,8 @@ def test_x_wins_using_a_spiral_path # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html - def test_bookkeeping skip - assert_equal 1, BookKeeping::VERSION + assert_equal 2, BookKeeping::VERSION end end diff --git a/exercises/connect/example.rb b/exercises/connect/example.rb index a6a6268156..8b1e075361 100644 --- a/exercises/connect/example.rb +++ b/exercises/connect/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 1 + VERSION = 2 end Position = Struct.new(:x, :y) class Board diff --git a/exercises/connect/example.tt b/exercises/connect/example.tt index be21a744e5..1b2c4d844e 100644 --- a/exercises/connect/example.tt +++ b/exercises/connect/example.tt @@ -4,11 +4,13 @@ require 'minitest/autorun' require_relative 'connect' # Common test data version: <%= abbreviated_commit_hash %> -class ConnectTest < Minitest::Test<% test_cases.each do |test_case| %> +class ConnectTest < Minitest::Test +<% test_cases.each do |test_case| %> <%= test_case.ignore_method_length%>def <%= test_case.name %> <%= test_case.skipped %><% test_case.test_body.each do |line| %> <%= line %><% end %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> def test_bookkeeping diff --git a/lib/connect_cases.rb b/lib/connect_cases.rb index 9a4e11a16c..83285296de 100644 --- a/lib/connect_cases.rb +++ b/lib/connect_cases.rb @@ -1,12 +1,6 @@ require 'exercise_cases' -class ConnectCase < OpenStruct - def name - 'test_%s' % description - .gsub(/[() -]/, '_') - .chomp('_') - .downcase - end +class ConnectCase < ExerciseCase def test_body [ @@ -19,9 +13,7 @@ def test_body ] end - def skipped - index.zero? ? '# skip' : 'skip' - end + private def single_quote(string) string.inspect.tr('"', "'") @@ -31,13 +23,3 @@ def ignore_method_length "# rubocop:disable MethodLength\n " if board.length > 8 end end - -ConnectCases = proc do |data| - json = JSON.parse(data) - cases = [] - json['cases'].each_with_index do |row, i| - row['index'] = i - cases << ConnectCase.new(row) - end - cases -end From 6950d68856d3501ff308fca9c43f7b0063e51f42 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 17:04:23 -0700 Subject: [PATCH 36/61] convert custom-set --- exercises/custom-set/custom_set_test.rb | 3 +- exercises/custom-set/example.tt | 7 +++- lib/custom_set_cases.rb | 49 +++++++------------------ 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/exercises/custom-set/custom_set_test.rb b/exercises/custom-set/custom_set_test.rb index 7a06d402a5..028e2519c8 100755 --- a/exercises/custom-set/custom_set_test.rb +++ b/exercises/custom-set/custom_set_test.rb @@ -3,8 +3,7 @@ require 'minitest/autorun' require_relative 'custom_set' -# Test data version: -# cdfb4a2 +# Common test data version: 4527635 class CustomSetTest < Minitest::Test def test_sets_with_no_elements_are_empty # skip diff --git a/exercises/custom-set/example.tt b/exercises/custom-set/example.tt index 8e43614e32..d5993c8f0f 100644 --- a/exercises/custom-set/example.tt +++ b/exercises/custom-set/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'custom_set' # Common test data version: <%= abbreviated_commit_hash %> -class CustomSetTest < Minitest::Test<% test_cases.each do |test_case| %> +class CustomSetTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> <%= test_case.skipped %> - <%= test_case.test_body %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/custom_set_cases.rb b/lib/custom_set_cases.rb index 9111971aac..ae196fb0bf 100644 --- a/lib/custom_set_cases.rb +++ b/lib/custom_set_cases.rb @@ -1,88 +1,67 @@ require 'exercise_cases' -class CustomSetCase < OpenStruct - def name - 'test_%s' % description.gsub(/ |-/, '_') - end +class CustomSetCase < ExerciseCase - def test_body - send section + def workload + send property end + private + def union "set1 = CustomSet.new #{set1} set2 = CustomSet.new #{set2} expected = CustomSet.new #{expected} - #{assert_or_refute}_equal expected, set1.union(set2)" + #{assert}_equal expected, set1.union(set2)" end def difference "set1 = CustomSet.new #{set1} set2 = CustomSet.new #{set2} expected = CustomSet.new #{expected} - #{assert_or_refute}_equal expected, set1.difference(set2)" + #{assert}_equal expected, set1.difference(set2)" end def intersection "set1 = CustomSet.new #{set1} set2 = CustomSet.new #{set2} expected = CustomSet.new #{expected} - #{assert_or_refute}_equal expected, set2.intersection(set1)" + #{assert}_equal expected, set2.intersection(set1)" end def add "set = CustomSet.new #{set} expected = CustomSet.new #{expected} - #{assert_or_refute}_equal expected, set.add(#{element})" + #{assert}_equal expected, set.add(#{element})" end def equal "set1 = CustomSet.new #{set1} set2 = CustomSet.new #{set2} - #{assert_or_refute}_equal set1, set2" + #{assert}_equal set1, set2" end def disjoint "set1 = CustomSet.new #{set1} set2 = CustomSet.new #{set2} - #{assert_or_refute} set1.disjoint? set2" + #{assert} set1.disjoint? set2" end def subset "set1 = CustomSet.new #{set1} set2 = CustomSet.new #{set2} - #{assert_or_refute} set1.subset? set2" + #{assert} set1.subset? set2" end def empty "set = CustomSet.new #{set} - #{assert_or_refute}_empty set" + #{assert}_empty set" end def contains "set = CustomSet.new #{set} element = #{element} - #{assert_or_refute} set.member? element" - end - - def assert_or_refute - expected ? 'assert' : 'refute' + #{assert} set.member? element" end - def skipped - index.zero? ? '# skip' : 'skip' - end -end - -CustomSetCases = proc do |data| - json = JSON.parse(data) - cases = [] - i = 0 - (json.keys - ['#']).each do |section| - json[section]['cases'].each do |row| - cases << CustomSetCase.new(row.merge('index' => i, 'section' => section)) - i += 1 - end - end - cases end From 70d9bce4d45a8dfc19dd639a6f1f0abb69a56920 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 17:20:42 -0700 Subject: [PATCH 37/61] convert difference-of-squares --- .../difference_of_squares_test.rb | 11 ++++--- exercises/difference-of-squares/example.tt | 12 ++++--- lib/difference_of_squares_cases.rb | 31 +++---------------- 3 files changed, 19 insertions(+), 35 deletions(-) diff --git a/exercises/difference-of-squares/difference_of_squares_test.rb b/exercises/difference-of-squares/difference_of_squares_test.rb index 724bc8af3c..a803083576 100755 --- a/exercises/difference-of-squares/difference_of_squares_test.rb +++ b/exercises/difference-of-squares/difference_of_squares_test.rb @@ -3,11 +3,10 @@ require 'minitest/autorun' require_relative 'difference_of_squares' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: 1eb9535 class DifferenceOfSquaresTest < Minitest::Test def test_square_of_sum_5 + # skip assert_equal 225, Squares.new(5).square_of_sum end @@ -61,14 +60,16 @@ def test_consistent_difference squares = Squares.new(10) assert_equal squares.difference, squares.difference end + # Problems in exercism evolve over time, as we find better ways to ask # questions. # The version number refers to the version of the problem you solved, # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. diff --git a/exercises/difference-of-squares/example.tt b/exercises/difference-of-squares/example.tt index 62e691df38..7ebbf058a9 100644 --- a/exercises/difference-of-squares/example.tt +++ b/exercises/difference-of-squares/example.tt @@ -4,18 +4,22 @@ require 'minitest/autorun' require_relative 'difference_of_squares' # Common test data version: <%= abbreviated_commit_hash %> -class DifferenceOfSquaresTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %><% if test_case.skipped? %> - skip<% end %> - assert_equal <%= test_case.expected_formatted %>, <%= test_case.do %> +class DifferenceOfSquaresTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> def test_consistent_difference skip squares = Squares.new(10) assert_equal squares.difference, squares.difference end + <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/difference_of_squares_cases.rb b/lib/difference_of_squares_cases.rb index 19993699a0..514d75ab20 100644 --- a/lib/difference_of_squares_cases.rb +++ b/lib/difference_of_squares_cases.rb @@ -1,38 +1,17 @@ require 'exercise_cases' -class DifferenceOfSquaresCase < OpenStruct - def test_name - 'test_%s' % description.gsub(/[ -]/, '_') - end +class DifferenceOfSquaresCase < ExerciseCase - def do - "Squares.new(#{number}).#{action}" + def workload + %Q(assert_equal #{expected_formatted}, Squares.new(#{number}).#{action}) end def action - return 'difference' if section == 'difference_of_squares' - section - end - - def skipped? - index > 0 + return 'difference' if property == 'differenceOfSquares' + property.gsub(/([OS])/) {|cap| "_#{$1.downcase}" } end def expected_formatted expected.to_s.reverse.scan(/\d{1,3}/).join('_').reverse end end - -DifferenceOfSquaresCases = proc do |data| - i = 0 - json = JSON.parse(data) - cases = [] - %w(square_of_sum sum_of_squares difference_of_squares).each do |section| - json[section]['cases'].each do |row| - row = row.merge(row.merge('index' => i, 'section' => section)) - cases << DifferenceOfSquaresCase.new(row) - i += 1 - end - end - cases -end From aee153dbfb4472274beeead0846f99d93738b8f5 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 17:22:44 -0700 Subject: [PATCH 38/61] convert dominoes --- exercises/dominoes/dominoes_test.rb | 2 +- exercises/dominoes/example.tt | 2 +- lib/dominoes_cases.rb | 13 ++----------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/exercises/dominoes/dominoes_test.rb b/exercises/dominoes/dominoes_test.rb index fcb06def6e..030b26d903 100755 --- a/exercises/dominoes/dominoes_test.rb +++ b/exercises/dominoes/dominoes_test.rb @@ -3,7 +3,7 @@ require 'minitest/autorun' require_relative 'dominoes' -# Test data version: 82eb00d +# Common test data version: 89a5281 class DominoesTest < Minitest::Test def test_empty_input_empty_output # skip diff --git a/exercises/dominoes/example.tt b/exercises/dominoes/example.tt index 9a2839c75c..452f7e67d1 100644 --- a/exercises/dominoes/example.tt +++ b/exercises/dominoes/example.tt @@ -6,7 +6,7 @@ require_relative 'dominoes' # Common test data version: <%= abbreviated_commit_hash %> class DominoesTest < Minitest::Test <% test_cases.each do |test_case| %> - def <%= test_case.test_name %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end diff --git a/lib/dominoes_cases.rb b/lib/dominoes_cases.rb index e210918c5b..b67dc49606 100644 --- a/lib/dominoes_cases.rb +++ b/lib/dominoes_cases.rb @@ -1,7 +1,7 @@ require 'exercise_cases' -class DominoesCase < OpenStruct - def test_name +class DominoesCase < ExerciseCase + def name 'test_%s' % description.gsub("can't", 'can not').gsub(/[= -]+/, '_') end @@ -13,13 +13,4 @@ def workload WL end - def skipped - index.zero? ? '# skip' : 'skip' - end -end - -DominoesCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - DominoesCase.new(row.merge('index' => i)) - end end From 5c0b3d8fe8fedef704a705c561d661518763906f Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 17:29:51 -0700 Subject: [PATCH 39/61] convert hello-world --- exercises/hello-world/example.tt | 2 +- exercises/hello-world/hello_world_test.rb | 2 +- lib/hello_world_cases.rb | 16 ++-------------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/exercises/hello-world/example.tt b/exercises/hello-world/example.tt index b5b11df425..93fa862cd7 100644 --- a/exercises/hello-world/example.tt +++ b/exercises/hello-world/example.tt @@ -15,7 +15,7 @@ end # Common test data version: <%= abbreviated_commit_hash %> class HelloWorldTest < Minitest::Test <% test_cases.each do |test_case| %> - def <%= test_case.test_name %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end diff --git a/exercises/hello-world/hello_world_test.rb b/exercises/hello-world/hello_world_test.rb index 848784949c..dfb53740eb 100755 --- a/exercises/hello-world/hello_world_test.rb +++ b/exercises/hello-world/hello_world_test.rb @@ -14,7 +14,7 @@ # Common test data version: 4b9ae53 class HelloWorldTest < Minitest::Test - def test_hello + def test_say_hi # skip assert_equal "Hello, World!", HelloWorld.hello end diff --git a/lib/hello_world_cases.rb b/lib/hello_world_cases.rb index 9afdb99628..0637e853b3 100644 --- a/lib/hello_world_cases.rb +++ b/lib/hello_world_cases.rb @@ -1,21 +1,9 @@ require 'exercise_cases' -class HelloWorldCase < OpenStruct - def test_name - 'test_%s' % property.gsub(/[ -]/, '_') - end +class HelloWorldCase < ExerciseCase def workload - "assert_equal #{expected.inspect}, HelloWorld.hello" + assert_equal { "HelloWorld.hello" } end - def skipped - index.zero? ? '# skip' : 'skip' - end -end - -HelloWorldCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - HelloWorldCase.new(row.merge('index' => i)) - end end From 2a1e0aacbcc79f2508fa35577d923f9bf946d5bf Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 17:49:55 -0700 Subject: [PATCH 40/61] add indentation helper for multi-line workloads --- lib/generator/exercise_cases.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/generator/exercise_cases.rb b/lib/generator/exercise_cases.rb index f1f7271b25..a4c6c99c0c 100644 --- a/lib/generator/exercise_cases.rb +++ b/lib/generator/exercise_cases.rb @@ -14,6 +14,17 @@ def skipped protected + # used to indent multi line workloads, as + # indent_lines( + # [ + # "string = #{input.inspect}", + # "#{assert} Isogram.is_isogram?(string)" + # ], 4 + # ) + def indent_lines(code, depth) + code.join("\n" + ' ' * depth) + end + # used in workload, for example, as # "#{assert} Luhn.valid?(#{input.inspect})" def assert From 0b46dfbe11ba578f7dbe9d0cde333e2cfa3d3bd4 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 17:50:22 -0700 Subject: [PATCH 41/61] convert isogram --- exercises/isogram/.meta/.version | 2 +- exercises/isogram/example.rb | 2 +- exercises/isogram/example.tt | 10 ++++++---- exercises/isogram/isogram_test.rb | 28 ++++++++++++++++++---------- lib/isogram_cases.rb | 24 ++++++++---------------- 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/exercises/isogram/.meta/.version b/exercises/isogram/.meta/.version index d8263ee986..e440e5c842 100644 --- a/exercises/isogram/.meta/.version +++ b/exercises/isogram/.meta/.version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/exercises/isogram/example.rb b/exercises/isogram/example.rb index 3f03e418dc..857864361a 100644 --- a/exercises/isogram/example.rb +++ b/exercises/isogram/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 2 + VERSION = 3 end class Isogram diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index 8825aa0929..6091953aa1 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -5,14 +5,16 @@ require 'minitest/autorun' require_relative 'isogram' # Common test data version: <%= abbreviated_commit_hash %> -class IsogramTest < Minitest::Test<% test_cases.each do |test_case| %> +class IsogramTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> - <%= test_case.skip %> - string = '<%= test_case.input %>' - <%= test_case.assertion %> Isogram.is_isogram?(string) + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/isogram/isogram_test.rb b/exercises/isogram/isogram_test.rb index 1373d1ff85..ad11e324aa 100755 --- a/exercises/isogram/isogram_test.rb +++ b/exercises/isogram/isogram_test.rb @@ -4,55 +4,62 @@ require 'minitest/autorun' require_relative 'isogram' -# Common test data version: c59c2c4 +# Common test data version: 857c40d class IsogramTest < Minitest::Test def test_empty_string # skip - string = '' + string = "" assert Isogram.is_isogram?(string) end def test_isogram_with_only_lower_case_characters skip - string = 'isogram' + string = "isogram" assert Isogram.is_isogram?(string) end def test_word_with_one_duplicated_character skip - string = 'eleven' + string = "eleven" refute Isogram.is_isogram?(string) end def test_longest_reported_english_isogram skip - string = 'subdermatoglyphic' + string = "subdermatoglyphic" assert Isogram.is_isogram?(string) end def test_word_with_duplicated_character_in_mixed_case skip - string = 'Alphabet' + string = "Alphabet" refute Isogram.is_isogram?(string) end def test_hypothetical_isogrammic_word_with_hyphen skip - string = 'thumbscrew-japingly' + string = "thumbscrew-japingly" assert Isogram.is_isogram?(string) end def test_isogram_with_duplicated_non_letter_character skip - string = 'Hjelmqvist-Gryb-Zock-Pfund-Wax' + string = "Hjelmqvist-Gryb-Zock-Pfund-Wax" assert Isogram.is_isogram?(string) end def test_made_up_name_that_is_an_isogram skip - string = 'Emily Jung Schwartzkopf' + string = "Emily Jung Schwartzkopf" assert Isogram.is_isogram?(string) end + + def test_duplicated_character_in_the_middle + skip + string = "accentor" + refute Isogram.is_isogram?(string) + end + # Problems in exercism evolve over time, as we find better ways to ask # questions. # The version number refers to the version of the problem you solved, @@ -69,8 +76,9 @@ def test_made_up_name_that_is_an_isogram # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip - assert_equal 2, BookKeeping::VERSION + assert_equal 3, BookKeeping::VERSION end end diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 7248108757..c5e12d431f 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -1,22 +1,14 @@ require 'exercise_cases' -class IsogramCase < OpenStruct +class IsogramCase < ExerciseCase - def name - format('test_%s', description.downcase.gsub(/[ -]/, '_')) + def workload + indent_lines( + [ + "string = #{input.inspect}", + "#{assert} Isogram.is_isogram?(string)" + ], 4 + ) end - def assertion - expected ? 'assert' : 'refute' - end - - def skip - index.zero? ? '# skip' : 'skip' - end -end - -IsogramCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - IsogramCase.new(row.merge('index' => i)) - end end From 646e72aa090964cfad76fc38a4e5a745074b8814 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:04:42 -0700 Subject: [PATCH 42/61] convert (and update) largest-series-product --- .../largest-series-product/.meta/.version | 2 +- exercises/largest-series-product/example.rb | 2 +- exercises/largest-series-product/example.tt | 12 ++++--- .../largest_series_product_test.rb | 32 +++++++------------ lib/largest_series_product_cases.rb | 26 ++++++--------- 5 files changed, 30 insertions(+), 44 deletions(-) diff --git a/exercises/largest-series-product/.meta/.version b/exercises/largest-series-product/.meta/.version index d8263ee986..e440e5c842 100644 --- a/exercises/largest-series-product/.meta/.version +++ b/exercises/largest-series-product/.meta/.version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/exercises/largest-series-product/example.rb b/exercises/largest-series-product/example.rb index 521312588b..2d3c81a43c 100644 --- a/exercises/largest-series-product/example.rb +++ b/exercises/largest-series-product/example.rb @@ -1,7 +1,7 @@ # see also https://gist.github.com/blairand/5237976 # see also https://gist.github.com/burtlo/89b0b817fdccf6bdf20f module BookKeeping - VERSION = 2 + VERSION = 3 end class Series diff --git a/exercises/largest-series-product/example.tt b/exercises/largest-series-product/example.tt index 2cc815fdae..3723f52553 100644 --- a/exercises/largest-series-product/example.tt +++ b/exercises/largest-series-product/example.tt @@ -4,14 +4,16 @@ require 'minitest/autorun' require_relative 'largest_series_product' # Common test data version: <%= abbreviated_commit_hash %> -class Seriestest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %><% if test_case.raises_error? %> - assert_raises(ArgumentError) { <%= test_case.do %> }<% else %> - assert_equal <%= test_case.expected %>, <%= test_case.do %><% end %> +class Seriestest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping assert_equal <%= version %>, BookKeeping::VERSION end diff --git a/exercises/largest-series-product/largest_series_product_test.rb b/exercises/largest-series-product/largest_series_product_test.rb index de1d9dff2e..c5613d3b24 100755 --- a/exercises/largest-series-product/largest_series_product_test.rb +++ b/exercises/largest-series-product/largest_series_product_test.rb @@ -3,11 +3,15 @@ require 'minitest/autorun' require_relative 'largest_series_product' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: e79b832 class Seriestest < Minitest::Test + def test_finds_the_largest_product_if_span_equals_length + # skip + assert_equal 18, Series.new('29').largest_product(2) + end + def test_can_find_the_largest_product_of_2_with_numbers_in_order + skip assert_equal 72, Series.new('0123456789').largest_product(2) end @@ -16,11 +20,6 @@ def test_can_find_the_largest_product_of_2 assert_equal 48, Series.new('576802143').largest_product(2) end - def test_finds_the_largest_product_if_span_equals_length - skip - assert_equal 18, Series.new('29').largest_product(2) - end - def test_can_find_the_largest_product_of_3_with_numbers_in_order skip assert_equal 504, Series.new('0123456789').largest_product(3) @@ -41,16 +40,6 @@ def test_can_get_the_largest_product_of_a_big_number assert_equal 23520, Series.new('73167176531330624919225119674426574742355349194934').largest_product(6) end - def test_can_get_the_largest_product_of_a_big_number_ii - skip - assert_equal 28350, Series.new('52677741234314237566414902593461595376319419139427').largest_product(6) - end - - def test_can_get_the_largest_product_of_a_big_number_project_euler - skip - assert_equal 23514624000, Series.new('7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450').largest_product(13) - end - def test_reports_zero_if_the_only_digits_are_zero skip assert_equal 0, Series.new('0000').largest_product(2) @@ -97,8 +86,9 @@ def test_rejects_negative_span # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. @@ -108,6 +98,6 @@ def test_rejects_negative_span # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html def test_bookkeeping - assert_equal 2, BookKeeping::VERSION + assert_equal 3, BookKeeping::VERSION end end diff --git a/lib/largest_series_product_cases.rb b/lib/largest_series_product_cases.rb index 1cf2484a97..de9786803b 100644 --- a/lib/largest_series_product_cases.rb +++ b/lib/largest_series_product_cases.rb @@ -1,25 +1,19 @@ require 'exercise_cases' -class LargestSeriesProductCase < OpenStruct - def name - 'test_%s' % description.tr('()', '').tr(' -', '_').downcase - end +class LargestSeriesProductCase < ExerciseCase - def do - "Series.new('#{digits}').largest_product(#{span})" + def workload + if raises_error? + assert_raises(ArgumentError) { test_case } + else + assert_equal { test_case } + end end - def raises_error? - expected.to_i == -1 - end + private - def skipped? - index > 0 + def test_case + "Series.new('#{digits}').largest_product(#{span})" end -end -LargestSeriesProductCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - LargestSeriesProductCase.new(row.merge('index' => i)) - end end From 4470a07b80c240fc1d8ab5be05e9603f5ddf0f7b Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:14:03 -0700 Subject: [PATCH 43/61] convert (and update) leap --- exercises/leap/.meta/.version | 2 +- exercises/leap/example.rb | 2 +- exercises/leap/example.tt | 10 ++++++---- exercises/leap/leap_test.rb | 36 +++++++++++------------------------ lib/leap_cases.rb | 19 +++--------------- 5 files changed, 22 insertions(+), 47 deletions(-) diff --git a/exercises/leap/.meta/.version b/exercises/leap/.meta/.version index 0cfbf08886..e440e5c842 100644 --- a/exercises/leap/.meta/.version +++ b/exercises/leap/.meta/.version @@ -1 +1 @@ -2 +3 \ No newline at end of file diff --git a/exercises/leap/example.rb b/exercises/leap/example.rb index 446309bc92..54ec3aca2a 100644 --- a/exercises/leap/example.rb +++ b/exercises/leap/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 2 + VERSION = 3 end class Year diff --git a/exercises/leap/example.tt b/exercises/leap/example.tt index a3214faac7..862ff33226 100644 --- a/exercises/leap/example.tt +++ b/exercises/leap/example.tt @@ -13,14 +13,16 @@ class Date alias julian_leap? leap? end -class YearTest < Minitest::Test<% test_cases.each do |test_case| %> +class YearTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> - <%= test_case.skip %><% if test_case.expected%> - assert <%= test_case.do %>, "<%= test_case.failure_message%>"<% else %> - refute <%= test_case.do %>, "<%= test_case.failure_message%>"<% end%> + <%= test_case.skipped %> + <%= test_case.workload %>, "<%= test_case.failure_message %>" end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/leap/leap_test.rb b/exercises/leap/leap_test.rb index 1b9baf4592..de2fb87896 100755 --- a/exercises/leap/leap_test.rb +++ b/exercises/leap/leap_test.rb @@ -3,8 +3,7 @@ require 'minitest/autorun' require_relative 'leap' -# Test data version: -# 7b0949e +# Common test data version: cc65ebe class Date def leap? raise RuntimeError, "Implement this yourself instead of using Ruby's implementation." @@ -15,40 +14,26 @@ def leap? end class YearTest < Minitest::Test - def test_leap_year + def test_year_not_divisible_by_4_common_year # skip - assert Year.leap?(1996), "Expected 'true', 1996 is a leap year." + refute Year.leap?(2015), "Expected 'false', 2015 is not a leap year." end - def test_standard_and_odd_year + def test_year_divisible_by_4_not_divisible_by_100_leap_year skip - refute Year.leap?(1997), "Expected 'false', 1997 is not a leap year." + assert Year.leap?(2016), "Expected 'true', 2016 is a leap year." end - def test_standard_even_year + def test_year_divisible_by_100_not_divisible_by_400_common_year skip - refute Year.leap?(1998), "Expected 'false', 1998 is not a leap year." + refute Year.leap?(2100), "Expected 'false', 2100 is not a leap year." end - def test_standard_nineteenth_century - skip - refute Year.leap?(1900), "Expected 'false', 1900 is not a leap year." - end - - def test_standard_eighteenth_century - skip - refute Year.leap?(1800), "Expected 'false', 1800 is not a leap year." - end - - def test_leap_twenty_fourth_century - skip - assert Year.leap?(2400), "Expected 'true', 2400 is a leap year." - end - - def test_leap_y2k + def test_year_divisible_by_400_leap_year skip assert Year.leap?(2000), "Expected 'true', 2000 is a leap year." end + # Problems in exercism evolve over time, as we find better ways to ask # questions. # The version number refers to the version of the problem you solved, @@ -65,8 +50,9 @@ def test_leap_y2k # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip - assert_equal 2, BookKeeping::VERSION + assert_equal 3, BookKeeping::VERSION end end diff --git a/lib/leap_cases.rb b/lib/leap_cases.rb index 7f0f14b705..592c4b1ac5 100644 --- a/lib/leap_cases.rb +++ b/lib/leap_cases.rb @@ -1,25 +1,12 @@ require 'exercise_cases' -class LeapCase < OpenStruct - def name - 'test_%s' % description.downcase.gsub(/[ -]/, '_') - end - - def do - "Year.leap?(#{input})" - end +class LeapCase < ExerciseCase - def skip - index.zero? ? '# skip' : 'skip' + def workload + "#{assert} Year.leap?(#{input.inspect})" end def failure_message "Expected '#{expected}', #{input} is #{expected ? '' : 'not '}a leap year." end end - -LeapCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - LeapCase.new(row.merge('index' => i)) - end -end From d2ae3d6e5a9bbcc466c39dd6dfc92519b78dee05 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:17:58 -0700 Subject: [PATCH 44/61] convert nth-prime --- exercises/nth-prime/example.tt | 12 +++++++----- exercises/nth-prime/nth_prime_test.rb | 5 ++--- lib/nth_prime_cases.rb | 24 +++++++++++------------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/exercises/nth-prime/example.tt b/exercises/nth-prime/example.tt index 1583a5e0f0..c2bce8d179 100644 --- a/exercises/nth-prime/example.tt +++ b/exercises/nth-prime/example.tt @@ -4,14 +4,16 @@ require 'minitest/autorun' require_relative 'nth_prime' # Common test data version: <%= abbreviated_commit_hash %> -class NthPrimeTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %><% if test_case.raises_error? %> - assert_raises(ArgumentError) { <%= test_case.actual %> }<% else %> - assert_equal <%= test_case.expected %>, <%= test_case.actual %><% end %> +class NthPrimeTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/nth-prime/nth_prime_test.rb b/exercises/nth-prime/nth_prime_test.rb index f13f1ecc29..ac94605934 100755 --- a/exercises/nth-prime/nth_prime_test.rb +++ b/exercises/nth-prime/nth_prime_test.rb @@ -3,11 +3,10 @@ require 'minitest/autorun' require_relative 'nth_prime' -# Test data version: -# bb79e10 -# +# Common test data version: 016d65b class NthPrimeTest < Minitest::Test def test_first_prime + # skip assert_equal 2, Prime.nth(1) end diff --git a/lib/nth_prime_cases.rb b/lib/nth_prime_cases.rb index 4cb4824d65..efb6eab55f 100644 --- a/lib/nth_prime_cases.rb +++ b/lib/nth_prime_cases.rb @@ -1,11 +1,18 @@ require 'exercise_cases' -class NthPrimeCase < OpenStruct - def name - 'test_%s' % description.downcase.gsub(/[ -]/, '_') +class NthPrimeCase < ExerciseCase + + def workload + if raises_error? + assert_raises(ArgumentError) { test_case } + else + assert_equal { test_case } + end end - def actual + private + + def test_case "Prime.nth(#{input})" end @@ -13,13 +20,4 @@ def raises_error? expected == false end - def skipped? - index > 0 - end -end - -NthPrimeCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - NthPrimeCase.new(row.merge('index' => i)) - end end From 8e786c9d12417146a7171c49beabeddff7eb446a Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:31:58 -0700 Subject: [PATCH 45/61] convert raindrops --- exercises/raindrops/example.tt | 11 ++-- exercises/raindrops/raindrops_test.rb | 76 +++++++++++++-------------- lib/raindrops_cases.rb | 18 ++----- 3 files changed, 48 insertions(+), 57 deletions(-) diff --git a/exercises/raindrops/example.tt b/exercises/raindrops/example.tt index 5efd047f35..b1db84ae5b 100644 --- a/exercises/raindrops/example.tt +++ b/exercises/raindrops/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'raindrops' # Common test data version: <%= abbreviated_commit_hash %> -class RaindropsTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %> - assert_equal '<%= test_case.expected %>', <%= test_case.do %> +class RaindropsTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/raindrops/raindrops_test.rb b/exercises/raindrops/raindrops_test.rb index ecf39a4623..9b1fc867ad 100755 --- a/exercises/raindrops/raindrops_test.rb +++ b/exercises/raindrops/raindrops_test.rb @@ -3,96 +3,96 @@ require 'minitest/autorun' require_relative 'raindrops' -# Test data version: -# 5b5e807 +# Common test data version: 9db5371 class RaindropsTest < Minitest::Test - def test_1 - assert_equal '1', Raindrops.convert(1) + def test_the_sound_for_1_is_1 + # skip + assert_equal "1", Raindrops.convert(1) end - def test_3 + def test_the_sound_for_3_is_pling skip - assert_equal 'Pling', Raindrops.convert(3) + assert_equal "Pling", Raindrops.convert(3) end - def test_5 + def test_the_sound_for_5_is_plang skip - assert_equal 'Plang', Raindrops.convert(5) + assert_equal "Plang", Raindrops.convert(5) end - def test_7 + def test_the_sound_for_7_is_plong skip - assert_equal 'Plong', Raindrops.convert(7) + assert_equal "Plong", Raindrops.convert(7) end - def test_6 + def test_the_sound_for_6_is_pling_as_it_has_a_factor_3 skip - assert_equal 'Pling', Raindrops.convert(6) + assert_equal "Pling", Raindrops.convert(6) end - def test_8 + def test_2_to_the_power_3_does_not_make_a_raindrop_sound_as_3_is_the_exponent_not_the_base skip - assert_equal '8', Raindrops.convert(8) + assert_equal "8", Raindrops.convert(8) end - def test_9 + def test_the_sound_for_9_is_pling_as_it_has_a_factor_3 skip - assert_equal 'Pling', Raindrops.convert(9) + assert_equal "Pling", Raindrops.convert(9) end - def test_10 + def test_the_sound_for_10_is_plang_as_it_has_a_factor_5 skip - assert_equal 'Plang', Raindrops.convert(10) + assert_equal "Plang", Raindrops.convert(10) end - def test_14 + def test_the_sound_for_14_is_plong_as_it_has_a_factor_of_7 skip - assert_equal 'Plong', Raindrops.convert(14) + assert_equal "Plong", Raindrops.convert(14) end - def test_15 + def test_the_sound_for_15_is_plingplang_as_it_has_factors_3_and_5 skip - assert_equal 'PlingPlang', Raindrops.convert(15) + assert_equal "PlingPlang", Raindrops.convert(15) end - def test_21 + def test_the_sound_for_21_is_plingplong_as_it_has_factors_3_and_7 skip - assert_equal 'PlingPlong', Raindrops.convert(21) + assert_equal "PlingPlong", Raindrops.convert(21) end - def test_25 + def test_the_sound_for_25_is_plang_as_it_has_a_factor_5 skip - assert_equal 'Plang', Raindrops.convert(25) + assert_equal "Plang", Raindrops.convert(25) end - def test_27 + def test_the_sound_for_27_is_pling_as_it_has_a_factor_3 skip - assert_equal 'Pling', Raindrops.convert(27) + assert_equal "Pling", Raindrops.convert(27) end - def test_35 + def test_the_sound_for_35_is_plangplong_as_it_has_factors_5_and_7 skip - assert_equal 'PlangPlong', Raindrops.convert(35) + assert_equal "PlangPlong", Raindrops.convert(35) end - def test_49 + def test_the_sound_for_49_is_plong_as_it_has_a_factor_7 skip - assert_equal 'Plong', Raindrops.convert(49) + assert_equal "Plong", Raindrops.convert(49) end - def test_52 + def test_the_sound_for_52_is_52 skip - assert_equal '52', Raindrops.convert(52) + assert_equal "52", Raindrops.convert(52) end - def test_105 + def test_the_sound_for_105_is_plingplangplong_as_it_has_factors_3_5_and_7 skip - assert_equal 'PlingPlangPlong', Raindrops.convert(105) + assert_equal "PlingPlangPlong", Raindrops.convert(105) end - def test_3125 + def test_the_sound_for_3125_is_plang_as_it_has_a_factor_5 skip - assert_equal 'Plang', Raindrops.convert(3125) + assert_equal "Plang", Raindrops.convert(3125) end # Problems in exercism evolve over time, as we find better ways to ask diff --git a/lib/raindrops_cases.rb b/lib/raindrops_cases.rb index 2b8487d46d..59449694ac 100644 --- a/lib/raindrops_cases.rb +++ b/lib/raindrops_cases.rb @@ -1,21 +1,9 @@ require 'exercise_cases' -class RaindropsCase < OpenStruct - def name - 'test_%s' % number - end +class RaindropsCase < ExerciseCase - def do - "Raindrops.convert(#{number})" + def workload + assert_equal { "Raindrops.convert(#{number})" } end - def skipped? - index > 0 - end -end - -RaindropsCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - RaindropsCase.new(row.merge('index' => i)) - end end From b72a89de206b74b8f9a17fecff2239b4d14a24bc Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:38:11 -0700 Subject: [PATCH 46/61] convert rna-transcription --- exercises/rna-transcription/example.tt | 9 ++++++--- .../rna-transcription/rna_transcription_test.rb | 9 ++++----- lib/rna_transcription_cases.rb | 16 ++-------------- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/exercises/rna-transcription/example.tt b/exercises/rna-transcription/example.tt index b748fec11d..71b2edacee 100644 --- a/exercises/rna-transcription/example.tt +++ b/exercises/rna-transcription/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'rna_transcription' # Common test data version: <%= abbreviated_commit_hash %> -class ComplementTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class ComplementTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> - assert_equal '<%= test_case.expected %>', <%= test_case.workload %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/rna-transcription/rna_transcription_test.rb b/exercises/rna-transcription/rna_transcription_test.rb index b42e200542..04e236fa5f 100755 --- a/exercises/rna-transcription/rna_transcription_test.rb +++ b/exercises/rna-transcription/rna_transcription_test.rb @@ -3,9 +3,7 @@ require 'minitest/autorun' require_relative 'rna_transcription' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: 0b20fff class ComplementTest < Minitest::Test def test_rna_complement_of_cytosine_is_guanine # skip @@ -53,8 +51,9 @@ def test_dna_correctly_handles_partially_invalid_input # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. diff --git a/lib/rna_transcription_cases.rb b/lib/rna_transcription_cases.rb index 3632d94a52..fe9b917edc 100644 --- a/lib/rna_transcription_cases.rb +++ b/lib/rna_transcription_cases.rb @@ -1,21 +1,9 @@ require 'exercise_cases' -class RnaTranscriptionCase < OpenStruct - def test_name - 'test_%s' % description.gsub(/[ -]/, '_') - end +class RnaTranscriptionCase < ExerciseCase def workload - "Complement.of_dna('#{dna}')" + "assert_equal '#{expected}', Complement.of_dna('#{dna}')" end - def skipped - index.zero? ? '# skip' : 'skip' - end -end - -RnaTranscriptionCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - RnaTranscriptionCase.new(row.merge('index' => i)) - end end From 1f756227eb133c11a8545520751ecc690d8f441f Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:44:22 -0700 Subject: [PATCH 47/61] convert roman-numerals --- exercises/roman-numerals/example.tt | 11 +++++++---- exercises/roman-numerals/roman_numerals_test.rb | 10 +++++----- lib/roman_numerals_cases.rb | 17 +++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/exercises/roman-numerals/example.tt b/exercises/roman-numerals/example.tt index 3ea7808043..225e9fff30 100644 --- a/exercises/roman-numerals/example.tt +++ b/exercises/roman-numerals/example.tt @@ -4,13 +4,16 @@ require 'minitest/autorun' require_relative 'roman_numerals' # Common test data version: <%= abbreviated_commit_hash %> -class RomanNumeralsTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %> - assert_equal '<%= test_case.expected %>', <%= test_case.do %> +class RomanNumeralsTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/roman-numerals/roman_numerals_test.rb b/exercises/roman-numerals/roman_numerals_test.rb index adaa76d1a3..f0fd00f0f8 100755 --- a/exercises/roman-numerals/roman_numerals_test.rb +++ b/exercises/roman-numerals/roman_numerals_test.rb @@ -3,11 +3,10 @@ require 'minitest/autorun' require_relative 'roman_numerals' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: 070e8d5 class RomanNumeralsTest < Minitest::Test def test_1 + # skip assert_equal 'I', 1.to_roman end @@ -102,8 +101,9 @@ def test_3000 # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. diff --git a/lib/roman_numerals_cases.rb b/lib/roman_numerals_cases.rb index e193d061d4..66eb6b0657 100644 --- a/lib/roman_numerals_cases.rb +++ b/lib/roman_numerals_cases.rb @@ -1,21 +1,18 @@ require 'exercise_cases' -class RomanNumeralsCase < OpenStruct +class RomanNumeralsCase < ExerciseCase def name 'test_%s' % number.to_s end - def do - '%s.to_roman' % number.to_s + def workload + "assert_equal '#{expected}', #{actual}" end - def skipped? - index > 0 - end -end + private -RomanNumeralsCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - RomanNumeralsCase.new(row.merge('index' => i)) + def actual + '%s.to_roman' % number.to_s end + end From 1765e987d490ead1a4e1e6447e62b023a8958514 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:54:40 -0700 Subject: [PATCH 48/61] convert sieve --- exercises/sieve/example.tt | 5 ++++- exercises/sieve/sieve_test.rb | 4 +--- lib/sieve_cases.rb | 16 +--------------- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/exercises/sieve/example.tt b/exercises/sieve/example.tt index 5c4f6077fa..32453a6b7d 100644 --- a/exercises/sieve/example.tt +++ b/exercises/sieve/example.tt @@ -4,14 +4,17 @@ require 'minitest/autorun' require_relative 'sieve' # Common test data version: <%= abbreviated_commit_hash %> -class SieveTest < Minitest::Test<% test_cases.each do |test_case| %> +class SieveTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> <%= test_case.skipped %> expected = <%= test_case.expected_string %> assert_equal expected, Sieve.new(<%= test_case.limit %>).primes end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/sieve/sieve_test.rb b/exercises/sieve/sieve_test.rb index 6d9d24f096..4193802ad9 100755 --- a/exercises/sieve/sieve_test.rb +++ b/exercises/sieve/sieve_test.rb @@ -3,9 +3,7 @@ require 'minitest/autorun' require_relative 'sieve' -# Test data version: -# 43d62d1 - +# Common test data version: f2b2693 class SieveTest < Minitest::Test def test_no_primes_under_two # skip diff --git a/lib/sieve_cases.rb b/lib/sieve_cases.rb index ff109c68ef..a20de27dda 100644 --- a/lib/sieve_cases.rb +++ b/lib/sieve_cases.rb @@ -1,15 +1,11 @@ require 'exercise_cases' -class SieveCase < OpenStruct +class SieveCase < ExerciseCase OPEN_ARRAY = "[\n\s\s\s\s\s\s".freeze CLOSE_ARRAY = "\n\s\s\s\s]".freeze NEW_ARRAY_ROW = ",\n\s\s\s\s\s\s".freeze ARRAY_ELEMENTS_PER_ROW = 17.freeze - def name - 'test_%s' % description.tr(' ', '_') - end - def expected_string return expected unless needs_indentation? @@ -17,19 +13,9 @@ def expected_string "#{OPEN_ARRAY}#{array_rows.join(NEW_ARRAY_ROW)}#{CLOSE_ARRAY}" end - def skipped - index.zero? ? '# skip' : 'skip' - end - private def needs_indentation? expected.size > ARRAY_ELEMENTS_PER_ROW end end - -SieveCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - SieveCase.new(row.merge('index' => i)) - end -end From 70954d85f6bc311abb3a6df45434cc10c67b5829 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:57:38 -0700 Subject: [PATCH 49/61] convert transpose --- exercises/transpose/example.tt | 7 +++++-- exercises/transpose/transpose_test.rb | 3 +-- lib/transpose_cases.rb | 15 +-------------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/exercises/transpose/example.tt b/exercises/transpose/example.tt index 8767b3963e..7f173c4273 100644 --- a/exercises/transpose/example.tt +++ b/exercises/transpose/example.tt @@ -4,16 +4,19 @@ require 'minitest/autorun' require_relative 'transpose' # Common test data version: <%= abbreviated_commit_hash %> -class TransposeTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class TransposeTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> input = <%= test_case.input_text %> actual = <%= test_case.workload %> expected = <%= test_case.expect %> assert_equal expected.strip, actual end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/transpose/transpose_test.rb b/exercises/transpose/transpose_test.rb index 31a14563f0..149db2fa9d 100755 --- a/exercises/transpose/transpose_test.rb +++ b/exercises/transpose/transpose_test.rb @@ -3,8 +3,7 @@ require 'minitest/autorun' require_relative 'transpose' -# Test data version: -# 0a51cfc +# Common test data version: 6dba022 class TransposeTest < Minitest::Test def test_empty_string # skip diff --git a/lib/transpose_cases.rb b/lib/transpose_cases.rb index e29923ec65..23cdd0db84 100644 --- a/lib/transpose_cases.rb +++ b/lib/transpose_cases.rb @@ -1,13 +1,6 @@ require 'exercise_cases' -class TransposeCase < OpenStruct - def test_name - "test_#{description.tr(' ', '_')}" - end - - def skipped - index.zero? ? '# skip' : 'skip' - end +class TransposeCase < ExerciseCase def workload 'Transpose.transpose(input)' @@ -39,9 +32,3 @@ def indent_line(line, indent = 2) ' ' * indent * 2 + line end end - -TransposeCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - TransposeCase.new(row.merge('index' => i)) - end -end From b6d0b08b2b4f3fa2b166ae4bbee647679239dca4 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Tue, 25 Apr 2017 18:59:28 -0700 Subject: [PATCH 50/61] convert word-count --- exercises/word-count/example.tt | 10 ++++++---- exercises/word-count/word_count_test.rb | 5 ++--- lib/word_count_cases.rb | 14 +------------- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/exercises/word-count/example.tt b/exercises/word-count/example.tt index 7661a1c50d..2247b89492 100644 --- a/exercises/word-count/example.tt +++ b/exercises/word-count/example.tt @@ -4,18 +4,20 @@ require 'minitest/autorun' require_relative 'word_count' # Common test data version: <%= abbreviated_commit_hash %> -class PhraseTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %> +class PhraseTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> phrase = <%= test_case.object_under_test %> counts = <%= test_case.expected %> assert_equal counts, phrase.word_count end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION end end - diff --git a/exercises/word-count/word_count_test.rb b/exercises/word-count/word_count_test.rb index de0c666738..1199c2a179 100755 --- a/exercises/word-count/word_count_test.rb +++ b/exercises/word-count/word_count_test.rb @@ -3,10 +3,10 @@ require 'minitest/autorun' require_relative 'word_count' -# Test data version: -# 5b5e807 +# Common test data version: cd26d49 class PhraseTest < Minitest::Test def test_count_one_word + # skip phrase = Phrase.new("word") counts = {"word"=>1} assert_equal counts, phrase.word_count @@ -97,4 +97,3 @@ def test_bookkeeping assert_equal 1, BookKeeping::VERSION end end - diff --git a/lib/word_count_cases.rb b/lib/word_count_cases.rb index 3ebc3583fe..7c9094ec6d 100644 --- a/lib/word_count_cases.rb +++ b/lib/word_count_cases.rb @@ -1,21 +1,9 @@ require 'exercise_cases' -class WordCountCase < OpenStruct - def name - 'test_%s' % description.tr(' ', '_') - end +class WordCountCase < ExerciseCase def object_under_test %Q(Phrase.new(#{input.inspect})) end - def skipped? - index.nonzero? - end -end - -WordCountCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - WordCountCase.new(row.merge('index' => i)) - end end From 0dff1966a28495c25dcf1857e355eaa9a422da68 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 11:04:19 -0700 Subject: [PATCH 51/61] convert (and fix) binary --- exercises/binary/binary_test.rb | 5 +++-- exercises/binary/example.tt | 7 +++++-- lib/binary_cases.rb | 23 +++++------------------ 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/exercises/binary/binary_test.rb b/exercises/binary/binary_test.rb index be9f37d900..e2bfd8f1be 100755 --- a/exercises/binary/binary_test.rb +++ b/exercises/binary/binary_test.rb @@ -4,8 +4,7 @@ require 'minitest/autorun' require_relative 'binary' -# Test data version: -# 82eb00d +# Common test data version: 969717d class BinaryTest < Minitest::Test def test_binary_0_is_decimal_0 # skip @@ -81,6 +80,7 @@ def test_a_number_and_a_word_whitespace_spearated_is_invalid skip assert_raises(ArgumentError) { Binary.to_decimal('001 nope') } end + # Problems in exercism evolve over time, as we find better ways to ask # questions. # The version number refers to the version of the problem you solved, @@ -97,6 +97,7 @@ def test_a_number_and_a_word_whitespace_spearated_is_invalid # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip assert_equal 3, BookKeeping::VERSION diff --git a/exercises/binary/example.tt b/exercises/binary/example.tt index a057b78305..548df6a27d 100644 --- a/exercises/binary/example.tt +++ b/exercises/binary/example.tt @@ -5,13 +5,16 @@ require 'minitest/autorun' require_relative 'binary' # Common test data version: <%= abbreviated_commit_hash %> -class BinaryTest < Minitest::Test<% test_cases.each do |test_case| %> +class BinaryTest < Minitest::Test +<% test_cases.each do |test_case| %> def <%= test_case.name %> <%= test_case.skipped %> - <%= test_case.assertion %> + <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/lib/binary_cases.rb b/lib/binary_cases.rb index c281e7851f..7fc65de53b 100644 --- a/lib/binary_cases.rb +++ b/lib/binary_cases.rb @@ -1,29 +1,22 @@ require 'exercise_cases' -class BinaryCase < OpenStruct - def name - 'test_%s' % description.gsub(/[ -]/, '_') - end +class BinaryCase < ExerciseCase - def assertion + def workload raises_error? ? error_assertion : equality_assertion end - def skipped - index.zero? ? '# skip' : 'skip' - end - private def error_assertion - "assert_raises(ArgumentError) { #{workload} }" + "assert_raises(ArgumentError) { #{test_case} }" end def equality_assertion - "assert_equal #{expected}, #{workload}" + "assert_equal #{expected}, #{test_case}" end - def workload + def test_case "Binary.to_decimal('#{binary}')" end @@ -31,9 +24,3 @@ def raises_error? expected.nil? end end - -BinaryCases = proc do |data| - JSON.parse(data)['decimal'].map.with_index do |row, i| - BinaryCase.new(row.merge('index' => i)) - end -end From 9fe3565107cf34692c1a5f473cf9d8b6f00810d3 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 11:26:28 -0700 Subject: [PATCH 52/61] convert (and fix) say --- exercises/say/example.tt | 12 +++++++----- exercises/say/say_test.rb | 5 +++-- lib/say_cases.rb | 17 +++-------------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/exercises/say/example.tt b/exercises/say/example.tt index e6dd9f726a..caf3a0c8d9 100644 --- a/exercises/say/example.tt +++ b/exercises/say/example.tt @@ -1,17 +1,19 @@ require 'minitest/autorun' require_relative 'say' -# Test data version: <%= sha1 %> -class SayTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +# Common test data version: <%= abbreviated_commit_hash %> +class SayTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end -<% end %> +<% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip - assert_equal <%= version.next %>, BookKeeping::VERSION + assert_equal <%= version %>, BookKeeping::VERSION end end diff --git a/exercises/say/say_test.rb b/exercises/say/say_test.rb index 83067ceef6..daa3bb0f1d 100755 --- a/exercises/say/say_test.rb +++ b/exercises/say/say_test.rb @@ -1,7 +1,7 @@ require 'minitest/autorun' require_relative 'say' -# Test data version: e3bd4a2 +# Common test data version: be403e1 class SayTest < Minitest::Test def test_zero # skip @@ -89,7 +89,7 @@ def test_numbers_below_zero_are_out_of_range end end - def test_numbers_above_999_999_999_999_are_out_of_range + def test_numbers_above_999999999999_are_out_of_range skip question = 1_000_000_000_000 assert_raises ArgumentError do @@ -113,6 +113,7 @@ def test_numbers_above_999_999_999_999_are_out_of_range # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip assert_equal 1, BookKeeping::VERSION diff --git a/lib/say_cases.rb b/lib/say_cases.rb index 52c7a5be52..0010d4948a 100644 --- a/lib/say_cases.rb +++ b/lib/say_cases.rb @@ -1,7 +1,6 @@ -class SayCase < OpenStruct - def test_name - 'test_%s' % description.tr(' ,-', '_').downcase - end +require 'exercise_cases' + +class SayCase < ExerciseCase def workload [ @@ -10,10 +9,6 @@ def workload ].join("\n") end - def skipped - index.zero? ? '# skip' : 'skip' - end - private def indent(size, lines) @@ -38,9 +33,3 @@ def underscore_format(number) number.to_s.reverse.gsub(/...(?=.)/, '\&_').reverse end end - -SayCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - SayCase.new(row.merge(index: i)) - end -end From 01abfc965778ecea6153f9cf3d9547a015a17b2e Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 11:37:15 -0700 Subject: [PATCH 53/61] convert, update and fix run-length-encoding generator --- exercises/run-length-encoding/.meta/.version | 2 +- exercises/run-length-encoding/example.rb | 2 +- exercises/run-length-encoding/example.tt | 9 +- .../run_length_encoding_test.rb | 98 +++++++++++++------ lib/run_length_encoding_cases.rb | 29 +----- 5 files changed, 82 insertions(+), 58 deletions(-) diff --git a/exercises/run-length-encoding/.meta/.version b/exercises/run-length-encoding/.meta/.version index d8263ee986..e440e5c842 100644 --- a/exercises/run-length-encoding/.meta/.version +++ b/exercises/run-length-encoding/.meta/.version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/exercises/run-length-encoding/example.rb b/exercises/run-length-encoding/example.rb index 0f2704c3e0..8f4ec5ae24 100644 --- a/exercises/run-length-encoding/example.rb +++ b/exercises/run-length-encoding/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 2 + VERSION = 3 end class RunLengthEncoding diff --git a/exercises/run-length-encoding/example.tt b/exercises/run-length-encoding/example.tt index 411a955e1b..defc9fd60c 100644 --- a/exercises/run-length-encoding/example.tt +++ b/exercises/run-length-encoding/example.tt @@ -5,15 +5,18 @@ require 'minitest/autorun' require_relative 'run_length_encoding' # Common test data version: <%= abbreviated_commit_hash %> -class RunLengthEncodingTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.name %><% if test_case.skipped? %> - skip<% end %> +class RunLengthEncodingTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> <%= test_case.assign_input %> <%= test_case.assign_output %> <%= test_case.assertion %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/run-length-encoding/run_length_encoding_test.rb b/exercises/run-length-encoding/run_length_encoding_test.rb index 6a90285739..ee305330f7 100755 --- a/exercises/run-length-encoding/run_length_encoding_test.rb +++ b/exercises/run-length-encoding/run_length_encoding_test.rb @@ -4,57 +4,98 @@ require 'minitest/autorun' require_relative 'run_length_encoding' -# Test data version: -# deb225e Implement canonical dataset for scrabble-score problem (#255) - +# Common test data version: 503a57a class RunLengthEncodingTest < Minitest::Test - def test_encode_simple - input = 'AABBBCCCC' - output = '2A3B4C' + def test_empty_string + # skip + input = '' + output = '' assert_equal output, RunLengthEncoding.encode(input) end - def test_decode_simple + def test_single_characters_only_are_encoded_without_count skip - input = '2A3B4C' - output = 'AABBBCCCC' - assert_equal output, RunLengthEncoding.decode(input) + input = 'XYZ' + output = 'XYZ' + assert_equal output, RunLengthEncoding.encode(input) + end + + def test_string_with_no_single_characters + skip + input = 'AABBBCCCC' + output = '2A3B4C' + assert_equal output, RunLengthEncoding.encode(input) end - def test_encode_with_single_values + def test_single_characters_mixed_with_repeated_characters skip input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' output = '12WB12W3B24WB' assert_equal output, RunLengthEncoding.encode(input) end - def test_decode_with_single_values + def test_multiple_whitespace_mixed_in_string + skip + input = ' hsqq qww ' + output = '2 hs2q q2w2 ' + assert_equal output, RunLengthEncoding.encode(input) + end + + def test_lowercase_characters + skip + input = 'aabbbcccc' + output = '2a3b4c' + assert_equal output, RunLengthEncoding.encode(input) + end + + def test_empty_string + skip + input = '' + output = '' + assert_equal output, RunLengthEncoding.decode(input) + end + + def test_single_characters_only + skip + input = 'XYZ' + output = 'XYZ' + assert_equal output, RunLengthEncoding.decode(input) + end + + def test_string_with_no_single_characters + skip + input = '2A3B4C' + output = 'AABBBCCCC' + assert_equal output, RunLengthEncoding.decode(input) + end + + def test_single_characters_with_repeated_characters skip input = '12WB12W3B24WB' output = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' assert_equal output, RunLengthEncoding.decode(input) end - def test_decode_encode_combination + def test_multiple_whitespace_mixed_in_string skip - input = 'zzz ZZ zZ' - output = 'zzz ZZ zZ' - assert_equal output, - RunLengthEncoding.decode(RunLengthEncoding.encode(input)) + input = '2 hs2q q2w2 ' + output = ' hsqq qww ' + assert_equal output, RunLengthEncoding.decode(input) end - def test_encode_unicode + def test_lower_case_string skip - input = '⏰⚽⚽⚽⭐⭐⏰' - output = '⏰3⚽2⭐⏰' - assert_equal output, RunLengthEncoding.encode(input) + input = '2a3b4c' + output = 'aabbbcccc' + assert_equal output, RunLengthEncoding.decode(input) end - def test_decode_unicode + def test_encode_followed_by_decode_gives_original_string skip - input = '⏰3⚽2⭐⏰' - output = '⏰⚽⚽⚽⭐⭐⏰' - assert_equal output, RunLengthEncoding.decode(input) + input = 'zzz ZZ zZ' + output = 'zzz ZZ zZ' + assert_equal output, + RunLengthEncoding.decode(RunLengthEncoding.encode(input)) end # Problems in exercism evolve over time, as we find better ways to ask @@ -63,8 +104,9 @@ def test_decode_unicode # not your solution. # # Define a constant named VERSION inside of the top level BookKeeping - # module. - # In your file, it will look like this: + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: # # module BookKeeping # VERSION = 1 # Where the version number matches the one in the test. @@ -75,6 +117,6 @@ def test_decode_unicode def test_bookkeeping skip - assert_equal 2, BookKeeping::VERSION + assert_equal 3, BookKeeping::VERSION end end diff --git a/lib/run_length_encoding_cases.rb b/lib/run_length_encoding_cases.rb index 7816ff9411..45cd8dc675 100644 --- a/lib/run_length_encoding_cases.rb +++ b/lib/run_length_encoding_cases.rb @@ -1,9 +1,6 @@ require 'exercise_cases' -class RunLengthEncodingCase < OpenStruct - def name - 'test_%s' % cleaned_description - end +class RunLengthEncodingCase < ExerciseCase def assign_input "input = '#{input}'" @@ -14,30 +11,12 @@ def assign_output end def assertion - case description - when /decode.+encode/ + if property == 'consistency' 'assert_equal output, RunLengthEncoding.decode(RunLengthEncoding.encode(input))' - when /encode/ - 'assert_equal output, RunLengthEncoding.encode(input)' - when /decode/ - 'assert_equal output, RunLengthEncoding.decode(input)' + else + "assert_equal output, RunLengthEncoding.#{property}(input)" end end - def skipped? - index > 0 - end - - # internal - - def cleaned_description - description.gsub(/\W+/, '_').squeeze('_') - end -end - -RunLengthEncodingCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - RunLengthEncodingCase.new(row.merge('index' => i)) - end end From 2023c78a8434157bd1e8f3103b4789fa88b84743 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 11:56:07 -0700 Subject: [PATCH 54/61] convert wordy --- exercises/wordy/example.tt | 8 +++++--- exercises/wordy/wordy_test.rb | 3 ++- lib/wordy_cases.rb | 31 ++++--------------------------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/exercises/wordy/example.tt b/exercises/wordy/example.tt index 3a7203f5d7..0be041d28d 100644 --- a/exercises/wordy/example.tt +++ b/exercises/wordy/example.tt @@ -2,14 +2,16 @@ require 'minitest/autorun' require_relative 'wordy' # Common test data version: <%= abbreviated_commit_hash %> -class WordyTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class WordyTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end -<% end %> +<% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/wordy/wordy_test.rb b/exercises/wordy/wordy_test.rb index 46312f0c9b..c902bd8cf5 100755 --- a/exercises/wordy/wordy_test.rb +++ b/exercises/wordy/wordy_test.rb @@ -1,7 +1,7 @@ require 'minitest/autorun' require_relative 'wordy' -# Test data version: aa12f2e +# Common test data version: 5b8ad58 class WordyTest < Minitest::Test def test_addition # skip @@ -121,6 +121,7 @@ def test_non_math_question # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip assert_equal 1, BookKeeping::VERSION diff --git a/lib/wordy_cases.rb b/lib/wordy_cases.rb index bd12581d75..530fe25837 100644 --- a/lib/wordy_cases.rb +++ b/lib/wordy_cases.rb @@ -1,9 +1,6 @@ require 'exercise_cases' -class WordyCase < OpenStruct - def test_name - 'test_%s' % description.downcase.tr(' ', '_') - end +class WordyCase < ExerciseCase def workload [ @@ -12,10 +9,6 @@ def workload ].join("\n") end - def skipped - index.zero? ? '# skip' : 'skip' - end - private def indent(size, lines) @@ -44,26 +37,10 @@ def message_assertion "assert_equal(#{expected}, answer, message)", ].join("\n") end -end - -class WordyCase::PreProcessor - class << self - def call(row) - row.merge('message' => message_for(row)) - end - private - - def message_for(row) - return unless row['input'] == 'What is -3 plus 7 multiplied by -2?' - - 'You should ignore order of precedence. -3 + 7 * -2 = -8, not %s' - end - end -end + def message + return unless input == 'What is -3 plus 7 multiplied by -2?' -WordyCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - WordyCase.new(WordyCase::PreProcessor.call(row).merge(index: i)) + 'You should ignore order of precedence. -3 + 7 * -2 = -8, not %s' end end From 195640cca3831a257413071fe76a05d7a6482932 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 12:17:36 -0700 Subject: [PATCH 55/61] fix wordy tests removed tests that are now redundant --- test/wordy_cases_test.rb | 69 +++------------------------------------- 1 file changed, 4 insertions(+), 65 deletions(-) diff --git a/test/wordy_cases_test.rb b/test/wordy_cases_test.rb index 7e93803007..7b5699d9b2 100644 --- a/test/wordy_cases_test.rb +++ b/test/wordy_cases_test.rb @@ -2,30 +2,6 @@ require_relative 'test_helper' class WordyCaseTest < Minitest::Test - def test_test_name - test_case = WordyCase.new(description: 'description') - - assert_equal 'test_description', test_case.test_name - end - - def test_test_name_with_description_with_spaces - test_case = WordyCase.new(description: 'description with spaces') - - assert_equal 'test_description_with_spaces', test_case.test_name - end - - def test_skipped_with_zero_index - test_case = WordyCase.new(index: 0) - - assert_equal '# skip', test_case.skipped - end - - def test_skipped_with_non_zero_index - test_case = WordyCase.new(index: 1) - - assert_equal 'skip', test_case.skipped - end - def test_workload_with_expected_and_no_message test_case = WordyCase.new(expected: 1, input: 1) @@ -38,12 +14,13 @@ def test_workload_with_expected_and_no_message end def test_workload_with_expected_and_message - test_case = WordyCase.new(expected: 1, input: 1, message: 'test %s') + test_case = WordyCase.new(expected: 1, input: 'What is -3 plus 7 multiplied by -2?') + message = test_case.send(:message) expected_workload = [ - 'question = \'1\'', + "question = 'What is -3 plus 7 multiplied by -2?'", ' answer = WordProblem.new(question).answer', - ' message = "test #{answer}"', + ' message = "' + message[0..-3] + '#{answer}"', ' assert_equal(1, answer, message)', ].join("\n") @@ -63,41 +40,3 @@ def test_workload_without_expected assert_equal expected_workload, test_case.workload end end - -class WordyCasePrProcessorTest < Minitest::Test - def test_call_as_non_special_case - row = { 'input' => '' } - processed_row = WordyCase::PreProcessor.call(row) - - assert_equal({ 'input' => '', 'message' => nil }, processed_row) - end - - def test_call_as_special_case - row = { 'input' => 'What is -3 plus 7 multiplied by -2?' } - processed_row = WordyCase::PreProcessor.call(row) - expected_row = { - 'input' => 'What is -3 plus 7 multiplied by -2?', - 'message' => 'You should ignore order of precedence. -3 + 7 * -2 = -8, not %s', - } - - assert_equal expected_row, processed_row - end -end - -class WordyCasesTest < Minitest::Test - def test_call - json = { - cases: [ - { description: 'test 1' }, - { description: 'test 2' }, - ] - }.to_json - - expected_cases = [ - WordyCase.new(description: 'test 1', message: nil, index: 0), - WordyCase.new(description: 'test 2', message: nil, index: 1), - ] - - assert_equal expected_cases, WordyCases.call(json) - end -end From eb993bede74d1a6f740c950751153c0a33f5ef49 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 12:23:36 -0700 Subject: [PATCH 56/61] convert (and fix) triangle generator --- exercises/triangle/example.tt | 8 ++++--- exercises/triangle/triangle_test.rb | 4 +--- lib/triangle_cases.rb | 35 +++++++---------------------- 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/exercises/triangle/example.tt b/exercises/triangle/example.tt index b98d5b75d2..b68cd68d1d 100644 --- a/exercises/triangle/example.tt +++ b/exercises/triangle/example.tt @@ -4,16 +4,18 @@ require 'minitest/autorun' require_relative 'triangle' # Common test data version: <%= abbreviated_commit_hash %> -class TriangleTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class TriangleTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION end end - diff --git a/exercises/triangle/triangle_test.rb b/exercises/triangle/triangle_test.rb index b5277fe085..048cd67206 100755 --- a/exercises/triangle/triangle_test.rb +++ b/exercises/triangle/triangle_test.rb @@ -3,8 +3,7 @@ require 'minitest/autorun' require_relative 'triangle' -# Test data version: -# b806246 +# Common test data version: fa90b35 class TriangleTest < Minitest::Test def test_triangle_is_equilateral_if_all_sides_are_equal # skip @@ -130,4 +129,3 @@ def test_bookkeeping assert_equal 1, BookKeeping::VERSION end end - diff --git a/lib/triangle_cases.rb b/lib/triangle_cases.rb index b07643458a..6ea686d384 100644 --- a/lib/triangle_cases.rb +++ b/lib/triangle_cases.rb @@ -1,11 +1,11 @@ require 'exercise_cases' -class TriangleCase < OpenStruct - def test_name +class TriangleCase < ExerciseCase + def name initial = description.downcase replaced = initial.gsub(/(true|false)/, expected_type) - if initial.eql?(replaced) && !initial.include?(triangle) - replaced = triangle + ' triangle ' + initial + if initial.eql?(replaced) && !initial.include?(property) + replaced = property + ' triangle ' + initial end 'test_%s' % replaced.tr_s(', -', '_') end @@ -13,41 +13,22 @@ def test_name def workload [ "triangle = Triangle.new(#{sides})", - indent("#{assert_or_refute} triangle.#{triangle}?, #{failure_message}") + indent("#{assert} triangle.#{property}?, #{failure_message}") ].join("\n") end + private + def indent(line) ' ' * 4 + line end - def assert_or_refute - expected ? 'assert' : 'refute' - end - def failure_message %Q("Expected '#{expected}', #{expected_type}.") end def expected_type - "triangle is #{expected ? '' : 'not '}#{triangle}" - end - - def skipped - index.zero? ? '# skip' : 'skip' + "triangle is #{expected ? '' : 'not '}#{property}" end -end -TriangleCases = proc do |data| - i = 0 - cases = [] - data = JSON.parse(data).select { |key, value| key.to_s.match(/[^#]+/) } - data.keys.each do |triangle| - data[triangle]['cases'].each do |row| - row = row.merge(row.merge('index' => i, 'triangle' => triangle)) - cases << TriangleCase.new(row) - i += 1 - end - end - cases end From 519163cdd38a766a748e805eb1f50297e8322680 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 12:29:26 -0700 Subject: [PATCH 57/61] convert (and fix) grains generator --- exercises/grains/example.tt | 8 ++++-- exercises/grains/grains_test.rb | 3 +- lib/grains_cases.rb | 49 ++++++++------------------------- 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/exercises/grains/example.tt b/exercises/grains/example.tt index 5f3be36938..571417b20c 100644 --- a/exercises/grains/example.tt +++ b/exercises/grains/example.tt @@ -2,14 +2,16 @@ require 'minitest/autorun' require_relative 'grains' # Common test data version: <%= abbreviated_commit_hash %> -class GrainsTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class GrainsTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end -<% end %> +<% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/grains/grains_test.rb b/exercises/grains/grains_test.rb index db99758d62..577857db65 100755 --- a/exercises/grains/grains_test.rb +++ b/exercises/grains/grains_test.rb @@ -1,7 +1,7 @@ require 'minitest/autorun' require_relative 'grains' -# Test data version: aa12f2e +# Common test data version: 2e0e77e class GrainsTest < Minitest::Test def test_1 # skip @@ -74,6 +74,7 @@ def test_returns_the_total_number_of_grains_on_the_board # # If you are curious, read more about constants on RubyDoc: # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + def test_bookkeeping skip assert_equal 1, BookKeeping::VERSION diff --git a/lib/grains_cases.rb b/lib/grains_cases.rb index d343ed9f77..6b4cb04291 100644 --- a/lib/grains_cases.rb +++ b/lib/grains_cases.rb @@ -1,53 +1,26 @@ require 'exercise_cases' -class GrainsCase < OpenStruct - def test_name - 'test_%s' % description.downcase.tr_s(' ', '_') - end +class GrainsCase < ExerciseCase def workload - fail NotImplementedError - end - - def skipped - index.zero? ? '# skip' : 'skip' + send("#{property}_workload") end private - def underscore_format(number) - number.to_s.reverse.gsub(/...(?=.)/, '\&_').reverse + def square_workload + if raises_error? + "assert_raises(ArgumentError) { Grains.square(#{input}) }" + else + "assert_equal #{underscore_format(expected)}, Grains.square(#{input})" + end end -end -class GrainsCase::SquareMethod < GrainsCase - def workload - return error_assertion if expected < 0 - - "assert_equal #{underscore_format(expected)}, Grains.square(#{input})" - end - - private - - def error_assertion - "assert_raises(ArgumentError) { Grains.square(#{input}) }" - end -end - -class GrainsCase::TotalMethod < GrainsCase - def workload + def total_workload "assert_equal #{underscore_format(expected)}, Grains.total" end -end - -GrainsCases = proc do |data| - data = JSON.parse(data) - cases = data['square']['cases'].map.with_index do |row, i| - GrainsCase::SquareMethod.new(row.merge('index' => i)) + def underscore_format(number) + number.to_s.reverse.gsub(/...(?=.)/, '\&_').reverse end - - cases << GrainsCase::TotalMethod.new( - data['total'].merge('index' => cases.size) - ) end From a26d051c7fd3517e60e33d43afb78ca740595c29 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 12:31:23 -0700 Subject: [PATCH 58/61] removed obsolete grains_cases tests --- test/grains_cases_test.rb | 103 -------------------------------------- 1 file changed, 103 deletions(-) delete mode 100644 test/grains_cases_test.rb diff --git a/test/grains_cases_test.rb b/test/grains_cases_test.rb deleted file mode 100644 index b58947230f..0000000000 --- a/test/grains_cases_test.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'json' -require_relative 'test_helper' - -class GrainsTest < Minitest::Test - def test_test_name - test_case = GrainsCase.new(description: 'description') - - assert_equal 'test_description', test_case.test_name - end - - def test_test_name_when_description_has_spaces - test_case = GrainsCase.new(description: 'description with spaces') - - assert_equal 'test_description_with_spaces', test_case.test_name - end - - def test_workload_is_not_implemented - assert_raises(NotImplementedError) { GrainsCase.new.workload } - end - - def test_skipped_with_zero_index - assert_equal '# skip', GrainsCase.new(index: 0).skipped - end - - def test_skipped_with_non_zero_index - assert_equal 'skip', GrainsCase.new(index: 1).skipped - end -end - -class SquareMethodTest < Minitest::Test - def test_workload_when_expected_is_negative - test_case = GrainsCase::SquareMethod.new(expected: -1, input: 10) - - assert_equal 'assert_raises(ArgumentError) { Grains.square(10) }', - test_case.workload - end - - def test_workload_when_expected_is_positive - test_case = GrainsCase::SquareMethod.new(expected: 1, input: 10) - - assert_equal 'assert_equal 1, Grains.square(10)', test_case.workload - end - - def test_workload_with_large_expected_number - test_case = GrainsCase::SquareMethod.new(expected: 10000, input: 10) - - assert_equal 'assert_equal 10_000, Grains.square(10)', test_case.workload - end -end - -class TotalMethodTest < Minitest::Test - def test_workload - test_case = GrainsCase::TotalMethod.new(expected: 1) - - assert_equal 'assert_equal 1, Grains.total', test_case.workload - end - - def test_workload_with_large_expected_number - test_case = GrainsCase::TotalMethod.new(expected: 10000) - - assert_equal 'assert_equal 10_000, Grains.total', test_case.workload - end -end - -class GrainsCasesTest < Minitest::Test - def test_handling_of_json - json = { - square: { - cases: [ - {}, - {}, - ], - }, - total: { - } - }.to_json - - cases = GrainsCases.call(json) - - assert_instance_of GrainsCase::SquareMethod, cases[0] - assert_instance_of GrainsCase::SquareMethod, cases[1] - assert_instance_of GrainsCase::TotalMethod, cases[2] - end - - def test_continuous_index - json = { - square: { - cases: [ - {}, - {}, - ], - }, - total: { - } - }.to_json - - cases = GrainsCases.call(json) - - assert_equal 0, cases[0].index - assert_equal 1, cases[1].index - assert_equal 2, cases[2].index - end -end From a739e6bef48e631cda6a5f4562bd6eefeea93fe4 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 12:43:46 -0700 Subject: [PATCH 59/61] convert (and fix) tournament generator --- exercises/tournament/example.tt | 5 ++++- exercises/tournament/tournament_test.rb | 3 +-- lib/tournament_cases.rb | 15 +-------------- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/exercises/tournament/example.tt b/exercises/tournament/example.tt index e6858cf16c..fc12c8a41b 100644 --- a/exercises/tournament/example.tt +++ b/exercises/tournament/example.tt @@ -5,16 +5,19 @@ require_relative 'tournament' # Common test data version: <%= abbreviated_commit_hash %> class TournamentTest < Minitest::Test + <% test_cases.each do |test_case| %> - def <%= test_case.test_name %> + def <%= test_case.name %> <%= test_case.skipped %> input = <%= test_case.input_text %> actual = <%= test_case.workload %> expected = <%= test_case.expect %> assert_equal expected, actual end + <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping skip assert_equal <%= version %>, BookKeeping::VERSION diff --git a/exercises/tournament/tournament_test.rb b/exercises/tournament/tournament_test.rb index 17a838152a..cf2b464302 100755 --- a/exercises/tournament/tournament_test.rb +++ b/exercises/tournament/tournament_test.rb @@ -3,8 +3,7 @@ require 'minitest/autorun' require_relative 'tournament' -# Test data version: -# 0a51cfc +# Common test data version: cda8f98 class TournamentTest < Minitest::Test def test_typical_input diff --git a/lib/tournament_cases.rb b/lib/tournament_cases.rb index ea1675ce5c..40bb181e6e 100644 --- a/lib/tournament_cases.rb +++ b/lib/tournament_cases.rb @@ -1,13 +1,6 @@ require 'exercise_cases' -class TournamentCase < OpenStruct - def test_name - "test_#{description.tr(' ', '_').tr('()', '')}" - end - - def skipped - index.zero? ? '# skip' : 'skip' - end +class TournamentCase < ExerciseCase def workload 'Tournament.tally(input)' @@ -39,9 +32,3 @@ def indent_line(line, indent = 2) ' ' * indent * 2 + line end end - -TournamentCases = proc do |data| - JSON.parse(data)['valid_inputs']['cases'].map.with_index do |row, i| - TournamentCase.new(row.merge('index' => i)) - end -end From ba795b326e1f8597b7cbb76ea4867a29919d1596 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 12:56:27 -0700 Subject: [PATCH 60/61] convert all-your-base --- exercises/all-your-base/all_your_base_test.rb | 2 +- exercises/all-your-base/example.tt | 7 +- lib/all_your_base_cases.rb | 76 ++++++------------- 3 files changed, 27 insertions(+), 58 deletions(-) diff --git a/exercises/all-your-base/all_your_base_test.rb b/exercises/all-your-base/all_your_base_test.rb index f88bc77bee..b20d2c3bf6 100755 --- a/exercises/all-your-base/all_your_base_test.rb +++ b/exercises/all-your-base/all_your_base_test.rb @@ -1,7 +1,7 @@ require 'minitest/autorun' require_relative 'all_your_base' -# Test data version: aa12f2e +# Common test data version: 39de23b class AllYourBaseTest < Minitest::Test def test_single_bit_one_to_decimal # skip diff --git a/exercises/all-your-base/example.tt b/exercises/all-your-base/example.tt index 82b3561bea..35634f3e01 100644 --- a/exercises/all-your-base/example.tt +++ b/exercises/all-your-base/example.tt @@ -2,13 +2,14 @@ require 'minitest/autorun' require_relative 'all_your_base' # Common test data version: <%= abbreviated_commit_hash %> -class AllYourBaseTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class AllYourBaseTest < Minitest::Test +<% test_cases.each do |test_case| %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end -<% end %> +<% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> def test_bookkeeping skip diff --git a/lib/all_your_base_cases.rb b/lib/all_your_base_cases.rb index c5e418f1b9..130d0b9d14 100644 --- a/lib/all_your_base_cases.rb +++ b/lib/all_your_base_cases.rb @@ -1,18 +1,11 @@ require 'exercise_cases' -class AllYourBaseCase < OpenStruct - def test_name - 'test_%s' % description.downcase.tr(' -', '_') - end +class AllYourBaseCase < ExerciseCase def workload indent(4, (assignments + assertion).join("\n")) + "\n" end - def skipped - index.zero? ? '# skip' : 'skip' - end - private def indent(size, text) @@ -30,10 +23,10 @@ def assignments end def assertion - return error_assertion unless expected + return error_assertion unless expected_value [ - "expected = #{expected}", + "expected = #{expected_value}", "", "converted = BaseConverter.convert(input_base, digits, output_base)", "", @@ -55,57 +48,32 @@ def error_message %q("Input base: #{input_base}, output base #{output_base}. " \\) \ "\n" + %q("Expected #{expected} but got #{converted}.") end -end - -class AllYourBaseCase::PreProcessor - class << self - attr_reader :row - - def call(row) - @row = row - - row.merge('expected' => expected_value) - end - - private :row - private - def expected_value - return row['expected'] if row['expected'] + def expected_value + return expected if expected - if invalid_input_digits? || invalid_bases? - nil - elsif row['input_digits'].empty? - [] - elsif input_of_zero? - [0] - else - handle_special_cases - end - end - - def invalid_input_digits? - row['input_digits'].any? { |x| x < 0 || x >= row['input_base'] } + case + when invalid_input_digits? || invalid_bases? then nil + when input_digits.empty? then [] + when input_of_zero? then [0] + else + handle_special_cases end + end - def invalid_bases? - row['input_base'] <= 1 || row['output_base'] <= 1 - end + def invalid_input_digits? + input_digits.any? { |x| x < 0 || x >= input_base } + end - def input_of_zero? - row['input_digits'].all? { |x| x == 0 } - end + def invalid_bases? + input_base <= 1 || output_base <= 1 + end - def handle_special_cases - [4, 2] if row['input_digits'] == [0, 6, 0] - end + def input_of_zero? + input_digits.all? { |x| x == 0 } end -end -AllYourBaseCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - AllYourBaseCase.new( - AllYourBaseCase::PreProcessor.call(row).merge(index: i), - ) + def handle_special_cases + [4, 2] if input_digits == [0, 6, 0] end end From c56bd33196b6c6c8449c4102287123ed9a65aac6 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Wed, 26 Apr 2017 13:41:40 -0700 Subject: [PATCH 61/61] convert (and fix) queen attack generator --- exercises/queen-attack/example.tt | 4 +- exercises/queen-attack/queen_attack_test.rb | 29 ++++++------ lib/queen_attack_cases.rb | 51 ++++++--------------- 3 files changed, 30 insertions(+), 54 deletions(-) diff --git a/exercises/queen-attack/example.tt b/exercises/queen-attack/example.tt index a1184b9c6e..d2290991df 100644 --- a/exercises/queen-attack/example.tt +++ b/exercises/queen-attack/example.tt @@ -4,10 +4,10 @@ require 'minitest/autorun' require_relative 'queen_attack' # Common test data version: <%= abbreviated_commit_hash %> -class QueenTest < Minitest::Test +class QueenAttackTest < Minitest::Test <% test_cases.each do |test_case| %> - def <%= test_case.test_name %> + def <%= test_case.name %> <%= test_case.skipped %> <%= test_case.workload %> end diff --git a/exercises/queen-attack/queen_attack_test.rb b/exercises/queen-attack/queen_attack_test.rb index 8c7c77ce26..5dc6339655 100755 --- a/exercises/queen-attack/queen_attack_test.rb +++ b/exercises/queen-attack/queen_attack_test.rb @@ -3,82 +3,81 @@ require 'minitest/autorun' require_relative 'queen_attack' -# Test data version: -# 82eb00d -class QueenTest < Minitest::Test +# Common test data version: 8adde5f +class QueenAttackTest < Minitest::Test def test_queen_with_a_valid_position # skip - Queens.new white: [2, 2] + assert Queens.new(white: [2, 2]) end def test_queen_must_have_positive_rank skip assert_raises ArgumentError do - Queens.new white: [-2, 2] + Queens.new(white: [-2, 2]) end end def test_queen_must_have_rank_on_board skip assert_raises ArgumentError do - Queens.new white: [8, 4] + Queens.new(white: [8, 4]) end end def test_queen_must_have_positive_file skip assert_raises ArgumentError do - Queens.new white: [2, -2] + Queens.new(white: [2, -2]) end end def test_queen_must_have_file_on_board skip assert_raises ArgumentError do - Queens.new white: [4, 8] + Queens.new(white: [4, 8]) end end def test_can_not_attack skip - queens = Queens.new white: [2, 4], black: [6, 6] + queens = Queens.new(white: [2, 4], black: [6, 6]) refute queens.attack? end def test_can_attack_on_same_rank skip - queens = Queens.new white: [2, 4], black: [2, 6] + queens = Queens.new(white: [2, 4], black: [2, 6]) assert queens.attack? end def test_can_attack_on_same_file skip - queens = Queens.new white: [4, 5], black: [2, 5] + queens = Queens.new(white: [4, 5], black: [2, 5]) assert queens.attack? end def test_can_attack_on_first_diagonal skip - queens = Queens.new white: [2, 2], black: [0, 4] + queens = Queens.new(white: [2, 2], black: [0, 4]) assert queens.attack? end def test_can_attack_on_second_diagonal skip - queens = Queens.new white: [2, 2], black: [3, 1] + queens = Queens.new(white: [2, 2], black: [3, 1]) assert queens.attack? end def test_can_attack_on_third_diagonal skip - queens = Queens.new white: [2, 2], black: [1, 1] + queens = Queens.new(white: [2, 2], black: [1, 1]) assert queens.attack? end def test_can_attack_on_fourth_diagonal skip - queens = Queens.new white: [2, 2], black: [5, 5] + queens = Queens.new(white: [2, 2], black: [5, 5]) assert queens.attack? end diff --git a/lib/queen_attack_cases.rb b/lib/queen_attack_cases.rb index 11aa229ecb..c5a720abc5 100644 --- a/lib/queen_attack_cases.rb +++ b/lib/queen_attack_cases.rb @@ -1,56 +1,33 @@ require 'exercise_cases' -class QueenCase < OpenStruct - def test_name - "test_#{description.gsub(/[ ]/, '_')}" - end +class QueenAttackCase < ExerciseCase - def skipped - index.zero? ? '# skip' : 'skip' + def workload + property == 'create' ? create_workload : attack_workload end - def parse_position queen - queen['position'].delete('() ').split(',').map{|i| i.to_i} - end -end + private -class QueenAttackCase < QueenCase - def workload - """queens = Queens.new white: #{parse_position white_queen}, black: #{parse_position black_queen} - #{assertion} queens.attack?""" + def attack_workload + """queens = Queens.new(white: #{parse_position white_queen}, black: #{parse_position black_queen}) + #{assert} queens.attack?""" end - def assertion - expected ? 'assert' : 'refute' + def parse_position queen + queen['position'].delete('() ').split(',').map{|i| i.to_i} end -end -class QueenCreateCase < QueenCase - def workload - expected == -1 ? exception : input + def create_workload + raises_error? ? exception : "#{assert} #{test_case}" end - def input - "Queens.new white: #{parse_position queen}" + def test_case + "Queens.new(white: #{parse_position queen})" end def exception """assert_raises ArgumentError do - #{input} + #{test_case} end""" end end - -TYPES = [ - ['create', QueenCreateCase], - ['can_attack', QueenAttackCase] -] - -QueenAttackCases = proc do |data| - json = JSON.parse data - TYPES.flat_map.with_index do |(type, caseClass), i| - json[type]['cases'].map.with_index do |row, j| - caseClass.new row.merge('index' => i+j) - end - end -end