Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def initialize(track:, metadata:)
# Doesn't update the version information.
class GenerateTests < ImplementationDelegator
def call
create_tests_file
build_tests
end
end

Expand All @@ -24,7 +24,7 @@ class UpdateVersionAndGenerateTests < ImplementationDelegator
def call
update_tests_version
update_example_solution
create_tests_file
build_tests
end
end
end
10 changes: 7 additions & 3 deletions lib/generator/command_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def parse(args)
attr_reader :paths

def generators
implementations.map { |slug| generator(implementation(slug)) }
implementations.map { |slug| generator(implementation(exercise(slug))) }
end

def implementations
Expand All @@ -35,9 +35,13 @@ def freeze?
@options[:freeze] || @options[:all]
end

def implementation(slug)
def exercise(slug)
Exercise.new(slug: slug)
end

def implementation(exercise)
LoggingImplementation.new(
implementation: Implementation.new(paths: paths, slug: slug),
implementation: Implementation.new(paths: paths, exercise: exercise),
logger: logger
)
end
Expand Down
19 changes: 19 additions & 0 deletions lib/generator/exercise.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Generator
class Exercise
using Generator::Underscore

attr_reader :slug

def initialize(slug:)
@slug = slug
end

def name
@name ||= slug.underscore
end

def case_class
slug.camel_case + 'Case'
end
end
end
4 changes: 0 additions & 4 deletions lib/generator/files/generator_cases.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ def available(track_path)
cases_filepaths(track_path).map { |filepath| slugify(filepath) }.sort
end

def class_name(exercise_name_or_slug)
filename(exercise_name_or_slug).split('_').map(&:capitalize).join
end

def source_filepath(track_path, slug)
path = meta_generator_path(track_path, slug)
filename = filename(slug) + '.rb'
Expand Down
2 changes: 1 addition & 1 deletion lib/generator/files/metadata_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def canonical_data
private

def exercise_metadata_path
File.join(paths.metadata, 'exercises', slug)
File.join(paths.metadata, 'exercises', exercise.slug)
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/generator/files/track_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def tests_template
private

def exercise_path
File.join(paths.track, 'exercises', slug)
File.join(paths.track, 'exercises', exercise.slug)
end

def meta_path
Expand All @@ -34,15 +34,15 @@ def solutions_path
end

def minitest_tests_filename
"#{exercise_name}_test.rb"
"#{exercise.name}_test.rb"
end

def version_filename
'.version'
end

def example_filename
"#{exercise_name}.rb"
"#{exercise.name}.rb"
end

def tests_template_absolute_filename
Expand Down
18 changes: 7 additions & 11 deletions lib/generator/implementation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ class Implementation
include Files::MetadataFiles
include TemplateValuesFactory

def initialize(paths:, slug:)
def initialize(paths:, exercise:)
@paths = paths
@slug = slug
@exercise = exercise
end

attr_reader :paths, :slug
attr_reader :paths, :exercise

def version
tests_version.to_i
Expand All @@ -25,16 +25,12 @@ def update_example_solution
example_solution.update_version(version)
end

def create_tests_file
def build_tests
minitest_tests.generate(
template: tests_template.to_s,
values: template_values
)
end

def exercise_name
@exercise_name ||= slug.tr('-', '_')
end
end

# This exists to give us a clue as to what we are delegating to.
Expand All @@ -58,9 +54,9 @@ def update_example_solution
@logger.debug "Updated version in example solution to #{version}"
end

def create_tests_file
@implementation.create_tests_file
@logger.info "Generated #{slug} tests version #{version}"
def build_tests
@implementation.build_tests
@logger.info "Generated #{exercise.slug} tests version #{version}"
end
end
end
14 changes: 5 additions & 9 deletions lib/generator/template_values.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,26 @@ def template_values
abbreviated_commit_hash: canonical_data.abbreviated_commit_hash,
canonical_data_version: canonical_data.version,
version: version,
exercise_name: slug_underscore,
exercise_name: exercise.name,
test_cases: extract
)
end

private

def slug_underscore
slug ? slug.tr('-_', '_') : ''
end

def extract
load cases_load_name
extractor.cases(canonical_data.to_s)
end

def extractor
CaseValues::Extractor.new(
case_class: Object.const_get(Files::GeneratorCases.class_name(slug))
)
CaseValues::Extractor.new(
case_class: Object.const_get(exercise.case_class)
)
end

def cases_load_name
Files::GeneratorCases.source_filepath(paths.track, slug)
Files::GeneratorCases.source_filepath(paths.track, exercise.slug)
end
end
end
4 changes: 4 additions & 0 deletions lib/generator/underscore.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ module Underscore
def underscore
downcase.gsub(/[- ]/, '_').gsub(/[^\w?]/, '')
end

def camel_case
underscore.split('_').map(&:capitalize).join
end
end

refine Fixnum do
Expand Down
6 changes: 3 additions & 3 deletions test/fixtures/xruby/lib/generator/test_template.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env ruby
require 'minitest/autorun'
require_relative 'acronym'
require_relative '<%= exercise_name %>'

# Common test data version: <%= abbreviated_commit_hash %>
class AcronymTest < Minitest::Test
# Common test data version: <%= canonical_data_version %> <%= abbreviated_commit_hash %>
class <%= exercise_name_camel %>Test < Minitest::Test
<% test_cases.each_with_index do |test_case, idx| %>
def <%= test_case.name %>
<%= test_case.skipped(idx) %>
Expand Down
20 changes: 20 additions & 0 deletions test/generator/exercise_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require_relative '../test_helper'

module Generator
class ExerciseTest < Minitest::Test
def test_slug
exercise = Exercise.new(slug: 'alpha')
assert_equal 'alpha', exercise.slug
end

def test_name
exercise = Exercise.new(slug: 'alpha-beta')
assert_equal 'alpha_beta', exercise.name
end

def test_case_class
exercise = Exercise.new(slug: 'alpha-beta')
assert_equal 'AlphaBetaCase', exercise.case_class
end
end
end
4 changes: 0 additions & 4 deletions test/generator/files/generate_cases_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ def test_available_calls_glob_with_the_right_arguments
mock_glob_call.verify
end

def test_class_name
assert_equal 'TwoParterCase', GeneratorCases.class_name('two-parter')
end

def test_source_filepath
track_path = '/track'
slug = 'slug'
Expand Down
4 changes: 2 additions & 2 deletions test/generator/files/metadata_files_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class MetadataFilesTest < Minitest::Test
class TestMetadataFiles
def initialize
@paths = FixturePaths
@slug = 'alpha'
@exercise = Exercise.new(slug: 'alpha')
end
attr_reader :paths, :slug
attr_reader :paths, :exercise
include MetadataFiles
end

Expand Down
9 changes: 4 additions & 5 deletions test/generator/files/track_files_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ class TrackFilesTest < Minitest::Test
class TestTrackFiles
def initialize
@paths = FixturePaths
@slug = 'alpha-beta'
@exercise_name = 'alpha_beta'
@exercise = Exercise.new(slug: 'alpha-beta')
end
attr_accessor :paths, :slug, :exercise_name
attr_reader :paths, :exercise
include TrackFiles
end

Expand Down Expand Up @@ -44,9 +43,9 @@ def test_tests_template
class TestTrackFilesUseDefault
def initialize
@paths = FixturePaths
@slug = 'notemplate'
@exercise = Exercise.new(slug: 'notemplate')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there room here to use 'no template' or if necessary 'no_template'?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. It would need to be no-template. This will need to happen later though as I'm trying not to mess with the pre-existing commits.

end
attr_reader :paths, :slug
attr_reader :paths, :exercise
include TrackFiles
end

Expand Down
32 changes: 12 additions & 20 deletions test/generator/implementation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@ class ImplementationTest < Minitest::Test
)

def test_version
subject = Implementation.new(paths: FixturePaths, slug: 'alpha')
exercise = Minitest::Mock.new.expect :slug, 'alpha'
subject = Implementation.new(paths: FixturePaths, exercise: exercise)
assert_equal 1, subject.version
end

def test_slug
subject = Implementation.new(paths: FixturePaths, slug: 'alpha')
assert_equal 'alpha', subject.slug
end

def test_update_tests_version
mock_file = Minitest::Mock.new.expect :write, '2'.length, [2]
subject = Implementation.new(paths: FixturePaths, slug: 'alpha')
subject = Implementation.new(paths: FixturePaths, exercise: Exercise.new(slug: 'alpha'))
# Verify iniital condition from fixture file
assert_equal 1, subject.tests_version.to_i
File.stub(:open, true, mock_file) do
Expand All @@ -31,14 +27,14 @@ def test_update_tests_version
def test_update_example_solution
expected_content = "# This is the example\n\nclass BookKeeping\n VERSION = 1\nend\n"
mock_file = Minitest::Mock.new.expect :write, expected_content.length, [expected_content]
subject = Implementation.new(paths: FixturePaths, slug: 'alpha')
subject = Implementation.new(paths: FixturePaths, exercise: Exercise.new(slug: 'alpha'))
File.stub(:open, true, mock_file) do
assert_equal expected_content, subject.update_example_solution
end
mock_file.verify
end

def test_create_tests_file
def test_build_tests
# Q: Is the pain here caused by:
# a) Implementation `including` everything rather than using composition?
# b) Trying to verify the expected content.
Expand Down Expand Up @@ -84,34 +80,30 @@ def test_bookkeeping
end
TESTS_FILE
mock_file = Minitest::Mock.new.expect :write, expected_content.length, [expected_content]
subject = Implementation.new(paths: FixturePaths, slug: 'alpha')
subject = Implementation.new(paths: FixturePaths, exercise: Exercise.new(slug: 'alpha'))
GitCommand.stub(:abbreviated_commit_hash, '123456789') do
File.stub(:open, true, mock_file) do
assert_equal expected_content, subject.create_tests_file
assert_equal expected_content, subject.build_tests
end
end
mock_file.verify
# Don't pollute the namespace
Object.send(:remove_const, :AlphaCase)
end

def test_exercise_name
subject = Implementation.new(paths: FixturePaths, slug: 'alpha-beta')
assert_equal 'alpha_beta', subject.exercise_name
end
end

class LoggingImplementationTest < Minitest::Test
def test_create_tests_file
def test_build_tests
exercise = Exercise.new(slug: 'alpha')
mock_implementation = Minitest::Mock.new
mock_implementation.expect :create_tests_file, nil
mock_implementation.expect :slug, 'alpha'
mock_implementation.expect :build_tests, nil
mock_implementation.expect :exercise, exercise
mock_implementation.expect :version, 2
mock_logger = Minitest::Mock.new
mock_logger.expect :info, nil, ['Generated alpha tests version 2']

subject = LoggingImplementation.new(implementation: mock_implementation, logger: mock_logger)
subject.create_tests_file
subject.build_tests

mock_implementation.verify
end
Expand Down
Loading