-
-
Notifications
You must be signed in to change notification settings - Fork 531
grains: add test generator #514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,14 @@ | ||
| module BookKeeping | ||
| VERSION = 1 | ||
| end | ||
|
|
||
| module Grains | ||
| def self.square(number) | ||
| fail ArgumentError if number <= 0 || number > 64 | ||
| 2**(number - 1) | ||
| end | ||
|
|
||
| def self.total | ||
| square(65) - 1 | ||
| 2**64 - 1 | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of the change to the square method, calling
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is fine. |
||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| require 'minitest/autorun' | ||
| require_relative 'grains' | ||
|
|
||
| # Test data version: <%= sha1 %> | ||
| class GrainsTest < 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,45 +1,81 @@ | ||
| #!/usr/bin/env ruby | ||
| gem 'minitest', '>= 5.0.0' | ||
| require 'minitest/autorun' | ||
| require_relative 'grains' | ||
|
|
||
| # Test data version: aa12f2e | ||
| class GrainsTest < Minitest::Test | ||
| def test_square_1 | ||
| def test_1 | ||
| # skip | ||
| assert_equal 1, Grains.square(1) | ||
| end | ||
|
|
||
| def test_square_2 | ||
| def test_2 | ||
| skip | ||
| assert_equal 2, Grains.square(2) | ||
| end | ||
|
|
||
| def test_square_3 | ||
| def test_3 | ||
| skip | ||
| assert_equal 4, Grains.square(3) | ||
| end | ||
|
|
||
| def test_square_4 | ||
| def test_4 | ||
| skip | ||
| assert_equal 8, Grains.square(4) | ||
| end | ||
|
|
||
| def test_square_16 | ||
| def test_16 | ||
| skip | ||
| assert_equal 32_768, Grains.square(16) | ||
| end | ||
|
|
||
| def test_square_32 | ||
| def test_32 | ||
| skip | ||
| assert_equal 2_147_483_648, Grains.square(32) | ||
| end | ||
|
|
||
| def test_square_64 | ||
| def test_64 | ||
| skip | ||
| assert_equal 9_223_372_036_854_775_808, Grains.square(64) | ||
| end | ||
|
|
||
| def test_total_grains | ||
| def test_square_0_raises_an_exception | ||
| skip | ||
| assert_raises(ArgumentError) { Grains.square(0) } | ||
| end | ||
|
|
||
| def test_negative_square_raises_an_exception | ||
| skip | ||
| assert_raises(ArgumentError) { Grains.square(-1) } | ||
| end | ||
|
|
||
| def test_square_greater_than_64_raises_an_exception | ||
| skip | ||
| assert_raises(ArgumentError) { Grains.square(65) } | ||
| end | ||
|
|
||
| def test_returns_the_total_number_of_grains_on_the_board | ||
| skip | ||
| assert_equal 18_446_744_073_709_551_615, Grains.total | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| class GrainsCase < OpenStruct | ||
| def test_name | ||
| 'test_%s' % description.downcase.tr_s(' ', '_') | ||
| end | ||
|
|
||
| def workload | ||
| fail NotImplementedError | ||
| end | ||
|
|
||
| def skipped | ||
| index.zero? ? '# skip' : 'skip' | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def underscore_format(number) | ||
| number.to_s.reverse.gsub(/...(?=.)/,'\&_').reverse | ||
| 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 | ||
| "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)) | ||
| end | ||
|
|
||
| cases << GrainsCase::TotalMethod.new( | ||
| data['total'].merge('index' => cases.size) | ||
| ) | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| require_relative 'test_helper' | ||
|
|
||
| class GrainsTest < Minitest::Test | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like that you're unit testing the Hopefully doing this will help you realise which methods should be part of some kind of |
||
| 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 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to make an adjustment to the implementation because the shared test data includes some error cases that weren't in the original ruby implementation.
How does this work with book keeping when it wasn't there originally? Normally, I'm assuming we would bump the
BookKeeping::VERSION, but this exercise wasn't using book keeping yet.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The adjustment looks reasonable.
BookKeeping is related to the tests, so you might need to add it in so that the example.rb still passes the tests.