From 8326281748aa4c439590e81c00520b2ff000b56f Mon Sep 17 00:00:00 2001 From: ajwann Date: Mon, 13 Feb 2017 19:16:16 -0500 Subject: [PATCH 1/4] etl: added generator --- exercises/etl/.meta/.version | 1 + exercises/etl/etl_test.rb | 115 ++++++++++++++++++++++++++--------- exercises/etl/example.rb | 4 ++ exercises/etl/example.tt | 17 ++++++ lib/etl_cases.rb | 48 +++++++++++++++ 5 files changed, 155 insertions(+), 30 deletions(-) create mode 100644 exercises/etl/.meta/.version create mode 100644 exercises/etl/example.tt create mode 100644 lib/etl_cases.rb diff --git a/exercises/etl/.meta/.version b/exercises/etl/.meta/.version new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/exercises/etl/.meta/.version @@ -0,0 +1 @@ +1 diff --git a/exercises/etl/etl_test.rb b/exercises/etl/etl_test.rb index 2a8b81d02c..e6dc4ac14e 100755 --- a/exercises/etl/etl_test.rb +++ b/exercises/etl/etl_test.rb @@ -1,58 +1,113 @@ -#!/usr/bin/env ruby -gem 'minitest', '>= 5.0.0' require 'minitest/autorun' require_relative 'etl' -class TransformTest < Minitest::Test - def test_transform_one_value - old = { 1 => ['A'] } - expected = { 'a' => 1 } +# Test data version: 040a24f +class EtlTest < Minitest::Test + def test_a_single_letter + # skip + old = { + '1' => ["A"], + } + expected = { + 'a' => '1', + } assert_equal expected, ETL.transform(old) end - def test_transform_more_values + def test_single_score_with_multiple_letters skip - old = { 1 => %w(A E I O U) } - expected = { 'a' => 1, 'e' => 1, 'i' => 1, 'o' => 1, 'u' => 1 } + old = { + '1' => ["A", "E", "I", "O", "U"], + } + expected = { + 'a' => '1', + 'e' => '1', + 'i' => '1', + 'o' => '1', + 'u' => '1', + } assert_equal expected, ETL.transform(old) end - def test_more_keys + def test_multiple_scores_with_multiple_letters skip - old = { 1 => %w(A E), 2 => %w(D G) } + old = { + '1' => ["A", "E"], + '2' => ["D", "G"], + } expected = { - 'a' => 1, - 'e' => 1, - 'd' => 2, - 'g' => 2 + 'a' => '1', + 'e' => '1', + 'd' => '2', + 'g' => '2', } assert_equal expected, ETL.transform(old) end - def test_full_dataset + def test_multiple_scores_with_differing_numbers_of_letters skip old = { - 1 => %w(A E I O U L N R S T), - 2 => %w(D G), - 3 => %w(B C M P), - 4 => %w(F H V W Y), - 5 => %w(K), - 8 => %w(J X), - 10 => %w(Q Z) + '1' => ["A", "E", "I", "O", "U", "L", "N", "R", "S", "T"], + '2' => ["D", "G"], + '3' => ["B", "C", "M", "P"], + '4' => ["F", "H", "V", "W", "Y"], + '5' => ["K"], + '8' => ["J", "X"], + '10' => ["Q", "Z"], } - expected = { - 'a' => 1, 'b' => 3, 'c' => 3, 'd' => 2, 'e' => 1, - 'f' => 4, 'g' => 2, 'h' => 4, 'i' => 1, 'j' => 8, - 'k' => 5, 'l' => 1, 'm' => 3, 'n' => 1, 'o' => 1, - 'p' => 3, 'q' => 10, 'r' => 1, 's' => 1, 't' => 1, - 'u' => 1, 'v' => 4, 'w' => 4, 'x' => 8, 'y' => 4, - 'z' => 10 + 'a' => '1', + 'b' => '3', + 'c' => '3', + 'd' => '2', + 'e' => '1', + 'f' => '4', + 'g' => '2', + 'h' => '4', + 'i' => '1', + 'j' => '8', + 'k' => '5', + 'l' => '1', + 'm' => '3', + 'n' => '1', + 'o' => '1', + 'p' => '3', + 'q' => '10', + 'r' => '1', + 's' => '1', + 't' => '1', + 'u' => '1', + 'v' => '4', + 'w' => '4', + 'x' => '8', + 'y' => '4', + 'z' => '10', } assert_equal expected, ETL.transform(old) 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, 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. + # end + # + # 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 + end end diff --git a/exercises/etl/example.rb b/exercises/etl/example.rb index 8797e0952c..a88d7f0fbd 100644 --- a/exercises/etl/example.rb +++ b/exercises/etl/example.rb @@ -1,3 +1,7 @@ +module BookKeeping + VERSION = 1 +end + class ETL def self.transform(old) data = {} diff --git a/exercises/etl/example.tt b/exercises/etl/example.tt new file mode 100644 index 0000000000..c4a58f240a --- /dev/null +++ b/exercises/etl/example.tt @@ -0,0 +1,17 @@ +require 'minitest/autorun' +require_relative 'etl' + +# Test data version: <%= abbreviated_commit_hash %> +class EtlTest < Minitest::Test<% test_cases.each do |test_case| %> + def <%= test_case.test_name %> + <%= test_case.skipped %> + <%= test_case.workload %> + end +<% end %> + +<%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping + skip + assert_equal <%= version.next %>, BookKeeping::VERSION + end +end diff --git a/lib/etl_cases.rb b/lib/etl_cases.rb new file mode 100644 index 0000000000..210f75e4af --- /dev/null +++ b/lib/etl_cases.rb @@ -0,0 +1,48 @@ +require 'exercise_cases' + +class EtlCase < OpenStruct + def test_name + 'test_%s' % description.tr(' ,-', '_').downcase + end + + def workload + [ + "old = #{format_hash(integerize_keys(input))}", + " expected = #{format_hash(expected)}\n", + indent(4, assertion), + ].join("\n") + end + + def skipped + index.zero? ? '# skip' : 'skip' + end + + private + + def indent(size, text) + text.lines.each_with_object('') { |line, obj| obj << ' ' * size + line } + end + + def assertion + "assert_equal expected, ETL.transform(old)" + end + + def integerize_keys(input) + input.reduce({}) { |hash, (k, v)| hash[k.to_i] = v; hash } + end + + def format_hash(hash) + middle = hash.each_pair.with_object('') do |(k, v), obj| + value = v.class == Array ? v : "'#{v}'" + obj << " '#{k}' => #{value},\n " + end + "{\n #{middle} }" + end + +end + +EtlCases = proc do |data| + JSON.parse(data)['transform']['cases'].map.with_index do |row, i| + EtlCase.new(row.merge(index: i)) + end +end From 35d1546ce727f2184e9f55d9ee225b0d1f3bff7d Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Thu, 27 Apr 2017 17:50:28 -0700 Subject: [PATCH 2/4] update etl generator --- exercises/etl/etl_test.rb | 5 +++-- exercises/etl/example.tt | 10 ++++++---- lib/etl_cases.rb | 18 ++---------------- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/exercises/etl/etl_test.rb b/exercises/etl/etl_test.rb index e6dc4ac14e..5a4865d242 100755 --- a/exercises/etl/etl_test.rb +++ b/exercises/etl/etl_test.rb @@ -1,7 +1,7 @@ require 'minitest/autorun' require_relative 'etl' -# Test data version: 040a24f +# Test data version: ca9ed58 class EtlTest < Minitest::Test def test_a_single_letter # skip @@ -39,8 +39,8 @@ def test_multiple_scores_with_multiple_letters } expected = { 'a' => '1', - 'e' => '1', 'd' => '2', + 'e' => '1', 'g' => '2', } @@ -106,6 +106,7 @@ def test_multiple_scores_with_differing_numbers_of_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 1, BookKeeping::VERSION diff --git a/exercises/etl/example.tt b/exercises/etl/example.tt index c4a58f240a..7cfa507956 100644 --- a/exercises/etl/example.tt +++ b/exercises/etl/example.tt @@ -2,16 +2,18 @@ require 'minitest/autorun' require_relative 'etl' # Test data version: <%= abbreviated_commit_hash %> -class EtlTest < Minitest::Test<% test_cases.each do |test_case| %> - def <%= test_case.test_name %> +class EtlTest < 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/lib/etl_cases.rb b/lib/etl_cases.rb index 210f75e4af..48bde9b9c5 100644 --- a/lib/etl_cases.rb +++ b/lib/etl_cases.rb @@ -1,10 +1,6 @@ -require 'exercise_cases' - -class EtlCase < OpenStruct - def test_name - 'test_%s' % description.tr(' ,-', '_').downcase - end +require 'generator/exercise_cases' +class EtlCase < ExerciseCase def workload [ "old = #{format_hash(integerize_keys(input))}", @@ -13,10 +9,6 @@ def workload ].join("\n") end - def skipped - index.zero? ? '# skip' : 'skip' - end - private def indent(size, text) @@ -40,9 +32,3 @@ def format_hash(hash) end end - -EtlCases = proc do |data| - JSON.parse(data)['transform']['cases'].map.with_index do |row, i| - EtlCase.new(row.merge(index: i)) - end -end From ec15c5b94290778e1019526bb3426132a60ce626 Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Thu, 27 Apr 2017 17:52:01 -0700 Subject: [PATCH 3/4] remove non custom template for etl --- exercises/etl/etl_test.rb | 4 +++- exercises/etl/example.tt | 19 ------------------- 2 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 exercises/etl/example.tt diff --git a/exercises/etl/etl_test.rb b/exercises/etl/etl_test.rb index 5a4865d242..2aeba1d515 100755 --- a/exercises/etl/etl_test.rb +++ b/exercises/etl/etl_test.rb @@ -1,7 +1,9 @@ +#!/usr/bin/env ruby +gem 'minitest', '>= 5.0.0' require 'minitest/autorun' require_relative 'etl' -# Test data version: ca9ed58 +# Common test data version: ca9ed58 class EtlTest < Minitest::Test def test_a_single_letter # skip diff --git a/exercises/etl/example.tt b/exercises/etl/example.tt deleted file mode 100644 index 7cfa507956..0000000000 --- a/exercises/etl/example.tt +++ /dev/null @@ -1,19 +0,0 @@ -require 'minitest/autorun' -require_relative 'etl' - -# Test data version: <%= abbreviated_commit_hash %> -class EtlTest < 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 From c6402c6be58f17746c688f327fc6858227d442ae Mon Sep 17 00:00:00 2001 From: Hilary Holz Date: Fri, 28 Apr 2017 14:14:39 -0700 Subject: [PATCH 4/4] keep integers integers! --- exercises/etl/etl_test.rb | 98 ++++++++++++++++----------------- lib/etl_cases.rb | 38 ++++++------- lib/generator/exercise_cases.rb | 4 +- 3 files changed, 65 insertions(+), 75 deletions(-) diff --git a/exercises/etl/etl_test.rb b/exercises/etl/etl_test.rb index 2aeba1d515..9b19cfc32e 100755 --- a/exercises/etl/etl_test.rb +++ b/exercises/etl/etl_test.rb @@ -8,87 +8,83 @@ class EtlTest < Minitest::Test def test_a_single_letter # skip old = { - '1' => ["A"], + 1 => ["A"] } expected = { - 'a' => '1', + 'a' => 1 } - assert_equal expected, ETL.transform(old) end def test_single_score_with_multiple_letters skip old = { - '1' => ["A", "E", "I", "O", "U"], + 1 => ["A", "E", "I", "O", "U"] } expected = { - 'a' => '1', - 'e' => '1', - 'i' => '1', - 'o' => '1', - 'u' => '1', + 'a' => 1, + 'e' => 1, + 'i' => 1, + 'o' => 1, + 'u' => 1 } - assert_equal expected, ETL.transform(old) end def test_multiple_scores_with_multiple_letters skip old = { - '1' => ["A", "E"], - '2' => ["D", "G"], + 1 => ["A", "E"], + 2 => ["D", "G"] } expected = { - 'a' => '1', - 'd' => '2', - 'e' => '1', - 'g' => '2', + 'a' => 1, + 'd' => 2, + 'e' => 1, + 'g' => 2 } - assert_equal expected, ETL.transform(old) end def test_multiple_scores_with_differing_numbers_of_letters skip old = { - '1' => ["A", "E", "I", "O", "U", "L", "N", "R", "S", "T"], - '2' => ["D", "G"], - '3' => ["B", "C", "M", "P"], - '4' => ["F", "H", "V", "W", "Y"], - '5' => ["K"], - '8' => ["J", "X"], - '10' => ["Q", "Z"], + 1 => ["A", "E", "I", "O", "U", "L", "N", "R", "S", "T"], + 2 => ["D", "G"], + 3 => ["B", "C", "M", "P"], + 4 => ["F", "H", "V", "W", "Y"], + 5 => ["K"], + 8 => ["J", "X"], + 10 => ["Q", "Z"] } expected = { - 'a' => '1', - 'b' => '3', - 'c' => '3', - 'd' => '2', - 'e' => '1', - 'f' => '4', - 'g' => '2', - 'h' => '4', - 'i' => '1', - 'j' => '8', - 'k' => '5', - 'l' => '1', - 'm' => '3', - 'n' => '1', - 'o' => '1', - 'p' => '3', - 'q' => '10', - 'r' => '1', - 's' => '1', - 't' => '1', - 'u' => '1', - 'v' => '4', - 'w' => '4', - 'x' => '8', - 'y' => '4', - 'z' => '10', + 'a' => 1, + 'b' => 3, + 'c' => 3, + 'd' => 2, + 'e' => 1, + 'f' => 4, + 'g' => 2, + 'h' => 4, + 'i' => 1, + 'j' => 8, + 'k' => 5, + 'l' => 1, + 'm' => 3, + 'n' => 1, + 'o' => 1, + 'p' => 3, + 'q' => 10, + 'r' => 1, + 's' => 1, + 't' => 1, + 'u' => 1, + 'v' => 4, + 'w' => 4, + 'x' => 8, + 'y' => 4, + 'z' => 10 } - assert_equal expected, ETL.transform(old) end diff --git a/lib/etl_cases.rb b/lib/etl_cases.rb index 48bde9b9c5..f348281dde 100644 --- a/lib/etl_cases.rb +++ b/lib/etl_cases.rb @@ -2,33 +2,27 @@ class EtlCase < ExerciseCase def workload - [ - "old = #{format_hash(integerize_keys(input))}", - " expected = #{format_hash(expected)}\n", - indent(4, assertion), - ].join("\n") + indent_lines([ + "old = {\n #{format(input)}\n }", + "expected = {\n #{format(expected)}\n }", + "assert_equal expected, ETL.transform(old)" + ], 4) end private - def indent(size, text) - text.lines.each_with_object('') { |line, obj| obj << ' ' * size + line } - end - - def assertion - "assert_equal expected, ETL.transform(old)" - end - - def integerize_keys(input) - input.reduce({}) { |hash, (k, v)| hash[k.to_i] = v; hash } - end - - def format_hash(hash) - middle = hash.each_pair.with_object('') do |(k, v), obj| - value = v.class == Array ? v : "'#{v}'" - obj << " '#{k}' => #{value},\n " + def format(obj) + case + when obj.respond_to?(:each_pair) + indent_lines( + obj.each_with_object([]) {|(k, v), string| string << "#{format(k)} => #{format(v)}" }, + 6, + ",\n" + ) + when obj.respond_to?(:each) then obj + when obj.to_s =~ /\d+/ then obj.to_i + else %Q('#{obj}') end - "{\n #{middle} }" end end diff --git a/lib/generator/exercise_cases.rb b/lib/generator/exercise_cases.rb index a4c6c99c0c..07c4e8a1f8 100644 --- a/lib/generator/exercise_cases.rb +++ b/lib/generator/exercise_cases.rb @@ -21,8 +21,8 @@ def skipped # "#{assert} Isogram.is_isogram?(string)" # ], 4 # ) - def indent_lines(code, depth) - code.join("\n" + ' ' * depth) + def indent_lines(code, depth, separator = "\n") + code.join(separator + ' ' * depth) end # used in workload, for example, as