trackler 2.0.6.1 → 2.0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/go/exercises/word-count/cases_test.go +23 -4
- data/tracks/go/exercises/word-count/example.go +6 -2
- data/tracks/go/exercises/word-count/word_count.go +1 -1
- data/tracks/go/exercises/word-count/word_count_test.go +1 -1
- data/tracks/pony/.travis.yml +16 -4
- data/tracks/pony/bin/install-deps +12 -0
- data/tracks/pony/bin/test-exercises +22 -0
- data/tracks/ruby/Gemfile +1 -0
- data/tracks/ruby/Rakefile +1 -1
- data/tracks/ruby/bin/generate +4 -29
- data/tracks/ruby/exercises/all-your-base/.meta/.version +1 -0
- data/tracks/ruby/exercises/all-your-base/all_your_base_test.rb +50 -60
- data/tracks/ruby/exercises/all-your-base/example.rb +13 -8
- data/tracks/ruby/exercises/all-your-base/example.tt +17 -0
- data/tracks/ruby/lib/all_your_base_cases.rb +109 -0
- data/tracks/ruby/lib/generator.rb +21 -100
- data/tracks/ruby/lib/generator/command_line.rb +119 -0
- data/tracks/ruby/lib/generator/files.rb +58 -0
- data/tracks/ruby/lib/generator/files/metadata_files.rb +22 -0
- data/tracks/ruby/lib/generator/files/track_files.rb +83 -0
- data/tracks/ruby/lib/generator/git_command.rb +8 -0
- data/tracks/ruby/lib/generator/repository.rb +62 -0
- data/tracks/ruby/lib/generator/template_values.rb +47 -0
- data/tracks/ruby/lib/helper.rb +5 -2
- data/tracks/ruby/test/fixtures/metadata/exercises/alpha/canonical-data.json +8 -9
- data/tracks/ruby/test/fixtures/{exercises → xruby/exercises}/alpha/.meta/.version +0 -0
- data/tracks/ruby/test/fixtures/{exercises → xruby/exercises}/alpha/example.rb +0 -0
- data/tracks/ruby/test/fixtures/xruby/exercises/alpha/example.tt +20 -0
- data/tracks/ruby/test/fixtures/xruby/lib/alpha_cases.rb +20 -0
- data/tracks/ruby/test/fixtures/xruby/lib/beta_cases.rb +0 -0
- data/tracks/ruby/test/generator/command_line_test.rb +83 -0
- data/tracks/ruby/test/generator/files/metadata_files_test.rb +25 -0
- data/tracks/ruby/test/generator/files/track_files_test.rb +117 -0
- data/tracks/ruby/test/generator/files_test.rb +63 -0
- data/tracks/ruby/test/generator/git_command_test.rb +9 -0
- data/tracks/ruby/test/generator/repository_test.rb +98 -0
- data/tracks/ruby/test/generator/template_values_test.rb +59 -0
- data/tracks/ruby/test/generator_test.rb +19 -63
- data/tracks/ruby/test/test_helper.rb +8 -5
- metadata +26 -6
- data/tracks/ruby/test/fixtures/exercises/alpha/alpha_test.rb +0 -1
- 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,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
|
data/tracks/ruby/lib/helper.rb
CHANGED
@@ -1,2 +1,5 @@
|
|
1
|
-
|
2
|
-
XRUBY_LIB = File.
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
}
|
File without changes
|
File without changes
|
@@ -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
|
File without changes
|
@@ -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
|