diff --git a/README.md b/README.md index fc945c47b8..01e0f382f9 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,19 @@ the language, so you're all set. The files for an exercise live in `exercises/` (where `` is the slug for the exercise, e.g. `clock` or -`atbash-cipher`). An exercise has a test suite -(`exercises//_test.rb`) and an example solution -(`exercises//example.rb`). +`atbash-cipher`). All exercises have: + +* a test suite, `_test.rb` +* an example solution, `.rb`, in `.meta/solutions` + +Tests with a test generator will also have: + +* a `.version` +* the test generator, `_cases.rb`, in `.meta/generator` + +A few tests have other custom files which are discussed below. + +### Canonical Data **Most exercises can be generated from shared inputs/outputs, called canonical data (see [Generated Test Suites](#generated-test-suites) below).** To find out @@ -25,9 +35,9 @@ the [x-common repo](https://github.com/exercism/x-common/tree/master/exercises). ## Running the Tests -Run the tests using `rake`, rather than `ruby path/to/the_test.rb`. `rake` -knows to look for `example.rb` and to disable skips. Just tell `rake` the -name of your problem and you are set: +Run the tests using `rake`, rather than `ruby path/to/the_test.rb`. `rake` knows +to look for the example solution and to disable skips. Just tell `rake` the name +of your problem and you are set: ```sh rake test:clock @@ -211,7 +221,7 @@ We have created a minimal set of guidelines for the testing files, which you can take advantage of by installing the `rubocop` gem. It will use the configuration file located in the root folder, `.rubocop.yml`. When you edit your code, you can simply run `rubocop -D`. It will ignore -your `example.rb`, but will gently suggest style for your test code. +your example solution, but will gently suggest style for your test code. The `-D` option that is suggested is provided to give you the ability to easily ignore the Cops that you think should be ignored. This is easily diff --git a/lib/generator/files/track_files.rb b/lib/generator/files/track_files.rb index 09cf239744..e2f012f4c1 100644 --- a/lib/generator/files/track_files.rb +++ b/lib/generator/files/track_files.rb @@ -10,7 +10,7 @@ def tests_version end def example_solution - ExampleSolutionFile.new(filename: File.join(exercise_path, 'example.rb')) + ExampleSolutionFile.new(filename: File.join(exercise_path, example_file)) end def minitest_tests @@ -48,6 +48,18 @@ def tests_template_filename 'test_template.erb' end + def example_file + File.exist?(File.join(exercise_path, example_filename)) ? example_filename : legacy_example_filename + end + + def example_filename + File.join('.meta', 'solutions', "#{exercise_name}.rb") + end + + def legacy_example_filename + 'example.rb' + end + def minitest_tests_filename "#{exercise_name.gsub(/[ -]/, '_')}_test.rb" end diff --git a/lib/tasks/exercise.rb b/lib/tasks/exercise.rb index bcc61cd1fb..d0ab5e2817 100644 --- a/lib/tasks/exercise.rb +++ b/lib/tasks/exercise.rb @@ -23,7 +23,7 @@ def directory end def example_file - 'example.rb' + File.exist?(example_filename) ? example_filename : legacy_example_filename end def testable_example_file @@ -36,6 +36,14 @@ def test_file private + def example_filename + File.join('.meta', 'solutions', "#{name}.rb") + end + + def legacy_example_filename + 'example.rb' + end + def base_file_name @_base_file_name ||= name.tr('-', '_') end diff --git a/test/fixtures/xruby/exercises/alpha/example.rb b/test/fixtures/xruby/exercises/alpha/.meta/solutions/alpha.rb similarity index 100% rename from test/fixtures/xruby/exercises/alpha/example.rb rename to test/fixtures/xruby/exercises/alpha/.meta/solutions/alpha.rb diff --git a/test/generator/files/track_files_test.rb b/test/generator/files/track_files_test.rb index ea583f3911..482b103262 100644 --- a/test/generator/files/track_files_test.rb +++ b/test/generator/files/track_files_test.rb @@ -13,7 +13,7 @@ def initialize @paths = FixturePaths @exercise_name = 'alpha' end - attr_reader :paths, :exercise_name + attr_accessor :paths, :exercise_name include TrackFiles end @@ -24,7 +24,15 @@ def test_tests_version def test_example_solution subject = TestTrackFiles.new - assert_instance_of ExampleSolutionFile, subject.example_solution + expected_filename = FixturePaths.track + '/exercises/alpha/.meta/solutions/alpha.rb' + assert_equal expected_filename, subject.example_solution.filename + end + + def test_legacy_example_solution + subject = TestTrackFiles.new + subject.exercise_name = 'beta' + expected_filename = FixturePaths.track + '/exercises/beta/example.rb' + assert_equal expected_filename, subject.example_solution.filename end def test_minitest_tests @@ -38,6 +46,7 @@ def test_tests_template assert_equal expected_filename, subject.tests_template.filename end + class TestTrackFilesUseDefault def initialize @paths = FixturePaths @@ -75,7 +84,9 @@ def save(content) end def test_update_version - subject = TestExampleSolutionFile.new(filename: 'test/fixtures/xruby/exercises/alpha/example.rb') + subject = TestExampleSolutionFile.new( + filename: 'test/fixtures/xruby/exercises/alpha/.meta/solutions/alpha.rb' + ) assert_match(/VERSION = 2/, subject.update_version(2)) end end diff --git a/test/tasks/exercise_test.rb b/test/tasks/exercise_test.rb index 8a5838141a..d3cde01d29 100644 --- a/test/tasks/exercise_test.rb +++ b/test/tasks/exercise_test.rb @@ -31,6 +31,12 @@ def test_directory end def test_example_file + File.stub(:exist?, true) do + assert_equal '.meta/solutions/name.rb', Exercise.new('name').example_file + end + end + + def test_legacy_example_file assert_equal 'example.rb', Exercise.new('').example_file end diff --git a/test/tasks/exercise_tests_runner_legacy_test.rb b/test/tasks/exercise_tests_runner_legacy_test.rb new file mode 100644 index 0000000000..d21820e100 --- /dev/null +++ b/test/tasks/exercise_tests_runner_legacy_test.rb @@ -0,0 +1,64 @@ +require_relative '../test_helper' + +class FakeLegacyExercise + def name + 'test' + end + + alias :to_s :name + + def directory + 'test/.' + end + + def example_file + 'example.rb' + end + + def testable_example_file + 'test.rb' + end + + def test_file + 'test_test.rb' + end +end + +class ExerciseTestsRunnerLegacyTest < Minitest::Test + def test_run + Dir.stub :mktmpdir, nil, 'dir' do + cp_mock = Minitest::Mock.new.expect(:call, nil, ['test/.', 'dir']) + + mv_mock = Minitest::Mock.new.expect( + :call, + nil, + ['dir/example.rb', 'dir/test.rb'], + ) + + ruby_mock = Minitest::Mock.new.expect( + :call, + nil, + ['-I lib -r disable_skip.rb dir/test_test.rb -p'], + ) + + FileUtils.stub :cp_r, cp_mock do + FileUtils.stub :mv, mv_mock do + runner = ExerciseTestsRunner.new( + exercise: FakeLegacyExercise.new, + test_options: '-p', + ) + + runner.stub :ruby, ruby_mock do + assert_output "\n\n#{'-'*64}\nrunning tests for: test\n" do + runner.run + end + end + + cp_mock.verify + mv_mock.verify + ruby_mock.verify + end + end + end + end +end diff --git a/test/tasks/exercise_tests_runner_test.rb b/test/tasks/exercise_tests_runner_test.rb index b0b013b037..d789bcc078 100644 --- a/test/tasks/exercise_tests_runner_test.rb +++ b/test/tasks/exercise_tests_runner_test.rb @@ -12,7 +12,7 @@ def directory end def example_file - 'example.rb' + '.meta/solutions/test.rb' end def testable_example_file @@ -32,7 +32,7 @@ def test_run mv_mock = Minitest::Mock.new.expect( :call, nil, - ['dir/example.rb', 'dir/test.rb'], + ['dir/.meta/solutions/test.rb', 'dir/test.rb'], ) ruby_mock = Minitest::Mock.new.expect(