trackler 2.0.6.1 → 2.0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/go/exercises/word-count/cases_test.go +23 -4
  4. data/tracks/go/exercises/word-count/example.go +6 -2
  5. data/tracks/go/exercises/word-count/word_count.go +1 -1
  6. data/tracks/go/exercises/word-count/word_count_test.go +1 -1
  7. data/tracks/pony/.travis.yml +16 -4
  8. data/tracks/pony/bin/install-deps +12 -0
  9. data/tracks/pony/bin/test-exercises +22 -0
  10. data/tracks/ruby/Gemfile +1 -0
  11. data/tracks/ruby/Rakefile +1 -1
  12. data/tracks/ruby/bin/generate +4 -29
  13. data/tracks/ruby/exercises/all-your-base/.meta/.version +1 -0
  14. data/tracks/ruby/exercises/all-your-base/all_your_base_test.rb +50 -60
  15. data/tracks/ruby/exercises/all-your-base/example.rb +13 -8
  16. data/tracks/ruby/exercises/all-your-base/example.tt +17 -0
  17. data/tracks/ruby/lib/all_your_base_cases.rb +109 -0
  18. data/tracks/ruby/lib/generator.rb +21 -100
  19. data/tracks/ruby/lib/generator/command_line.rb +119 -0
  20. data/tracks/ruby/lib/generator/files.rb +58 -0
  21. data/tracks/ruby/lib/generator/files/metadata_files.rb +22 -0
  22. data/tracks/ruby/lib/generator/files/track_files.rb +83 -0
  23. data/tracks/ruby/lib/generator/git_command.rb +8 -0
  24. data/tracks/ruby/lib/generator/repository.rb +62 -0
  25. data/tracks/ruby/lib/generator/template_values.rb +47 -0
  26. data/tracks/ruby/lib/helper.rb +5 -2
  27. data/tracks/ruby/test/fixtures/metadata/exercises/alpha/canonical-data.json +8 -9
  28. data/tracks/ruby/test/fixtures/{exercises → xruby/exercises}/alpha/.meta/.version +0 -0
  29. data/tracks/ruby/test/fixtures/{exercises → xruby/exercises}/alpha/example.rb +0 -0
  30. data/tracks/ruby/test/fixtures/xruby/exercises/alpha/example.tt +20 -0
  31. data/tracks/ruby/test/fixtures/xruby/lib/alpha_cases.rb +20 -0
  32. data/tracks/ruby/test/fixtures/xruby/lib/beta_cases.rb +0 -0
  33. data/tracks/ruby/test/generator/command_line_test.rb +83 -0
  34. data/tracks/ruby/test/generator/files/metadata_files_test.rb +25 -0
  35. data/tracks/ruby/test/generator/files/track_files_test.rb +117 -0
  36. data/tracks/ruby/test/generator/files_test.rb +63 -0
  37. data/tracks/ruby/test/generator/git_command_test.rb +9 -0
  38. data/tracks/ruby/test/generator/repository_test.rb +98 -0
  39. data/tracks/ruby/test/generator/template_values_test.rb +59 -0
  40. data/tracks/ruby/test/generator_test.rb +19 -63
  41. data/tracks/ruby/test/test_helper.rb +8 -5
  42. metadata +26 -6
  43. data/tracks/ruby/test/fixtures/exercises/alpha/alpha_test.rb +0 -1
  44. data/tracks/ruby/test/fixtures/exercises/alpha/example.tt +0 -1
@@ -0,0 +1,83 @@
1
+ require 'erb'
2
+
3
+ module Generator
4
+ module Files
5
+ module GeneratorCases
6
+ module_function
7
+
8
+ def available(track_path)
9
+ generator_glob = File.join(track_path, 'lib', '*_cases.rb')
10
+ Dir[generator_glob].sort.map { |filename| exercise_name(filename) }
11
+ end
12
+
13
+ def filename(exercise_name)
14
+ "#{exercise_name.tr('-','_')}_cases"
15
+ end
16
+
17
+ def proc_name(exercise_name)
18
+ filename(exercise_name).split('_').map(&:capitalize).join
19
+ end
20
+
21
+ def exercise_name(filename)
22
+ %r{([^/]*)_cases\.rb$}.match(filename).captures[0].tr('_','-')
23
+ end
24
+ end
25
+
26
+ module TrackFiles
27
+ include Exercise
28
+
29
+ def tests_version
30
+ TestsVersionFile.new(filename: File.join(exercise_path, '.meta', '.version'))
31
+ end
32
+
33
+ def example_solution
34
+ ExampleSolutionFile.new(filename: File.join(exercise_path, 'example.rb'))
35
+ end
36
+
37
+ def minitest_tests
38
+ MinitestTestsFile.new(filename: File.join(exercise_path, minitest_tests_filename))
39
+ end
40
+
41
+ def tests_template
42
+ TestsTemplateFile.new(filename: File.join(exercise_path, 'example.tt'))
43
+ end
44
+
45
+ private
46
+
47
+ def exercise_path
48
+ File.join(paths.track, 'exercises', exercise_name)
49
+ end
50
+
51
+ def minitest_tests_filename
52
+ "#{exercise_name.gsub(/[ -]/, '_')}_test.rb"
53
+ end
54
+ end
55
+
56
+ class TestsVersionFile < Writable
57
+ def to_i
58
+ to_s.to_i
59
+ end
60
+
61
+ def increment
62
+ save(to_i + 1)
63
+ end
64
+ end
65
+
66
+ class ExampleSolutionFile < Writable
67
+ def update_version(version)
68
+ content = to_s.gsub(/VERSION = \d+/, "VERSION = #{version}")
69
+ save(content)
70
+ end
71
+ end
72
+
73
+ class MinitestTestsFile < Writable
74
+ def generate(template:,values:)
75
+ content = ERB.new(template, nil, '<>').result values.get_binding
76
+ save(content)
77
+ end
78
+ end
79
+
80
+ class TestsTemplateFile < Readable
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,8 @@
1
+ module Generator
2
+ # Wrap git shell commands.
3
+ class GitCommand
4
+ def self.abbreviated_commit_hash(git_path, repository_relative_path)
5
+ `git --git-dir=#{git_path} log -1 --pretty=format:'%h' -- #{repository_relative_path}`
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,62 @@
1
+ require 'delegate'
2
+
3
+ module Generator
4
+ class Repository
5
+ include Files::TrackFiles
6
+ include Files::MetadataFiles
7
+ include TemplateValuesFactory
8
+
9
+ def initialize(paths:, exercise_name:)
10
+ @paths = paths
11
+ @exercise_name = exercise_name
12
+ end
13
+
14
+ attr_reader :paths, :exercise_name
15
+
16
+ def version
17
+ tests_version.to_i
18
+ end
19
+
20
+ def update_tests_version
21
+ tests_version.increment
22
+ end
23
+
24
+ def update_example_solution
25
+ example_solution.update_version(version)
26
+ end
27
+
28
+ def create_tests_file
29
+ minitest_tests.generate(
30
+ template: tests_template.to_s,
31
+ values: template_values
32
+ )
33
+ end
34
+ end
35
+
36
+ # A repository that also logs its progress.
37
+ class LoggingRepository < Repository
38
+ def initialize(paths:, exercise_name:, logger:)
39
+ super(paths: paths, exercise_name: exercise_name)
40
+ @logger = logger
41
+ end
42
+
43
+ def update_tests_version
44
+ super
45
+ @logger.info "Incremented tests version to #{version}"
46
+ end
47
+
48
+ def update_example_solution
49
+ super
50
+ @logger.info "Updated version in example solution to #{version}"
51
+ end
52
+
53
+ def create_tests_file
54
+ super
55
+ @logger.info "Generated tests for #{exercise_name}"
56
+ end
57
+ end
58
+
59
+ # This exists to give us a clue as to what we are delegating to.
60
+ class RepositoryDelegator < SimpleDelegator
61
+ end
62
+ end
@@ -0,0 +1,47 @@
1
+ module Generator
2
+ # Contains methods accessible to the ERB template
3
+ class TemplateValues
4
+ attr_reader :sha1, :version, :test_cases
5
+
6
+ def initialize(sha1:, version:, test_cases:)
7
+ @sha1 = sha1
8
+ @version = version
9
+ @test_cases = test_cases
10
+ end
11
+
12
+ def get_binding
13
+ binding
14
+ end
15
+ end
16
+
17
+ module TemplateValuesFactory
18
+ def template_values
19
+ # These are needed by the 'ExerciseCases' classes
20
+ # TODO: move these into the individual classes
21
+ require 'ostruct'
22
+ require 'json'
23
+ require cases_require_name
24
+
25
+ # Compensate for the version.next that appears in template files.
26
+ # TODO: remove the .next from the template files and remove compensation
27
+ compensated_version = version - 1
28
+
29
+ TemplateValues.new(
30
+ # TODO: rename sha1 to abbreviated_commit_hash
31
+ sha1: canonical_data.abbreviated_commit_hash,
32
+ version: compensated_version,
33
+ test_cases: test_cases_proc.call(canonical_data.to_s)
34
+ )
35
+ end
36
+
37
+ private
38
+
39
+ def cases_require_name
40
+ Files::GeneratorCases.filename(exercise_name)
41
+ end
42
+
43
+ def test_cases_proc
44
+ Object.const_get(Files::GeneratorCases.proc_name(exercise_name))
45
+ end
46
+ end
47
+ end
@@ -1,2 +1,5 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- XRUBY_LIB = File.dirname(__FILE__).freeze
1
+ XRUBY_ROOT = File.join(File.dirname(__FILE__), '..').freeze
2
+ XRUBY_LIB = File.join(XRUBY_ROOT, 'lib').freeze
3
+ METADATA_REPOSITORY_PATH = File.join(XRUBY_ROOT, '..', 'x-common').freeze
4
+
5
+ $LOAD_PATH.unshift(XRUBY_LIB)
@@ -1,11 +1,10 @@
1
1
  {
2
- "solve": {
3
- "description": "Test canonical data",
4
- "cases": [
5
- {
6
- "description": "add 2 numbers",
7
- "input": [1,1],
8
- "expected": 2
9
- },
10
- }
2
+ "description": "Test canonical data",
3
+ "cases": [
4
+ {
5
+ "description": "add 2 numbers",
6
+ "input": [1,1],
7
+ "expected": 2
8
+ }
9
+ ]
11
10
  }
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'minitest/autorun'
5
+ require_relative 'alpha'
6
+
7
+ # Common test data version: <%= sha1 %>
8
+ class AlphaTest < Minitest::Test<% test_cases.each do |test_case| %>
9
+ def <%= test_case.name %>
10
+ <%= test_case.skip %>
11
+ string = '<%= test_case.input %>'
12
+ <%= test_case.assertion %> Alpha.something?(string)
13
+ end
14
+ <% end %>
15
+ <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %>
16
+ def test_bookkeeping
17
+ skip
18
+ assert_equal <%= version.next %>, BookKeeping::VERSION
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ class AlphaCase < OpenStruct
2
+
3
+ def name
4
+ format('test_%s', description.downcase.gsub(/[ -]/,'_'))
5
+ end
6
+
7
+ def assertion
8
+ expected ? 'assert' : 'refute'
9
+ end
10
+
11
+ def skip
12
+ index.zero? ? '# skip' : 'skip'
13
+ end
14
+ end
15
+
16
+ AlphaCases = proc do |data|
17
+ JSON.parse(data)['cases'].map.with_index do |row, i|
18
+ AlphaCase.new(row.merge('index' => i))
19
+ end
20
+ end
@@ -0,0 +1,83 @@
1
+ require_relative '../test_helper'
2
+
3
+ module Generator
4
+ class CommandLineTest < Minitest::Test
5
+ FixturePaths = Paths.new(
6
+ metadata: 'test/fixtures/metadata',
7
+ track: 'test/fixtures/xruby'
8
+ )
9
+
10
+ def test_parse
11
+ expected_stderr = 'Exercise name required'
12
+ assert_output(/Usage:/, /#{expected_stderr}/) do
13
+ refute CommandLine.new(FixturePaths).parse([])
14
+ end
15
+ end
16
+
17
+ def test_invalid_metadata_repository_outputs_message_to_stderr
18
+ paths = Paths.new(metadata: 'test/fixtures/nonexistent', track: nil)
19
+ expected_stderr = <<-MESSAGE.gsub(/^ {6}/,'')
20
+ 'x-common' repository not found.
21
+ Try running the command:
22
+ git clone https://github.com/exercism/x-common.git "test/fixtures/nonexistent"
23
+ MESSAGE
24
+ assert_output nil, /#{expected_stderr}/ do
25
+ refute CommandLine.new(paths).parse([])
26
+ end
27
+ end
28
+
29
+ def test_usage_help
30
+ args = %w(-h)
31
+ assert_output(/Usage:/, nil) do
32
+ refute CommandLine.new(FixturePaths).parse(args)
33
+ end
34
+ end
35
+
36
+ def test_usage_help_with_exercise
37
+ args = %w(-h beta)
38
+ assert_output(/Usage:/, nil) do
39
+ refute CommandLine.new(FixturePaths).parse(args)
40
+ end
41
+ end
42
+
43
+ def test_usage_help_includes_available_generators
44
+ args = %w(-h)
45
+ fake_generators = %w(some fake generator names also-hyphen-ated)
46
+ Files::GeneratorCases.stub :available, fake_generators do
47
+ assert_output(/#{fake_generators.sort.join(' ')}/, nil) do
48
+ refute CommandLine.new(FixturePaths).parse(args)
49
+ end
50
+ end
51
+ end
52
+
53
+ def test_validate_missing_generator
54
+ args = %w(nonexistent)
55
+ Files::GeneratorCases.stub :available, [] do
56
+ assert_output(nil, /A generator does not currently exist fo/) do
57
+ refute CommandLine.new(FixturePaths).parse(args)
58
+ end
59
+ end
60
+ end
61
+
62
+ def test_default_options
63
+ args = %w(beta)
64
+ Files::GeneratorCases.stub :available, %w(beta) do
65
+ assert_instance_of UpdateVersionAndGenerateTests, CommandLine.new(FixturePaths).parse(args)
66
+ end
67
+ end
68
+
69
+ def test_frozen_option
70
+ args = %w(-f beta)
71
+ Files::GeneratorCases.stub :available, %w(beta) do
72
+ assert_instance_of GenerateTests, CommandLine.new(FixturePaths).parse(args)
73
+ end
74
+ end
75
+
76
+ def test_verbose_option
77
+ args = %w(-v beta)
78
+ Files::GeneratorCases.stub :available, %w(beta) do
79
+ assert_instance_of UpdateVersionAndGenerateTests, CommandLine.new(FixturePaths).parse(args)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../../test_helper.rb'
2
+ module Generator
3
+ module Files
4
+ class MetadataFilesTest < Minitest::Test
5
+ FixturePaths = Paths.new(
6
+ metadata: 'test/fixtures/metadata',
7
+ track: 'test/fixtures/xruby'
8
+ )
9
+
10
+ class TestMetadataFiles
11
+ def initialize
12
+ @paths = FixturePaths
13
+ @exercise_name = 'alpha'
14
+ end
15
+ attr_reader :paths, :exercise_name
16
+ include MetadataFiles
17
+ end
18
+
19
+ def test_canonical_data
20
+ subject = TestMetadataFiles.new
21
+ assert_instance_of CanonicalDataFile, subject.canonical_data
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,117 @@
1
+ require_relative '../../test_helper.rb'
2
+
3
+ module Generator
4
+ module Files
5
+ class GeneratorCasesTest < Minitest::Test
6
+ def test_no_cases_found
7
+ track_path = 'test/fixtures/nonexistant'
8
+ assert_equal [], GeneratorCases.available(track_path)
9
+ end
10
+
11
+ def test_cases_found
12
+ track_path = 'test/fixtures/xruby'
13
+ assert_equal %w(alpha beta), GeneratorCases.available(track_path).sort
14
+ end
15
+
16
+ def test_available_returns_exercise_names
17
+ track_path = 'test/fixtures/xruby'
18
+ Dir.stub :[], %w(/alpha_cases.rb hy_phen_ated_cases.rb) do
19
+ assert_equal %w(alpha hy-phen-ated), GeneratorCases.available(track_path)
20
+ end
21
+ end
22
+
23
+ def test_filename
24
+ exercise_name = 'two-parter'
25
+ assert_equal 'two_parter_cases', GeneratorCases.filename(exercise_name)
26
+ end
27
+
28
+ def test_proc_name
29
+ exercise_name = 'two-parter'
30
+ assert_equal 'TwoParterCases', GeneratorCases.proc_name(exercise_name)
31
+ end
32
+ end
33
+
34
+ class TrackFilesTest < Minitest::Test
35
+ FixturePaths = Paths.new(
36
+ metadata: 'test/fixtures/metadata',
37
+ track: 'test/fixtures/xruby'
38
+ )
39
+
40
+ class TestTrackFiles
41
+ def initialize
42
+ @paths = FixturePaths
43
+ @exercise_name = 'alpha'
44
+ end
45
+ attr_reader :paths, :exercise_name
46
+ include TrackFiles
47
+ end
48
+
49
+ def test_tests_version
50
+ subject = TestTrackFiles.new
51
+ assert_instance_of TestsVersionFile, subject.tests_version
52
+ end
53
+
54
+ def test_example_solution
55
+ subject = TestTrackFiles.new
56
+ assert_instance_of ExampleSolutionFile, subject.example_solution
57
+ end
58
+
59
+ def test_minitest_tests
60
+ subject = TestTrackFiles.new
61
+ assert_instance_of MinitestTestsFile, subject.minitest_tests
62
+ end
63
+
64
+ def test_tests_template
65
+ subject = TestTrackFiles.new
66
+ assert_instance_of TestsTemplateFile, subject.tests_template
67
+ end
68
+ end
69
+
70
+ class TestsVersionFileTest < Minitest::Test
71
+ class TestTestsVersionFile < TestsVersionFile
72
+ def save(content)
73
+ content
74
+ end
75
+ end
76
+
77
+ def test_increment
78
+ subject = TestTestsVersionFile.new(filename: 'test/fixtures/xruby/exercises/alpha/.meta/.version')
79
+ assert_equal 2, subject.increment
80
+ end
81
+ end
82
+
83
+ class ExampleSolutionFileTest < Minitest::Test
84
+ class TestExampleSolutionFile < ExampleSolutionFile
85
+ def save(content)
86
+ content
87
+ end
88
+ end
89
+
90
+ def test_update_version
91
+ subject = TestExampleSolutionFile.new(filename: 'test/fixtures/xruby/exercises/alpha/example.rb')
92
+ assert_match(/VERSION = 2/, subject.update_version(2))
93
+ end
94
+ end
95
+
96
+ class MinitestTestsFileTest < Minitest::Test
97
+ class TestMinitestTestsFile < MinitestTestsFile
98
+ def save(content)
99
+ content
100
+ end
101
+ end
102
+
103
+ def test_update_version
104
+ mock_template = Minitest::Mock.new
105
+ mock_values = Minitest::Mock.new
106
+ mock_values.expect :get_binding, 'mock binding'
107
+ mock_erb = Minitest::Mock.new
108
+ mock_erb.expect :result, 'new content', ['mock binding']
109
+
110
+ subject = TestMinitestTestsFile.new(filename: 'test/fixtures/xruby/exercises/alpha/alpha_tests.rb')
111
+ ERB.stub :new, mock_erb do
112
+ assert_equal 'new content', subject.generate(template: mock_template, values: mock_values)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end