From 9e9977a939cd84a0e3da8634803fd9432c77db45 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 11:05:11 +0100 Subject: [PATCH 01/26] lib/generator.rb: Ignore blank template lines. (#479) If you have a template that contains a value that might be nil or an empty string such as: ``` <%= test_case.comment %> ``` You often do not want a blank line appear in the output if there is no comment. This patch changes the ERB setttings so that these blank lines are not included in the output. This may cause minor issues where this behaviour has been relied on such as templates that expect a Ruby syntax related 'end' to insert a blank line. ``` <% end %> ``` But these are easily fixed by inserting a new blank line into the template. Technical details: It does this by setting the ERB *trim_mode* to '<>' '<>' omits newline for lines starting with <% and ending in %> See also: http://ruby-doc.org/stdlib-2.1.1/libdoc/erb/rdoc/ERB.html#method-c-new --- lib/generator.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/generator.rb b/lib/generator.rb index 48360e56cd..bf3bee1a10 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -64,7 +64,8 @@ def check_metadata_repository_exists def generate_test_file File.open(path_to("#{name.gsub(/[ -]/, '_')}_test.rb"), 'w') do |f| - f.write ERB.new(File.read(path_to('example.tt'))).result binding + template = File.read(path_to('example.tt')) + f.write ERB.new(template, nil, '<>').result binding end end From 209852558d01075dcc96f1e590d8597d8527322a Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 18:36:29 +0000 Subject: [PATCH 02/26] Regenerated based on updated xcommon data. --- exercises/isogram/.version | 2 +- exercises/isogram/example.rb | 2 +- exercises/isogram/isogram_test.rb | 44 +++++++++++-------------------- 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/exercises/isogram/.version b/exercises/isogram/.version index d00491fd7e..d8263ee986 100644 --- a/exercises/isogram/.version +++ b/exercises/isogram/.version @@ -1 +1 @@ -1 +2 \ No newline at end of file diff --git a/exercises/isogram/example.rb b/exercises/isogram/example.rb index e2b9e3d440..3f03e418dc 100644 --- a/exercises/isogram/example.rb +++ b/exercises/isogram/example.rb @@ -1,5 +1,5 @@ module BookKeeping - VERSION = 1 + VERSION = 2 end class Isogram diff --git a/exercises/isogram/isogram_test.rb b/exercises/isogram/isogram_test.rb index 238c8bd83a..b672323df7 100755 --- a/exercises/isogram/isogram_test.rb +++ b/exercises/isogram/isogram_test.rb @@ -4,68 +4,55 @@ require 'minitest/autorun' require_relative 'isogram' -# Common test data version: c1cb73f +# Common test data version: 2adfe21 class IsogramTest < Minitest::Test - def test_duplicates + def test_empty_string_has_no_duplicates # skip + string = '' + assert Isogram.is_isogram?(string) + end + + def test_isogram_with_only_lower_case_characters + skip string = 'duplicates' assert Isogram.is_isogram?(string) end - def test_eleven + def test_word_with_one_duplicated_character skip string = 'eleven' refute Isogram.is_isogram?(string) end - def test_subdermatoglyphic + def test_longest_reported_english_isogram skip string = 'subdermatoglyphic' assert Isogram.is_isogram?(string) end - def test_alphabet + def test_word_with_duplicated_character_in_mixed_case skip string = 'Alphabet' refute Isogram.is_isogram?(string) end - def test_thumbscrew_japingly + def test_hypothetical_isogrammic_word_with_hyphen skip string = 'thumbscrew-japingly' assert Isogram.is_isogram?(string) end - def test_hjelmqvist_gryb_zock_pfund_wax + def test_isogram_with_duplicated_non_letter_character skip string = 'Hjelmqvist-Gryb-Zock-Pfund-Wax' assert Isogram.is_isogram?(string) end - def test_heizölrückstoßabdämpfung - skip - string = 'Heizölrückstoßabdämpfung' - assert Isogram.is_isogram?(string) - end - - def test_the_quick_brown_fox - skip - string = 'the quick brown fox' - refute Isogram.is_isogram?(string) - end - - def test_emily_jung_schwartzkopf + def test_made_up_name_that_is_an_isogram skip string = 'Emily Jung Schwartzkopf' assert Isogram.is_isogram?(string) end - - def test_éléphant - skip - string = 'éléphant' - 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, @@ -82,9 +69,8 @@ def test_éléphant # # 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 From ea9dc16ad88aa91a87d95824f6bc0d00f3088eac Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 18:39:00 +0000 Subject: [PATCH 03/26] Don't increment the version here. --- exercises/isogram/example.tt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index acdd7a80d7..aa4b5a3876 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -15,6 +15,6 @@ class IsogramTest < Minitest::Test<% test_cases.each do |test_case| %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> def test_bookkeeping skip - assert_equal <%= version.next %>, BookKeeping::VERSION + assert_equal <%= version %>, BookKeeping::VERSION end end From a14029093769ee369f412867a33515a4906cce09 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 18:58:25 +0000 Subject: [PATCH 04/26] Generate whole test body in generator. --- exercises/isogram/example.tt | 6 ++--- lib/isogram_cases.rb | 48 ++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index aa4b5a3876..9e73182d4b 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -6,10 +6,8 @@ require_relative 'isogram' # Common test data version: <%= sha1 %> 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.method_definition %> +<%= test_case.workload %> end <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 4e042ef693..bdda89d033 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -1,13 +1,46 @@ -class IsogramCase < OpenStruct +require 'ostruct' - def name - format('test_%s', description) +class TestCase + attr_reader :data + def initialize(json_data) + @data = OpenStruct.new(json_data) end - def description - input.downcase.gsub(/[ -]/,'_') + def method_definition + format 'def %s', test_name end + def test_name + format 'test_%s', @data['description'].downcase.tr_s(' -','_') + end + + def workload + body = skip, + format( "string = '%s'", data.input ), + format( "%s Isogram.is_isogram?(string)", assertion) + [indent( body ),nil].join("\n") + end + + def indent(array, count=4 ) + array.map { |line| format "%s%s", ' ' * count, line } + end +end + +class IsogramCase < TestCase + + def input + data.input + end + + def index + data.index + end + + def expected + data.expected + end + + def assertion expected ? 'assert' : 'refute' end @@ -18,7 +51,8 @@ def skip end IsogramCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |row, i| - IsogramCase.new(row.merge('index' => i)) + JSON.parse(data)['cases'].map.with_index do |test_case,index| + test_case['index'] = index + IsogramCase.new(test_case) end end From 3e0d0e582c0fa24c40c108bd2c3113057350134c Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 19:01:39 +0000 Subject: [PATCH 05/26] Add spaces around bookkeeping comment. --- exercises/isogram/example.tt | 5 ++++- exercises/isogram/isogram_test.rb | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index 9e73182d4b..18aa1609fb 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -5,12 +5,15 @@ require 'minitest/autorun' require_relative 'isogram' # Common test data version: <%= sha1 %> -class IsogramTest < Minitest::Test<% test_cases.each do |test_case| %> +class IsogramTest < Minitest::Test +<% test_cases.each do |test_case| %> <%= test_case.method_definition %> <%= 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 b672323df7..07fba76d4c 100755 --- a/exercises/isogram/isogram_test.rb +++ b/exercises/isogram/isogram_test.rb @@ -53,6 +53,7 @@ def test_made_up_name_that_is_an_isogram string = 'Emily Jung Schwartzkopf' assert 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,6 +70,7 @@ 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 From f9d2ba0f0c833e69c6c93dfe1a0c66bed885ec09 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 19:09:13 +0000 Subject: [PATCH 06/26] Generate the whole test in the generator --- exercises/isogram/example.tt | 4 +--- lib/isogram_cases.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index 18aa1609fb..828f6b0436 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -7,9 +7,7 @@ require_relative 'isogram' # Common test data version: <%= sha1 %> class IsogramTest < Minitest::Test <% test_cases.each do |test_case| %> - <%= test_case.method_definition %> -<%= test_case.workload %> - end +<%= test_case.full_method %> <% end %> <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index bdda89d033..063b804c4c 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -10,6 +10,10 @@ def method_definition format 'def %s', test_name end + def method_end + 'end' + end + def test_name format 'test_%s', @data['description'].downcase.tr_s(' -','_') end @@ -21,6 +25,11 @@ def workload [indent( body ),nil].join("\n") end + def full_method + bla = [indent([method_definition],2), workload.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" + # .join("\n") + end + def indent(array, count=4 ) array.map { |line| format "%s%s", ' ' * count, line } end From 3d616a9f5b5edba8244ea50803f3669aa43b56e1 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 19:59:56 +0000 Subject: [PATCH 07/26] Remove redundant code. --- lib/isogram_cases.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 063b804c4c..bbbb02f048 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -26,8 +26,7 @@ def workload end def full_method - bla = [indent([method_definition],2), workload.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" - # .join("\n") + [indent([method_definition],2), workload.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" end def indent(array, count=4 ) From c78a049915e4f7b694189c2e7f83283d86fe28f7 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:00:11 +0000 Subject: [PATCH 08/26] Move bookkeeping comment into generator. --- exercises/isogram/example.tt | 4 ++-- lib/generator.rb | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index 828f6b0436..fc8505da72 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -7,10 +7,10 @@ require_relative 'isogram' # Common test data version: <%= sha1 %> class IsogramTest < Minitest::Test <% test_cases.each do |test_case| %> -<%= test_case.full_method %> +<%= test_case.full_method %> <% end %> -<%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> +<%= test_version %> def test_bookkeeping skip diff --git a/lib/generator.rb b/lib/generator.rb index bf3bee1a10..75480e0e14 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -38,6 +38,10 @@ def test_cases cases.call(data) end + def test_version + IO.read(XRUBY_LIB + '/bookkeeping.md') + end + def metadata_repository_missing_message <<-EOM.gsub(/^ {6}/, '') @@ -51,8 +55,8 @@ def metadata_repository_missing_message def generate check_metadata_repository_exists generate_test_file - increment_version - increment_version_in_example + # increment_version + # increment_version_in_example end def check_metadata_repository_exists From a38141c2534a537e8413d8993d1b4474ab63138d Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:21:48 +0000 Subject: [PATCH 09/26] Move Bookeeping gerneration into generator. --- exercises/isogram/example.tt | 7 +----- lib/generator.rb | 18 +++++++++++++-- lib/isogram_cases.rb | 44 ++++-------------------------------- lib/testcase.rb | 37 ++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 47 deletions(-) create mode 100644 lib/testcase.rb diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index fc8505da72..1b5ca992cb 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -10,10 +10,5 @@ class IsogramTest < Minitest::Test <%= test_case.full_method %> <% end %> -<%= test_version %> - - def test_bookkeeping - skip - assert_equal <%= version %>, BookKeeping::VERSION - end +<%= test_version_bookkeeping %> end diff --git a/lib/generator.rb b/lib/generator.rb index 75480e0e14..91a66c9e8c 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -4,6 +4,8 @@ require 'json' require 'ostruct' +require_relative 'testcase' + class Generator METADATA_REPOSITORY = 'x-common'.freeze @@ -38,8 +40,20 @@ def test_cases cases.call(data) end - def test_version - IO.read(XRUBY_LIB + '/bookkeeping.md') + class BookKeeping < TestCase + def assertion + 'assert_equal 2, BookKeeping::VERSION' + end + end + + def test_version_bookkeeping + comment = IO.read(XRUBY_LIB + '/bookkeeping.md') + bla = BookKeeping.new( { + 'description' => 'bookkeeping', + 'index' => -1 + } ) + + [comment, "\n", bla.full_method].join end def metadata_repository_missing_message diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index bbbb02f048..34fbad0c2e 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -1,38 +1,5 @@ require 'ostruct' - -class TestCase - attr_reader :data - def initialize(json_data) - @data = OpenStruct.new(json_data) - end - - def method_definition - format 'def %s', test_name - end - - def method_end - 'end' - end - - def test_name - format 'test_%s', @data['description'].downcase.tr_s(' -','_') - end - - def workload - body = skip, - format( "string = '%s'", data.input ), - format( "%s Isogram.is_isogram?(string)", assertion) - [indent( body ),nil].join("\n") - end - - def full_method - [indent([method_definition],2), workload.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" - end - - def indent(array, count=4 ) - array.map { |line| format "%s%s", ' ' * count, line } - end -end +require_relative 'testcase' class IsogramCase < TestCase @@ -48,14 +15,13 @@ def expected data.expected end - def assertion - expected ? 'assert' : 'refute' + [ + format( "string = '%s'", data.input ), + format( "%s Isogram.is_isogram?(string)", expected ? 'assert' : 'refute') + ] end - def skip - index.zero? ? '# skip' : 'skip' - end end IsogramCases = proc do |data| diff --git a/lib/testcase.rb b/lib/testcase.rb new file mode 100644 index 0000000000..4a237f87af --- /dev/null +++ b/lib/testcase.rb @@ -0,0 +1,37 @@ +class TestCase + attr_reader :data + def initialize(json_data) + @data = OpenStruct.new(json_data) + end + + def method_definition + format 'def %s', test_name + end + + def skip + data.index.zero? ? '# skip' : 'skip' + end + + def method_end + 'end' + end + + def test_name + format 'test_%s', @data['description'].downcase.tr_s(' -','_') + end + + def workload + body = [skip, assertion].flatten + [indent( body ),nil].join("\n") + end + + def full_method + [indent([method_definition],2), workload.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" + end + + def indent(array, count=4 ) + array.map { |line| format "%s%s", ' ' * count, line } + end +end + + From 22697ca62339e9e5e7f550fc35f4fee76def602d Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:24:37 +0000 Subject: [PATCH 10/26] Rename assertion to workload --- lib/generator.rb | 2 +- lib/isogram_cases.rb | 16 ++-------------- lib/testcase.rb | 6 +++--- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/lib/generator.rb b/lib/generator.rb index 91a66c9e8c..c327a0f128 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -41,7 +41,7 @@ def test_cases end class BookKeeping < TestCase - def assertion + def workload 'assert_equal 2, BookKeeping::VERSION' end end diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 34fbad0c2e..8b79411467 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -3,22 +3,10 @@ class IsogramCase < TestCase - def input - data.input - end - - def index - data.index - end - - def expected - data.expected - end - - def assertion + def workload [ format( "string = '%s'", data.input ), - format( "%s Isogram.is_isogram?(string)", expected ? 'assert' : 'refute') + format( "%s Isogram.is_isogram?(string)", data.expected ? 'assert' : 'refute') ] end diff --git a/lib/testcase.rb b/lib/testcase.rb index 4a237f87af..01ee0d82ad 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -20,13 +20,13 @@ def test_name format 'test_%s', @data['description'].downcase.tr_s(' -','_') end - def workload - body = [skip, assertion].flatten + def method_body + body = [skip, workload].flatten [indent( body ),nil].join("\n") end def full_method - [indent([method_definition],2), workload.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" + [indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" end def indent(array, count=4 ) From dbd5210fb8d8f8d58352c0211593fd5083325306 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:36:54 +0000 Subject: [PATCH 11/26] add canonical_data alias --- lib/isogram_cases.rb | 11 ++++++----- lib/testcase.rb | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 8b79411467..86f5f748d4 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -1,19 +1,20 @@ -require 'ostruct' require_relative 'testcase' class IsogramCase < TestCase - def workload [ - format( "string = '%s'", data.input ), - format( "%s Isogram.is_isogram?(string)", data.expected ? 'assert' : 'refute') + "string = '#{canonical_data.input}'", + "#{assertion} Isogram.is_isogram?(string)" ] end + def assertion + canonical_data.expected ? 'assert' : 'refute' + end end IsogramCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |test_case,index| + JSON.parse(data)['cases'].map.with_index do |test_case,index| test_case['index'] = index IsogramCase.new(test_case) end diff --git a/lib/testcase.rb b/lib/testcase.rb index 01ee0d82ad..40e5680316 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -4,6 +4,10 @@ def initialize(json_data) @data = OpenStruct.new(json_data) end + def canonical_data + data + end + def method_definition format 'def %s', test_name end From 671643dcc3198c60860fc8a8825d404983498f67 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:40:06 +0000 Subject: [PATCH 12/26] Add to_s to TestCase that returns the full test --- exercises/isogram/example.tt | 2 +- lib/testcase.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index 1b5ca992cb..81d68e3085 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -7,7 +7,7 @@ require_relative 'isogram' # Common test data version: <%= sha1 %> class IsogramTest < Minitest::Test <% test_cases.each do |test_case| %> -<%= test_case.full_method %> +<%= test_case %> <% end %> <%= test_version_bookkeeping %> diff --git a/lib/testcase.rb b/lib/testcase.rb index 40e5680316..a2a8bdfdc4 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -33,6 +33,10 @@ def full_method [indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" end + def to_s + full_method + end + def indent(array, count=4 ) array.map { |line| format "%s%s", ' ' * count, line } end From 5ea23bf8ce2a96ec81c5e16012709a21eba4a581 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:46:43 +0000 Subject: [PATCH 13/26] Rename data to canonical data --- lib/testcase.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/testcase.rb b/lib/testcase.rb index a2a8bdfdc4..96c67a1e40 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -1,11 +1,7 @@ class TestCase - attr_reader :data + attr_reader :canonical_data def initialize(json_data) - @data = OpenStruct.new(json_data) - end - - def canonical_data - data + @canonical_data = OpenStruct.new(json_data) end def method_definition @@ -13,7 +9,7 @@ def method_definition end def skip - data.index.zero? ? '# skip' : 'skip' + canonical_data.index.zero? ? '# skip' : 'skip' end def method_end @@ -21,7 +17,7 @@ def method_end end def test_name - format 'test_%s', @data['description'].downcase.tr_s(' -','_') + format 'test_%s', canonical_data.description.downcase.tr_s(' -','_') end def method_body From cc9af614af70e0f1cb7ec8fb3ee5fec12185a22f Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 20:58:53 +0000 Subject: [PATCH 14/26] Move the index out of the canonical data Add comment to test case. --- exercises/isogram/example.tt | 6 +++--- lib/generator.rb | 14 +++++++------- lib/isogram_cases.rb | 3 +-- lib/testcase.rb | 20 ++++++++++++-------- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/exercises/isogram/example.tt b/exercises/isogram/example.tt index 81d68e3085..9b58e2c8c3 100644 --- a/exercises/isogram/example.tt +++ b/exercises/isogram/example.tt @@ -6,9 +6,9 @@ require_relative 'isogram' # Common test data version: <%= sha1 %> class IsogramTest < Minitest::Test -<% test_cases.each do |test_case| %> -<%= test_case %> +<% test_cases.each_with_index do |test_case,index| %> +<%= test_case.render(index) %> <% end %> -<%= test_version_bookkeeping %> +<%= test_version_bookkeeping.render %> end diff --git a/lib/generator.rb b/lib/generator.rb index c327a0f128..5d9d54c6c7 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -41,19 +41,19 @@ def test_cases end class BookKeeping < TestCase + + def comment + IO.read(XRUBY_LIB + '/bookkeeping.md') + end + def workload 'assert_equal 2, BookKeeping::VERSION' end end def test_version_bookkeeping - comment = IO.read(XRUBY_LIB + '/bookkeeping.md') - bla = BookKeeping.new( { - 'description' => 'bookkeeping', - 'index' => -1 - } ) - - [comment, "\n", bla.full_method].join + BookKeeping.new( { 'description' => 'bookkeeping' } ) +# [comment, "\n", bla.full_method].join end def metadata_repository_missing_message diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 86f5f748d4..85b51f9338 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -14,8 +14,7 @@ def assertion end IsogramCases = proc do |data| - JSON.parse(data)['cases'].map.with_index do |test_case,index| - test_case['index'] = index + JSON.parse(data)['cases'].map do |test_case| IsogramCase.new(test_case) end end diff --git a/lib/testcase.rb b/lib/testcase.rb index 96c67a1e40..ea87bc2aeb 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -1,15 +1,20 @@ class TestCase attr_reader :canonical_data + def initialize(json_data) @canonical_data = OpenStruct.new(json_data) end + def comment + nil + end + def method_definition format 'def %s', test_name end def skip - canonical_data.index.zero? ? '# skip' : 'skip' + @index == 0 ? '# skip' : 'skip' end def method_end @@ -22,20 +27,19 @@ def test_name def method_body body = [skip, workload].flatten - [indent( body ),nil].join("\n") + [indent(body),nil].join("\n") end def full_method - [indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.join("\n") + "\n" + [comment,indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.compact.join("\n") + "\n" end - def to_s + def render(index = -1) + @index = index full_method end - def indent(array, count=4 ) - array.map { |line| format "%s%s", ' ' * count, line } + def indent(array, count = 4) + array.map { |line| line ? ' ' * count + line : nil } end end - - From c1273283ff06651c77749e7d2040d6c15c8a928c Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 21:09:10 +0000 Subject: [PATCH 15/26] Make IsogramCases a class rather than a proc --- lib/generator.rb | 10 ++++------ lib/isogram_cases.rb | 20 +++++++++++++++++--- lib/testcase.rb | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/generator.rb b/lib/generator.rb index 5d9d54c6c7..2a66afd085 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -16,7 +16,6 @@ def initialize(name, cases) end def metadata_dir - # rubocop:disable Metrics/LineLength File.expand_path(File.join('..', '..', '..', METADATA_REPOSITORY, 'exercises', name), __FILE__) end @@ -37,11 +36,10 @@ def sha1 end def test_cases - cases.call(data) + cases.new(data).to_a end class BookKeeping < TestCase - def comment IO.read(XRUBY_LIB + '/bookkeeping.md') end @@ -52,8 +50,8 @@ def workload end def test_version_bookkeeping - BookKeeping.new( { 'description' => 'bookkeeping' } ) -# [comment, "\n", bla.full_method].join + BookKeeping.new('description' => 'bookkeeping') + # [comment, "\n", bla.full_method].join end def metadata_repository_missing_message @@ -76,7 +74,7 @@ def generate def check_metadata_repository_exists unless File.directory?(metadata_dir) STDERR.puts metadata_repository_missing_message - fail Errno::ENOENT.new(metadata_dir) + raise Errno::ENOENT, metadata_dir end end diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 85b51f9338..6e474121ac 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -13,8 +13,22 @@ def assertion end end -IsogramCases = proc do |data| - JSON.parse(data)['cases'].map do |test_case| - IsogramCase.new(test_case) +class IsogramCases + def initialize(data) + @data = data + end + + def parsed_json_cases + JSON.parse(@data)['cases'] + end + + def to_a + parsed_json_cases.map { |test_case| IsogramCase.new(test_case) } end end + +# IsogramCases = proc do |data| +# JSON.parse(data)['cases'].map do |test_case| +# IsogramCase.new(test_case) +# end +# end diff --git a/lib/testcase.rb b/lib/testcase.rb index ea87bc2aeb..ca04a793aa 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -14,7 +14,7 @@ def method_definition end def skip - @index == 0 ? '# skip' : 'skip' + @index.zero? ? '# skip' : 'skip' end def method_end From 44bad1c375afc1f78ceed8fc2b61fbc183ed8194 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 21:20:37 +0000 Subject: [PATCH 16/26] Added generic TestCases class --- lib/isogram_cases.rb | 22 +++------------------- lib/testcase.rb | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 6e474121ac..304149a69e 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -1,5 +1,8 @@ require_relative 'testcase' +class IsogramCases < TestCases +end + class IsogramCase < TestCase def workload [ @@ -13,22 +16,3 @@ def assertion end end -class IsogramCases - def initialize(data) - @data = data - end - - def parsed_json_cases - JSON.parse(@data)['cases'] - end - - def to_a - parsed_json_cases.map { |test_case| IsogramCase.new(test_case) } - end -end - -# IsogramCases = proc do |data| -# JSON.parse(data)['cases'].map do |test_case| -# IsogramCase.new(test_case) -# end -# end diff --git a/lib/testcase.rb b/lib/testcase.rb index ca04a793aa..d549c7f6d3 100644 --- a/lib/testcase.rb +++ b/lib/testcase.rb @@ -1,3 +1,24 @@ +class TestCases + attr_reader :cases_key + def initialize(json_data, cases_key = 'cases') + @data = json_data + @cases_key = cases_key + end + + def case_classname + classname = self.class.to_s.sub(/Cases$/,'Case') + Object.const_get(classname) + end + + def parsed_json_cases + JSON.parse(@data)[cases_key] + end + + def to_a + parsed_json_cases.map { |test_case| case_classname.new(test_case) } + end +end + class TestCase attr_reader :canonical_data From a3587f5d6d328d97f811745e5481b3b15d508817 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 21:27:51 +0000 Subject: [PATCH 17/26] Add test failure message. --- exercises/isogram/isogram_test.rb | 16 ++++++++-------- lib/isogram_cases.rb | 12 +++++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/exercises/isogram/isogram_test.rb b/exercises/isogram/isogram_test.rb index 07fba76d4c..3fd914d4cc 100755 --- a/exercises/isogram/isogram_test.rb +++ b/exercises/isogram/isogram_test.rb @@ -9,49 +9,49 @@ class IsogramTest < Minitest::Test def test_empty_string_has_no_duplicates # skip string = '' - assert Isogram.is_isogram?(string) + assert Isogram.is_isogram?(string), '"" is an isogram' end def test_isogram_with_only_lower_case_characters skip string = 'duplicates' - assert Isogram.is_isogram?(string) + assert Isogram.is_isogram?(string), '"duplicates" is an isogram' end def test_word_with_one_duplicated_character skip string = 'eleven' - refute Isogram.is_isogram?(string) + refute Isogram.is_isogram?(string), '"eleven" is NOT an isogram' end def test_longest_reported_english_isogram skip string = 'subdermatoglyphic' - assert Isogram.is_isogram?(string) + assert Isogram.is_isogram?(string), '"subdermatoglyphic" is an isogram' end def test_word_with_duplicated_character_in_mixed_case skip string = 'Alphabet' - refute Isogram.is_isogram?(string) + refute Isogram.is_isogram?(string), '"Alphabet" is NOT an isogram' end def test_hypothetical_isogrammic_word_with_hyphen skip string = 'thumbscrew-japingly' - assert Isogram.is_isogram?(string) + assert Isogram.is_isogram?(string), '"thumbscrew-japingly" is an isogram' end def test_isogram_with_duplicated_non_letter_character skip string = 'Hjelmqvist-Gryb-Zock-Pfund-Wax' - assert Isogram.is_isogram?(string) + assert Isogram.is_isogram?(string), '"Hjelmqvist-Gryb-Zock-Pfund-Wax" is an isogram' end def test_made_up_name_that_is_an_isogram skip string = 'Emily Jung Schwartzkopf' - assert Isogram.is_isogram?(string) + assert Isogram.is_isogram?(string), '"Emily Jung Schwartzkopf" is an isogram' end # Problems in exercism evolve over time, as we find better ways to ask diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index 304149a69e..a806cc81b3 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -7,10 +7,20 @@ class IsogramCase < TestCase def workload [ "string = '#{canonical_data.input}'", - "#{assertion} Isogram.is_isogram?(string)" + "#{assertion} Isogram.is_isogram?(string), '#{failure_message}'" ] end + private + + def failure_message + "#{canonical_data.input.inspect} #{is_or_isnt} an isogram" + end + + def is_or_isnt + canonical_data.expected ? 'is' : 'is NOT' + end + def assertion canonical_data.expected ? 'assert' : 'refute' end From d2acb90557c7cce98dda0508f1f32ff1bc9e805e Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 21:33:09 +0000 Subject: [PATCH 18/26] Rename method to `isogram?` --- exercises/isogram/isogram_test.rb | 16 ++++++++-------- lib/isogram_cases.rb | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/exercises/isogram/isogram_test.rb b/exercises/isogram/isogram_test.rb index 3fd914d4cc..f366477e11 100755 --- a/exercises/isogram/isogram_test.rb +++ b/exercises/isogram/isogram_test.rb @@ -9,49 +9,49 @@ class IsogramTest < Minitest::Test def test_empty_string_has_no_duplicates # skip string = '' - assert Isogram.is_isogram?(string), '"" is an isogram' + assert Isogram.isogram?(string), '"" is an isogram' end def test_isogram_with_only_lower_case_characters skip string = 'duplicates' - assert Isogram.is_isogram?(string), '"duplicates" is an isogram' + assert Isogram.isogram?(string), '"duplicates" is an isogram' end def test_word_with_one_duplicated_character skip string = 'eleven' - refute Isogram.is_isogram?(string), '"eleven" is NOT an isogram' + refute Isogram.isogram?(string), '"eleven" is NOT an isogram' end def test_longest_reported_english_isogram skip string = 'subdermatoglyphic' - assert Isogram.is_isogram?(string), '"subdermatoglyphic" is an isogram' + assert Isogram.isogram?(string), '"subdermatoglyphic" is an isogram' end def test_word_with_duplicated_character_in_mixed_case skip string = 'Alphabet' - refute Isogram.is_isogram?(string), '"Alphabet" is NOT an isogram' + refute Isogram.isogram?(string), '"Alphabet" is NOT an isogram' end def test_hypothetical_isogrammic_word_with_hyphen skip string = 'thumbscrew-japingly' - assert Isogram.is_isogram?(string), '"thumbscrew-japingly" is an isogram' + assert Isogram.isogram?(string), '"thumbscrew-japingly" is an isogram' end def test_isogram_with_duplicated_non_letter_character skip string = 'Hjelmqvist-Gryb-Zock-Pfund-Wax' - assert Isogram.is_isogram?(string), '"Hjelmqvist-Gryb-Zock-Pfund-Wax" is an isogram' + assert Isogram.isogram?(string), '"Hjelmqvist-Gryb-Zock-Pfund-Wax" is an isogram' end def test_made_up_name_that_is_an_isogram skip string = 'Emily Jung Schwartzkopf' - assert Isogram.is_isogram?(string), '"Emily Jung Schwartzkopf" is an isogram' + assert Isogram.isogram?(string), '"Emily Jung Schwartzkopf" is an isogram' end # Problems in exercism evolve over time, as we find better ways to ask diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index a806cc81b3..d8dff502b1 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -7,7 +7,7 @@ class IsogramCase < TestCase def workload [ "string = '#{canonical_data.input}'", - "#{assertion} Isogram.is_isogram?(string), '#{failure_message}'" + "#{assertion} Isogram.isogram?(string), '#{failure_message}'" ] end From 091bf9f722b1ce3c54755171dbacf019be4a8110 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sat, 5 Nov 2016 23:29:08 +0000 Subject: [PATCH 19/26] Created tests Did some other stuff. --- lib/exercise_testcase.rb | 57 +++++++++++++++++++++++++++ lib/exercise_testcases.rb | 20 ++++++++++ lib/generator.rb | 5 ++- lib/isogram_cases.rb | 10 ++--- lib/testcase.rb | 66 -------------------------------- tests/exercise_testcase_test.rb | 42 ++++++++++++++++++++ tests/exercise_testcases_test.rb | 14 +++++++ tests/isogram_cases_test.rb | 17 ++++++++ tests/test_helper.rb | 9 +++++ 9 files changed, 166 insertions(+), 74 deletions(-) create mode 100644 lib/exercise_testcase.rb create mode 100644 lib/exercise_testcases.rb delete mode 100644 lib/testcase.rb create mode 100644 tests/exercise_testcase_test.rb create mode 100644 tests/exercise_testcases_test.rb create mode 100644 tests/isogram_cases_test.rb create mode 100644 tests/test_helper.rb diff --git a/lib/exercise_testcase.rb b/lib/exercise_testcase.rb new file mode 100644 index 0000000000..d78d96176a --- /dev/null +++ b/lib/exercise_testcase.rb @@ -0,0 +1,57 @@ +class ExerciseTestCase + attr_reader :canonical_data + + def initialize(canonical_data) + @canonical_data = OpenStruct.new(canonical_data) + end + + def render(index = -1) + @index = index + full_method + end + + def full_method + [comment,indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.compact.join("\n") + "\n" + end + + def comment + nil + end + + def description + canonical_data.description || '' + end + + def method_definition + "def #{test_name}" + end + + def method_end + 'end' + end + + + def skip + @index.zero? ? '# skip' : 'skip' + end + + def test_name + "test_#{description_as_test_name}" + end + + def description_as_test_name + description.downcase.tr_s(' -','_') + end + + def method_body + body = [skip, workload].flatten + [indent(body,4),nil].join("\n") + end + + def workload + end + + def indent(array, count) + array.map { |line| line ? ' ' * count + line : nil } + end +end diff --git a/lib/exercise_testcases.rb b/lib/exercise_testcases.rb new file mode 100644 index 0000000000..9653f89720 --- /dev/null +++ b/lib/exercise_testcases.rb @@ -0,0 +1,20 @@ +class ExerciseTestCases + attr_reader :cases_key + def initialize(json_data) + @data = json_data + @cases_key = 'cases' + end + + def case_classname + classname = self.class.to_s.sub(/Cases$/,'Case') + Object.const_get(classname) + end + + def parsed_json_cases + JSON.parse(@data)[cases_key] + end + + def to_a + parsed_json_cases.map { |test_case| case_classname.new(test_case) } + end +end diff --git a/lib/generator.rb b/lib/generator.rb index 2a66afd085..2ad0292f82 100644 --- a/lib/generator.rb +++ b/lib/generator.rb @@ -4,7 +4,8 @@ require 'json' require 'ostruct' -require_relative 'testcase' +require_relative 'exercise_testcases' +require_relative 'exercise_testcase' class Generator METADATA_REPOSITORY = 'x-common'.freeze @@ -39,7 +40,7 @@ def test_cases cases.new(data).to_a end - class BookKeeping < TestCase + class BookKeeping < ExerciseTestCase def comment IO.read(XRUBY_LIB + '/bookkeeping.md') end diff --git a/lib/isogram_cases.rb b/lib/isogram_cases.rb index d8dff502b1..7f08e5dd30 100644 --- a/lib/isogram_cases.rb +++ b/lib/isogram_cases.rb @@ -1,9 +1,10 @@ -require_relative 'testcase' +require_relative 'exercise_testcases' +require_relative 'exercise_testcase' -class IsogramCases < TestCases +class IsogramCases < ExerciseTestCases end -class IsogramCase < TestCase +class IsogramCase < ExerciseTestCase def workload [ "string = '#{canonical_data.input}'", @@ -11,8 +12,6 @@ def workload ] end - private - def failure_message "#{canonical_data.input.inspect} #{is_or_isnt} an isogram" end @@ -25,4 +24,3 @@ def assertion canonical_data.expected ? 'assert' : 'refute' end end - diff --git a/lib/testcase.rb b/lib/testcase.rb deleted file mode 100644 index d549c7f6d3..0000000000 --- a/lib/testcase.rb +++ /dev/null @@ -1,66 +0,0 @@ -class TestCases - attr_reader :cases_key - def initialize(json_data, cases_key = 'cases') - @data = json_data - @cases_key = cases_key - end - - def case_classname - classname = self.class.to_s.sub(/Cases$/,'Case') - Object.const_get(classname) - end - - def parsed_json_cases - JSON.parse(@data)[cases_key] - end - - def to_a - parsed_json_cases.map { |test_case| case_classname.new(test_case) } - end -end - -class TestCase - attr_reader :canonical_data - - def initialize(json_data) - @canonical_data = OpenStruct.new(json_data) - end - - def comment - nil - end - - def method_definition - format 'def %s', test_name - end - - def skip - @index.zero? ? '# skip' : 'skip' - end - - def method_end - 'end' - end - - def test_name - format 'test_%s', canonical_data.description.downcase.tr_s(' -','_') - end - - def method_body - body = [skip, workload].flatten - [indent(body),nil].join("\n") - end - - def full_method - [comment,indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.compact.join("\n") + "\n" - end - - def render(index = -1) - @index = index - full_method - end - - def indent(array, count = 4) - array.map { |line| line ? ' ' * count + line : nil } - end -end diff --git a/tests/exercise_testcase_test.rb b/tests/exercise_testcase_test.rb new file mode 100644 index 0000000000..2d1b365639 --- /dev/null +++ b/tests/exercise_testcase_test.rb @@ -0,0 +1,42 @@ +require_relative 'test_helper' +require 'exercise_testcase' + +class ExerciseTestCaseTest < Minitest::Test + def test_can_be_created + subject = ExerciseTestCase.new nil + assert subject.instance_of? ExerciseTestCase + end + + def test_render + subject = ExerciseTestCase.new nil + expected = " def test_\n skip\n end\n" + assert_equal expected, subject.render + end + + def dont_test_can_get_data + data = { 'key' => 'value' } + expected = OpenStruct.new(data) + subject = ExerciseTestCase.new(data) + assert_equal expected, subject.canonical_data + end + + def dont_test_test_name_from_description + data = { 'description' => 'from_description' } + subject = ExerciseTestCase.new(data) + assert_equal 'test_from_description', subject.test_name + end + + def dont_test_test_name_from_description_replaces_spaces + data = { 'description' => 'from description with spaces' } + subject = ExerciseTestCase.new(data) + assert_equal 'test_from_description_with_spaces', subject.test_name + end + + def dont_test_test_name_from_description_replaces_hyphens + data = { 'description' => 'from-description-with-hyphens' } + subject = ExerciseTestCase.new(data) + assert_equal 'test_from_description_with_hyphens', subject.test_name + end + + +end diff --git a/tests/exercise_testcases_test.rb b/tests/exercise_testcases_test.rb new file mode 100644 index 0000000000..f75cbd2f51 --- /dev/null +++ b/tests/exercise_testcases_test.rb @@ -0,0 +1,14 @@ +require_relative 'test_helper' +require 'exercise_testcases' +require 'exercise_testcase' +require 'json' + +class ExerciseTestCasesTest < Minitest::Test + def test_initialistion + some_json = JSON.generate(cases: [{ 'description' => 'first' },{ description: 'second' }]) + subject = ExerciseTestCases.new(some_json) + result = subject.to_a + assert_equal 2, result.size + assert_equal ExerciseTestCase, result.first.class + end +end diff --git a/tests/isogram_cases_test.rb b/tests/isogram_cases_test.rb new file mode 100644 index 0000000000..cdb9a1f45f --- /dev/null +++ b/tests/isogram_cases_test.rb @@ -0,0 +1,17 @@ +require_relative 'test_helper' +require 'isogram_cases' + +class IsogramCaseTest < Minitest::Test + def test_can_create_a_whole_test + data = { description: 'isogram is an isogram', input: 'isogram', expected: true } + subject = IsogramCase.new(data) + expected = < Date: Sat, 5 Nov 2016 23:49:11 +0000 Subject: [PATCH 20/26] Get coverage info on everything in lib --- tests/test_helper.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_helper.rb b/tests/test_helper.rb index fecef6575a..80b24741cf 100644 --- a/tests/test_helper.rb +++ b/tests/test_helper.rb @@ -5,5 +5,8 @@ require 'minitest/autorun' + $LOAD_PATH.push(File.expand_path('../../lib',__FILE__)) -#p $LOAD_PATH + +# So we can be sure we have coverage on the whole lib directory: +Dir.glob('lib/*.rb').each {|file| require file.gsub(/(^lib\/|\.rb$)/,'') } From 5d77f2e79b1a4a9f862a143c4e66444b6959b9f8 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sun, 6 Nov 2016 00:20:09 +0000 Subject: [PATCH 21/26] Tidy up ExerciseTestCase a bit. --- lib/exercise_testcase.rb | 25 ++++++++++++++----------- tests/exercise_testcase_test.rb | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/exercise_testcase.rb b/lib/exercise_testcase.rb index d78d96176a..c35ee47829 100644 --- a/lib/exercise_testcase.rb +++ b/lib/exercise_testcase.rb @@ -7,11 +7,15 @@ def initialize(canonical_data) def render(index = -1) @index = index - full_method + [comment, *full_method].compact.join("\n") + "\n" end def full_method - [comment,indent([method_definition],2), method_body.split("\n"), indent([method_end],2)].flatten.compact.join("\n") + "\n" + indent( [ + method_definition, + *method_body, + method_end + ], 2) end def comment @@ -26,10 +30,13 @@ def method_definition "def #{test_name}" end - def method_end - 'end' + def method_body + indent( [skip, *workload], 2) end + def method_end + "end" + end def skip @index.zero? ? '# skip' : 'skip' @@ -43,15 +50,11 @@ def description_as_test_name description.downcase.tr_s(' -','_') end - def method_body - body = [skip, workload].flatten - [indent(body,4),nil].join("\n") - end - def workload + "assert #{@canonical_data.expected.inspect}, Subject.method #{@canonical_data.input.inspect}" end - def indent(array, count) - array.map { |line| line ? ' ' * count + line : nil } + def indent(lines, count) + lines.compact.map { |line| ' ' * count + line } end end diff --git a/tests/exercise_testcase_test.rb b/tests/exercise_testcase_test.rb index 2d1b365639..536075e52e 100644 --- a/tests/exercise_testcase_test.rb +++ b/tests/exercise_testcase_test.rb @@ -9,7 +9,7 @@ def test_can_be_created def test_render subject = ExerciseTestCase.new nil - expected = " def test_\n skip\n end\n" + expected = " def test_\n skip\n assert nil, Subject.method nil\n end\n" assert_equal expected, subject.render end From 68a5dec57bc2d0744478de967c2d9012196bfe0e Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sun, 6 Nov 2016 09:32:20 +0000 Subject: [PATCH 22/26] Group test cases in coverage report. --- tests/test_helper.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_helper.rb b/tests/test_helper.rb index 80b24741cf..6c38278221 100644 --- a/tests/test_helper.rb +++ b/tests/test_helper.rb @@ -1,6 +1,10 @@ require 'simplecov' SimpleCov.start do add_filter "/tests/" + add_group "Utilities" do |file| + !(file.filename =~ /_cases\.rb$/) + end + add_group "Cases", "_cases.rb" end require 'minitest/autorun' From b23e0b61b4bccc3decc20153d4c5e3db135045e9 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sun, 6 Nov 2016 09:43:41 +0000 Subject: [PATCH 23/26] Add rake and simplecov for beter testing. --- Gemfile | 2 ++ Rakefile | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 Rakefile diff --git a/Gemfile b/Gemfile index c2bc80e179..79f5775b3f 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,5 @@ source 'https://rubygems.org' gem 'minitest' gem 'rubocop', '0.36.0' +gem 'simplecov' +gem 'rake' diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000000..d93b680454 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +require 'rake' +require 'rake/testtask' + +Rake::TestTask.new do |task| + task.pattern = 'tests/*_test.rb' +end From 3f258358dc0a9aa24af9948db7bfda3665f00e18 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sun, 6 Nov 2016 09:47:06 +0000 Subject: [PATCH 24/26] Update method name. --- exercises/isogram/example.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/isogram/example.rb b/exercises/isogram/example.rb index 3f03e418dc..fac7fb8862 100644 --- a/exercises/isogram/example.rb +++ b/exercises/isogram/example.rb @@ -3,7 +3,7 @@ module BookKeeping end class Isogram - def self.is_isogram?(str) + def self.isogram?(str) letters = str.downcase.gsub(/[[:punct:]]| /, '').chars letters == letters.uniq end From fe35f2dfe93a3bdd9a848b56cf16a3daf76b2006 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sun, 6 Nov 2016 09:48:14 +0000 Subject: [PATCH 25/26] Only test /exercises/* tests for executability. --- bin/executable-tests-check | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/executable-tests-check b/bin/executable-tests-check index 490a58a2e2..771f9d0331 100755 --- a/bin/executable-tests-check +++ b/bin/executable-tests-check @@ -3,7 +3,7 @@ require 'minitest/autorun' # Assume that this file lives in #{base}/bin base = File.join(__dir__,'..') -files = Dir.glob("#{base}/**/*test.rb") + Dir.glob("#{base}/bin/*") +files = Dir.glob("#{base}/exercises/**/*test.rb") + Dir.glob("#{base}/bin/*") files.each do |file| describe file do From 1e54c30f13cbe584a37a0b3bcd636eb17c8b7f39 Mon Sep 17 00:00:00 2001 From: Geoff Hubbard Date: Sun, 6 Nov 2016 09:59:38 +0000 Subject: [PATCH 26/26] Add 'Guard' for automatically running tests. --- Gemfile | 7 +++++++ Guardfile | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 Guardfile diff --git a/Gemfile b/Gemfile index 79f5775b3f..8bcffa5cdd 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,13 @@ source 'https://rubygems.org' +ruby '2.2.5' + gem 'minitest' gem 'rubocop', '0.36.0' gem 'simplecov' gem 'rake' + +# These are not strictly necessary, but I use them to automatically run the +# tests whenever I edit a file. +gem 'guard' +gem 'guard-shell' diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000000..6b169849d1 --- /dev/null +++ b/Guardfile @@ -0,0 +1,39 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +interactor :off + +# Add files and commands to this file, like the example: +# watch(%r{file/path}) { `command(s)` } +# +guard :shell do + watch(/(lib|tests\/)(.*)\.rb$/) do |m| + file = m[0] + puts "File changed: #{file}" + test_file = file[/_test\.rb/] ? file : file.sub(/\.rb/, '_test.rb') + commands = + "bundle exec rake test", + "bundle exec rubocop -D #{file}" + generator = + "bin/generate isogram", + "git --no-pager diff exercises/isogram/isogram_test.rb" + command = commands.join(' && ') + p command + system(command) + system(generator.join(' && ')) + end +end