devtools 0.1.0 → 0.1.5

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Gemfile +0 -2
  4. data/README.md +3 -3
  5. data/circle.yml +1 -1
  6. data/config/devtools.yml +2 -0
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/mutant.yml +2 -0
  10. data/config/reek.yml +7 -12
  11. data/config/rubocop.yml +8 -0
  12. data/devtools.gemspec +21 -19
  13. data/lib/devtools/config.rb +76 -55
  14. data/lib/devtools/flay.rb +94 -0
  15. data/lib/devtools/project/initializer/rake.rb +9 -7
  16. data/lib/devtools/project/initializer/rspec.rb +28 -55
  17. data/lib/devtools/project/initializer.rb +2 -12
  18. data/lib/devtools/project.rb +28 -105
  19. data/lib/devtools/rake/flay.rb +126 -0
  20. data/lib/devtools/spec_helper.rb +1 -3
  21. data/lib/devtools.rb +34 -83
  22. data/shared/spec/shared/abstract_type_behavior.rb +0 -2
  23. data/shared/spec/shared/command_method_behavior.rb +0 -2
  24. data/shared/spec/shared/each_method_behaviour.rb +0 -2
  25. data/shared/spec/shared/hash_method_behavior.rb +0 -2
  26. data/shared/spec/shared/idempotent_method_behavior.rb +0 -2
  27. data/shared/spec/support/ice_nine_config.rb +0 -2
  28. data/spec/integration/devtools/rake/flay/verify_spec.rb +164 -0
  29. data/spec/spec_helper.rb +2 -8
  30. data/spec/unit/devtools/config/yardstick_spec.rb +17 -0
  31. data/spec/unit/devtools/config_spec.rb +78 -0
  32. data/spec/unit/devtools/flay/file_list/call_spec.rb +19 -0
  33. data/spec/unit/devtools/flay/scale/flay_report_spec.rb +17 -0
  34. data/spec/unit/devtools/flay/scale/measure_spec.rb +43 -0
  35. data/spec/unit/devtools/project/initializer/rake_spec.rb +21 -0
  36. data/spec/unit/devtools/project/initializer/rspec_spec.rb +52 -0
  37. data/spec/unit/devtools/project_spec.rb +34 -0
  38. data/spec/unit/devtools_spec.rb +14 -0
  39. data/tasks/metrics/ci.rake +2 -3
  40. data/tasks/metrics/coverage.rake +0 -2
  41. data/tasks/metrics/flay.rake +6 -33
  42. data/tasks/metrics/flog.rake +0 -2
  43. data/tasks/metrics/mutant.rake +31 -39
  44. data/tasks/metrics/reek.rake +5 -4
  45. data/tasks/metrics/rubocop.rake +0 -2
  46. data/tasks/metrics/yardstick.rake +0 -14
  47. data/tasks/spec.rake +0 -2
  48. data/tasks/yard.rake +0 -2
  49. metadata +99 -35
  50. data/.travis.yml +0 -15
  51. data/TODO +0 -0
  52. data/bin/devtools +0 -18
  53. data/default/config/devtools.yml +0 -2
  54. data/default/config/flay.yml +0 -3
  55. data/default/config/flog.yml +0 -2
  56. data/default/config/mutant.yml +0 -3
  57. data/default/config/reek.yml +0 -103
  58. data/default/config/rubocop.yml +0 -91
  59. data/default/config/yardstick.yml +0 -2
  60. data/lib/devtools/platform.rb +0 -118
  61. data/lib/devtools/site/initializer.rb +0 -57
  62. data/lib/devtools/site.rb +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 764c83969a5e3165490c1032274ebae18ebe2b9d
4
- data.tar.gz: 8f7d916f56ce1d5e2e265331583bde25dc276d6f
3
+ metadata.gz: df0052621c82ba8a5452d4c9352c76690a59c159
4
+ data.tar.gz: b83f7ff1af43a8344a6d88921b6230fd2ce0653a
5
5
  SHA512:
6
- metadata.gz: ad8bba29c9c98632ea5502b1d22e89bc0c4d4a555e7f6f5a856021a33e0484f090b04306f3033e456cda7b133d057393e81905ea63b24a0149fef57efe4c1539
7
- data.tar.gz: 0fff91e6b6ed417aaf43c3328119f00b861d361b2d503e4bd306b6bb9b192e938a82f921900f92fe79769ee61b743c90980d6860900c7667f92f9695f1095530
6
+ metadata.gz: 8a4eb1dd77b9aabf6db22f150c4efc9adc5a840d5efb1dee144a6c3359ea006fe7b67b6d3a912f894a49df05081656aa45b2c78b081cc0a00eca85d378ba0e9f
7
+ data.tar.gz: 72b3ce1b479c109364841d3798454ea2380fa6e14154c533498375338089f04ab9307fa39cbc94818e1d5fe498cdf19c09c7eeeb1ae2fc5e71b04bd51de5df57
data/.rspec CHANGED
@@ -3,3 +3,4 @@
3
3
  --profile
4
4
  --warnings
5
5
  --order random
6
+ --require spec_helper
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  source 'https://rubygems.org'
4
2
 
5
3
  gemspec
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # devtools
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/mbj/devtools.png?branch=master)](http://travis-ci.org/mbj/devtools)
3
+ [![Build Status](https://img.shields.io/circleci/project/mbj/devtools.svg)](https://circleci.com/gh/mbj/devtools/tree/master)
4
4
  [![Dependency Status](https://gemnasium.com/mbj/devtools.png)](https://gemnasium.com/mbj/devtools)
5
5
  [![Code Climate](https://codeclimate.com/github/datamapper/devtools.png)](https://codeclimate.com/github/datamapper/devtools)
6
6
  <!-- [![Code Climate](https://codeclimate.com/github/mbj/devtools.png)](https://codeclimate.com/github/mbj/devtools) -->
@@ -10,11 +10,11 @@ Used to centralize metric setup and development gem dependencies.
10
10
 
11
11
  ## Installation
12
12
 
13
- Add the git source to your Gemfile's development section, there is currently no gem release.
13
+ Add the gem to your Gemfile's development section.
14
14
 
15
15
  ```ruby
16
16
  group :development, :test do
17
- gem 'devtools', git: 'https://github.com/mbj/devtools.git'
17
+ gem 'devtools', '~> 0.1.x'
18
18
  end
19
19
  ```
20
20
 
data/circle.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  machine:
3
3
  ruby:
4
- version: '2.2'
4
+ version: '2.2.3'
5
5
  test:
6
6
  override:
7
7
  - bundle exec rake ci
@@ -0,0 +1,2 @@
1
+ ---
2
+ unit_test_timeout: 0.2
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
- threshold: 16
3
- total_score: 97
2
+ threshold: 8
3
+ total_score: 112
data/config/flog.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  ---
2
- threshold: 11.1
2
+ threshold: 19.7
data/config/mutant.yml CHANGED
@@ -1,2 +1,4 @@
1
1
  name: devtools
2
2
  namespace: Devtools
3
+ ignore_subjects:
4
+ - "Devtools::Flay::Scale#flay"
data/config/reek.yml CHANGED
@@ -23,15 +23,14 @@ DuplicateMethodCall:
23
23
  allow_calls: []
24
24
  FeatureEnvy:
25
25
  enabled: true
26
- exclude:
27
- - Devtools::Site::Initializer#init_gemfile
28
- - Devtools::Site::Initializer#init_rakefile
26
+ exclude: []
29
27
  IrresponsibleModule:
30
28
  enabled: true
31
29
  exclude: []
32
30
  LongParameterList:
33
31
  enabled: true
34
- exclude: []
32
+ exclude:
33
+ - Devtools::Config#self.attribute
35
34
  max_params: 2
36
35
  overrides: {}
37
36
  LongYieldList:
@@ -52,17 +51,15 @@ RepeatedConditional:
52
51
  max_ifs: 1
53
52
  TooManyInstanceVariables:
54
53
  enabled: true
55
- exclude:
56
- - Devtools::Project
57
- max_instance_variables: 14 # no adamantium ;)
54
+ exclude: []
55
+ max_instance_variables: 2
58
56
  TooManyMethods:
59
57
  enabled: true
60
58
  exclude: []
61
59
  max_methods: 15
62
60
  TooManyStatements:
63
61
  enabled: true
64
- exclude:
65
- - Devtools::Project#initialize # needs refactoring, it is way too large
62
+ exclude: []
66
63
  max_statements: 5
67
64
  UncommunicativeMethodName:
68
65
  enabled: true
@@ -101,7 +98,5 @@ UnusedParameters:
101
98
  UtilityFunction:
102
99
  enabled: true
103
100
  exclude:
104
- - Devtools::Platform#ruby18?
105
- - Devtools::Platform#ruby19?
106
- - Devtools::Platform#ruby20?
101
+ - Devtools::Project::Initializer::Rspec#require_files # intentional for deduplication
107
102
  max_helper_calls: 0
data/config/rubocop.yml CHANGED
@@ -115,3 +115,11 @@ LambdaCall:
115
115
  # Allow additional spaces
116
116
  ExtraSpacing:
117
117
  Enabled: false
118
+
119
+ # All objects can still be mutated if their eigenclass is patched
120
+ RedundantFreeze:
121
+ Enabled: false
122
+
123
+ # Prefer using `fail` when raising and `raise` when reraising
124
+ SignalException:
125
+ EnforcedStyle: semantic
data/devtools.gemspec CHANGED
@@ -1,33 +1,35 @@
1
- # encoding: utf-8
2
-
3
1
  Gem::Specification.new do |gem|
4
2
  gem.name = 'devtools'
5
- gem.version = '0.1.0'
3
+ gem.version = '0.1.5'
6
4
  gem.authors = [ 'Markus Schirp' ]
7
5
  gem.email = [ 'mbj@schirp-dso.com' ]
8
- gem.description = 'A metagem for ROM-style development'
6
+ gem.description = 'A metagem wrapping development tools'
9
7
  gem.summary = gem.description
10
8
  gem.homepage = 'https://github.com/rom-rb/devtools'
11
9
  gem.license = 'MIT'
12
10
 
13
11
  gem.require_paths = %w[lib]
14
12
  gem.files = `git ls-files`.split($/)
15
- gem.executables = %w[devtools]
13
+ gem.executables = %w[]
16
14
  gem.test_files = `git ls-files -- spec`.split($/)
17
- gem.extra_rdoc_files = %w[README.md TODO]
15
+ gem.extra_rdoc_files = %w[README.md]
18
16
  gem.required_ruby_version = '>= 2.1'
19
17
 
20
- gem.add_dependency 'rspec', '~> 3.3.0'
21
- gem.add_dependency 'rspec-core', '~> 3.3.0'
22
- gem.add_dependency 'rspec-its', '~> 1.2.0'
23
- gem.add_dependency 'rake', '~> 10.4.2'
24
- gem.add_dependency 'yard', '~> 0.8.7.6'
25
- gem.add_dependency 'flay', '~> 2.6.1'
26
- gem.add_dependency 'flog', '~> 4.3.2'
27
- gem.add_dependency 'reek', '~> 3.3.1'
28
- gem.add_dependency 'rubocop', '~> 0.33.0'
29
- gem.add_dependency 'simplecov', '~> 0.10.0'
30
- gem.add_dependency 'yardstick', '~> 0.9.9'
31
- gem.add_dependency 'mutant', '~> 0.8.3'
32
- gem.add_dependency 'mutant-rspec', '~> 0.8.2'
18
+ gem.add_runtime_dependency 'procto', '~> 0.0.x'
19
+ gem.add_runtime_dependency 'anima', '~> 0.3.x'
20
+ gem.add_runtime_dependency 'concord', '~> 0.1.x'
21
+ gem.add_runtime_dependency 'adamantium', '~> 0.2.x'
22
+ gem.add_runtime_dependency 'rspec', '~> 3.4.0'
23
+ gem.add_runtime_dependency 'rspec-core', '~> 3.4.0'
24
+ gem.add_runtime_dependency 'rspec-its', '~> 1.2.0'
25
+ gem.add_runtime_dependency 'rake', '~> 10.4.2'
26
+ gem.add_runtime_dependency 'yard', '~> 0.8.7.6'
27
+ gem.add_runtime_dependency 'flay', '~> 2.7.0'
28
+ gem.add_runtime_dependency 'flog', '~> 4.3.2'
29
+ gem.add_runtime_dependency 'reek', '~> 3.10.2'
30
+ gem.add_runtime_dependency 'rubocop', '~> 0.37.2'
31
+ gem.add_runtime_dependency 'simplecov', '~> 0.10.0'
32
+ gem.add_runtime_dependency 'yardstick', '~> 0.9.9'
33
+ gem.add_runtime_dependency 'mutant', '~> 0.8.10'
34
+ gem.add_runtime_dependency 'mutant-rspec', '~> 0.8.8'
33
35
  end
@@ -1,48 +1,65 @@
1
- # encoding: utf-8
2
-
3
1
  module Devtools
4
2
 
5
3
  # Abstract base class of tool configuration
6
4
  class Config
5
+ include Adamantium::Flat, AbstractType, Concord.new(:config_dir)
6
+
7
7
  # Represent no configuration
8
8
  DEFAULT_CONFIG = {}.freeze
9
9
 
10
+ # Simple named type check representation
11
+ class TypeCheck
12
+ # Type check against expected class
13
+ include Concord.new(:name, :allowed_classes)
14
+
15
+ ERROR_FORMAT = '%<name>s: Got instance of %<got>s expected %<allowed>s'.freeze
16
+ CLASS_DELIM = ','.freeze
17
+
18
+ # Check value for instance of expected class
19
+ #
20
+ # @param [Object] value
21
+ #
22
+ # @return [Object]
23
+ def call(value)
24
+ klass = value.class
25
+
26
+ unless allowed_classes.any?(&klass.method(:equal?))
27
+ fail TypeError, ERROR_FORMAT % {
28
+ name: name,
29
+ got: klass,
30
+ allowed: allowed_classes.join(CLASS_DELIM)
31
+ }
32
+ end
33
+
34
+ value
35
+ end
36
+ end # TypeCheck
37
+
38
+ private_constant(*constants(false))
39
+
40
+ # Error raised on type errors
41
+ TypeError = Class.new(RuntimeError)
42
+
10
43
  # Declare an attribute
11
44
  #
12
45
  # @param [Symbol] name
13
- #
14
- # @yieldreturn [Object]
15
- # the default value to use
46
+ # @param [Array<Class>] classes
16
47
  #
17
48
  # @api private
18
49
  #
19
50
  # @return [self]
20
51
  #
21
- def self.attribute(name, *default)
52
+ def self.attribute(name, classes, **options)
53
+ default = [options.fetch(:default)] if options.key?(:default)
54
+ type_check = TypeCheck.new(name, classes)
55
+ key = name.to_s
56
+
22
57
  define_method(name) do
23
- raw.fetch(name.to_s, *default)
58
+ type_check.call(raw.fetch(key, *default))
24
59
  end
25
60
  end
26
61
  private_class_method :attribute
27
62
 
28
- # Return project
29
- #
30
- # @return [Project]
31
- #
32
- # @api private
33
- #
34
- attr_reader :project
35
-
36
- # Initialize object
37
- #
38
- # @return [Project]
39
- #
40
- # @api private
41
- #
42
- def initialize(project)
43
- @project = project
44
- end
45
-
46
63
  # Return config path
47
64
  #
48
65
  # @return [String]
@@ -50,8 +67,9 @@ module Devtools
50
67
  # @api private
51
68
  #
52
69
  def config_file
53
- @config_file ||= project.config_dir.join(self.class::FILE).freeze
70
+ config_dir.join(self.class::FILE)
54
71
  end
72
+ memoize :config_file
55
73
 
56
74
  private
57
75
 
@@ -62,8 +80,9 @@ module Devtools
62
80
  # @api private
63
81
  #
64
82
  def raw
65
- @raw ||= yaml_config || DEFAULT_CONFIG
83
+ yaml_config || DEFAULT_CONFIG
66
84
  end
85
+ memoize :raw
67
86
 
68
87
  # Return the raw config data from a yaml file
69
88
  #
@@ -75,29 +94,30 @@ module Devtools
75
94
  # @api private
76
95
  #
77
96
  def yaml_config
78
- config_file = self.config_file
79
- YAML.load_file(config_file).freeze if config_file.file?
97
+ IceNine.deep_freeze(YAML.load_file(config_file)) if config_file.file?
80
98
  end
81
99
 
82
100
  # Rubocop configuration
83
101
  class Rubocop < self
84
102
  FILE = 'rubocop.yml'.freeze
85
- end
103
+ end # Rubocop
86
104
 
87
105
  # Reek configuration
88
106
  class Reek < self
89
107
  FILE = 'reek.yml'.freeze
90
- end
108
+ end # Reek
91
109
 
92
110
  # Flay configuration
93
111
  class Flay < self
94
112
  FILE = 'flay.yml'.freeze
95
113
  DEFAULT_LIB_DIRS = %w[lib].freeze
114
+ DEFAULT_EXCLUDES = %w[].freeze
96
115
 
97
- attribute :total_score
98
- attribute :threshold
99
- attribute :lib_dirs, DEFAULT_LIB_DIRS
100
- end
116
+ attribute :total_score, [Fixnum]
117
+ attribute :threshold, [Fixnum]
118
+ attribute :lib_dirs, [Array], default: DEFAULT_LIB_DIRS
119
+ attribute :excludes, [Array], default: DEFAULT_EXCLUDES
120
+ end # Flay
101
121
 
102
122
  # Yardstick configuration
103
123
  class Yardstick < self
@@ -120,39 +140,40 @@ module Devtools
120
140
  hash[name] = raw.fetch(name, nil)
121
141
  end
122
142
  end
123
- end
143
+ end # Yardstick
124
144
 
125
145
  # Flog configuration
126
146
  class Flog < self
127
- FILE = 'flog.yml'.freeze
128
- DEFAULT_LIB_DIRS = %w[lib].freeze
147
+ FILE = 'flog.yml'.freeze
148
+ DEFAULT_LIB_DIRS = %w[lib].freeze
129
149
 
130
- attribute :total_score
131
- attribute :threshold
132
- attribute :lib_dirs, DEFAULT_LIB_DIRS
133
- end
150
+ attribute :total_score, [Float]
151
+ attribute :threshold, [Float]
152
+ attribute :lib_dirs, [Array], default: DEFAULT_LIB_DIRS
153
+ end # Flog
134
154
 
135
155
  # Mutant configuration
136
156
  class Mutant < self
137
157
  FILE = 'mutant.yml'.freeze
138
158
  DEFAULT_NAME = ''.freeze
139
159
  DEFAULT_STRATEGY = 'rspec'.freeze
160
+ DEFAULT_COVERAGE = '1/1'.freeze
140
161
 
141
- attribute :name, DEFAULT_NAME
142
- attribute :strategy, DEFAULT_STRATEGY
143
- attribute :zombify, false
144
- attribute :since, nil
145
- attribute :ignore_subjects, []
146
- attribute :expect_coverage, 1
147
- attribute :namespace
148
- end
162
+ attribute :name, [String], default: DEFAULT_NAME
163
+ attribute :strategy, [String], default: DEFAULT_STRATEGY
164
+ attribute :zombify, [TrueClass, FalseClass], default: false
165
+ attribute :since, [String, NilClass], default: nil
166
+ attribute :ignore_subjects, [Array], default: []
167
+ attribute :expect_coverage, [String], default: DEFAULT_COVERAGE
168
+ attribute :namespace, [String]
169
+ end # Mutant
149
170
 
150
171
  # Devtools configuration
151
172
  class Devtools < self
152
- FILE = 'devtools.yml'.freeze
173
+ FILE = 'devtools.yml'.freeze
153
174
  DEFAULT_UNIT_TEST_TIMEOUT = 0.1 # 100ms
154
175
 
155
- attribute :unit_test_timeout, DEFAULT_UNIT_TEST_TIMEOUT
156
- end
157
- end
158
- end
176
+ attribute :unit_test_timeout, [Float], default: DEFAULT_UNIT_TEST_TIMEOUT
177
+ end # Devtools
178
+ end # Config
179
+ end # Devtools
@@ -0,0 +1,94 @@
1
+ module Devtools
2
+ module Flay
3
+ # Measure flay mass relative to size of duplicated sexps
4
+ class Scale
5
+ include Adamantium
6
+ include Anima.new(:minimum_mass, :files)
7
+ include Procto.call(:measure)
8
+
9
+ # Measure duplication mass
10
+ #
11
+ # @return [Array<Rational>]
12
+ #
13
+ # @api private
14
+ def measure
15
+ flay.masses.map do |hash, mass|
16
+ Rational(mass, flay.hashes.fetch(hash).size)
17
+ end
18
+ end
19
+
20
+ # Report flay output
21
+ #
22
+ # @return [undefined]
23
+ #
24
+ # @api private
25
+ def flay_report
26
+ flay.report
27
+ end
28
+
29
+ private
30
+
31
+ # Memoized flay instance
32
+ #
33
+ # @return [Flay]
34
+ #
35
+ # @api private
36
+ def flay
37
+ ::Flay.new(mass: minimum_mass).tap do |flay|
38
+ flay.process(*files)
39
+ flay.analyze
40
+ end
41
+ end
42
+ memoize :flay, freezer: :noop
43
+ end
44
+
45
+ # Expand include and exclude file settings for flay
46
+ class FileList
47
+ include Procto.call, Concord.new(:includes, :excludes)
48
+
49
+ # Expand includes and filter by excludes
50
+ #
51
+ # @return [Set<Pathname>]
52
+ #
53
+ # @api private
54
+ def call
55
+ include_set - exclude_set
56
+ end
57
+
58
+ private
59
+
60
+ # Set of excluded files
61
+ #
62
+ # @return [Set<Pathname>]
63
+ #
64
+ # @api private
65
+ def exclude_set
66
+ excludes.flat_map(&Pathname.method(:glob))
67
+ end
68
+
69
+ # Set of included files
70
+ #
71
+ # Expanded using flay's file expander which takes into
72
+ # account flay's plugin support
73
+ #
74
+ # @return [Set<Pathname>]
75
+ #
76
+ # @api private
77
+ def include_set
78
+ Set.new(flay_includes.map(&method(:Pathname)))
79
+ end
80
+
81
+ # Expand includes using flay
82
+ #
83
+ # Expanded using flay's file expander which takes into
84
+ # account flay's plugin support
85
+ #
86
+ # @return [Array<String>]
87
+ #
88
+ # @api private
89
+ def flay_includes
90
+ ::Flay.expand_dirs_to_files(includes)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,16 +1,18 @@
1
- # encoding: utf-8
2
-
3
1
  module Devtools
4
2
  class Project
5
3
  class Initializer
6
-
7
4
  # Imports all devtools rake tasks into a project
8
- class Rake
9
-
10
- extend ::Rake::DSL
5
+ class Rake < self
6
+ include AbstractType
11
7
 
8
+ # Initialize rake tasks
9
+ #
10
+ # @return [undefined]
11
+ #
12
+ # @api rpivate
12
13
  def self.call
13
- FileList[RAKE_FILES_GLOB].each(&method(:import))
14
+ FileList.glob(RAKE_FILES_GLOB).each(&::Rake.application.method(:add_import))
15
+ self
14
16
  end
15
17
 
16
18
  end # class Rake
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Devtools
4
2
  class Project
5
3
  class Initializer
@@ -7,72 +5,33 @@ module Devtools
7
5
  # Requires all shared specs in a project's spec_helper
8
6
  # Also installs a configurable unit test timeout
9
7
  class Rspec < self
8
+ include Concord.new(:project)
10
9
 
11
- def self.require_files(directory)
12
- Devtools.require_files(directory, SHARED_SPEC_PATTERN)
13
- end
14
-
15
- # Initialize RSpec for +project+
10
+ # Call initializer for project
16
11
  #
17
12
  # @param [Project] project
18
- # the project to initialize
19
13
  #
20
- # @return [Rspec]
14
+ # @return [self]
21
15
  #
22
16
  # @api private
23
17
  def self.call(project)
24
- new(project).call
18
+ new(project).__send__(:call)
19
+ self
25
20
  end
26
21
 
27
- # The spec root
28
- #
29
- # @return [Pathname]
30
- #
31
- # @api private
32
- attr_reader :spec_root
33
- private :spec_root
22
+ private
34
23
 
35
- # The unit test timeout
36
- #
37
- # @return [Numeric]
38
- #
39
- # @api private
40
- attr_reader :unit_test_timeout
41
- private :unit_test_timeout
42
-
43
- # Initialize a new instance
44
- #
45
- # @param [Project] project
46
- # the project to initialize
47
- #
48
- # @param [Numeric] unit_test_timeout
49
- # the maximum time a single unit test can take
50
- #
51
- # @return [undefined]
52
- #
53
- # @api private
54
- def initialize(project)
55
- super
56
- @spec_root = project.spec_root
57
- @unit_test_timeout = project.unit_test_timeout
58
- end
59
-
60
- # Setup RSpec for {#project}
24
+ # Setup RSpec for project
61
25
  #
62
26
  # @return [self]
63
27
  #
64
28
  # @api private
65
29
  def call
66
- require 'rspec'
67
- require 'rspec/its'
68
30
  require_shared_spec_files
69
- enable_unit_test_timeout unless Devtools.jit?
70
- self
31
+ enable_unit_test_timeout
71
32
  end
72
33
 
73
- private
74
-
75
- # Timeout unit tests that take longer than 1/10th of a second
34
+ # Timeout unit tests that take longer than configured amount of time
76
35
  #
77
36
  # @param [Numeric] timeout
78
37
  #
@@ -84,19 +43,33 @@ module Devtools
84
43
  # @api private
85
44
  #
86
45
  def enable_unit_test_timeout
87
- timeout = unit_test_timeout # support the closure
88
- RSpec.configuration.around file_path: UNIT_TEST_PATH_REGEXP do |example|
46
+ timeout = project.devtools.unit_test_timeout
47
+ RSpec.configuration.around(file_path: UNIT_TEST_PATH_REGEXP) do |example|
89
48
  Timeout.timeout(timeout, &example)
90
49
  end
91
50
  end
92
51
 
52
+ # Trigger the require of shared spec files
53
+ #
54
+ # @return [undefined]
55
+ #
56
+ # @api private
57
+ #
93
58
  def require_shared_spec_files
94
59
  require_files(SHARED_SPEC_PATH)
95
- require_files(spec_root)
60
+ require_files(project.spec_root)
96
61
  end
97
62
 
98
- def require_files(directory)
99
- self.class.require_files(directory)
63
+ # Require files with pattern
64
+ #
65
+ # @param [Pathname] dir
66
+ # the directory containing the files to require
67
+ #
68
+ # @return [self]
69
+ #
70
+ # @api private
71
+ def require_files(dir)
72
+ Dir.glob(dir.join(SHARED_SPEC_PATTERN)).each(&Kernel.method(:require))
100
73
  end
101
74
 
102
75
  end # class Rspec
@@ -1,21 +1,11 @@
1
- # encoding: utf-8
2
-
3
1
  module Devtools
4
2
  class Project
5
3
 
6
4
  # Base class for project initializers
7
5
  class Initializer
6
+ include AbstractType
8
7
 
9
- attr_reader :project
10
- protected :project
11
-
12
- def initialize(project)
13
- @project = project
14
- end
15
-
16
- def call
17
- fail NotImplementedError, "#{self.class}##{__method__} must be implemented"
18
- end
8
+ abstract_singleton_method :call
19
9
  end # class Initializer
20
10
  end # class Project
21
11
  end # module Devtools