devtools 0.1.2 → 0.1.3

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Gemfile +0 -2
  4. data/README.md +2 -2
  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/devtools.gemspec +20 -18
  12. data/lib/devtools.rb +34 -83
  13. data/lib/devtools/config.rb +76 -55
  14. data/lib/devtools/flay.rb +94 -0
  15. data/lib/devtools/project.rb +28 -105
  16. data/lib/devtools/project/initializer.rb +2 -12
  17. data/lib/devtools/project/initializer/rake.rb +9 -7
  18. data/lib/devtools/project/initializer/rspec.rb +28 -55
  19. data/lib/devtools/rake/flay.rb +126 -0
  20. data/lib/devtools/spec_helper.rb +1 -3
  21. data/shared/spec/shared/abstract_type_behavior.rb +0 -2
  22. data/shared/spec/shared/command_method_behavior.rb +0 -2
  23. data/shared/spec/shared/each_method_behaviour.rb +0 -2
  24. data/shared/spec/shared/hash_method_behavior.rb +0 -2
  25. data/shared/spec/shared/idempotent_method_behavior.rb +0 -2
  26. data/shared/spec/support/ice_nine_config.rb +0 -2
  27. data/spec/integration/devtools/rake/flay/verify_spec.rb +164 -0
  28. data/spec/spec_helper.rb +2 -8
  29. data/spec/unit/devtools/config/yardstick_spec.rb +17 -0
  30. data/spec/unit/devtools/config_spec.rb +78 -0
  31. data/spec/unit/devtools/flay/file_list/call_spec.rb +19 -0
  32. data/spec/unit/devtools/flay/scale/flay_report_spec.rb +17 -0
  33. data/spec/unit/devtools/flay/scale/measure_spec.rb +43 -0
  34. data/spec/unit/devtools/project/initializer/rake_spec.rb +21 -0
  35. data/spec/unit/devtools/project/initializer/rspec_spec.rb +52 -0
  36. data/spec/unit/devtools/project_spec.rb +34 -0
  37. data/spec/unit/devtools_spec.rb +14 -0
  38. data/tasks/metrics/ci.rake +1 -3
  39. data/tasks/metrics/coverage.rake +0 -2
  40. data/tasks/metrics/flay.rake +6 -33
  41. data/tasks/metrics/flog.rake +0 -2
  42. data/tasks/metrics/mutant.rake +31 -39
  43. data/tasks/metrics/reek.rake +0 -2
  44. data/tasks/metrics/rubocop.rake +0 -2
  45. data/tasks/metrics/yardstick.rake +0 -14
  46. data/tasks/spec.rake +0 -2
  47. data/tasks/yard.rake +0 -2
  48. metadata +96 -31
  49. data/.travis.yml +0 -15
  50. data/TODO +0 -0
  51. data/bin/devtools +0 -18
  52. data/default/config/devtools.yml +0 -2
  53. data/default/config/flay.yml +0 -3
  54. data/default/config/flog.yml +0 -2
  55. data/default/config/mutant.yml +0 -3
  56. data/default/config/reek.yml +0 -103
  57. data/default/config/rubocop.yml +0 -91
  58. data/default/config/yardstick.yml +0 -2
  59. data/lib/devtools/platform.rb +0 -118
  60. data/lib/devtools/site.rb +0 -41
  61. data/lib/devtools/site/initializer.rb +0 -57
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1071f9d15d4b5aa58b37b2ce7673f52a1a93134
4
- data.tar.gz: 9df7747e313808a6e834a2a13578a238e07df7c0
3
+ metadata.gz: 525d730bf63b2733ddbde070eaf7a58615ff40cf
4
+ data.tar.gz: 4706f0847e170be9bf2d7477cab78f4afa36f6f9
5
5
  SHA512:
6
- metadata.gz: f9a7d6f2255c8f52c9cda553e550ee1c27f4fa2cf736cb824889b52585c97324782673b07f1bcffeef2c9481da788072dda1e575532a20a7adc88d3d682a0bbe
7
- data.tar.gz: eb0519a453e0d758a6dd1ab12b6f831cff8fb17a22e7eeb9748836c5885c874a1975d0fb9f6b33b0b05b686c7c0fe0808dc7a6bd618c9e4129e6ffa68c20df99
6
+ metadata.gz: cb7b59eaee5985348cbbc3902eafb956148d8fefdb2b43e102880a610766060521bfb655e58ce057becf08b3d0cf778cc0862f6077f125fe44820b36e0bbd530
7
+ data.tar.gz: 2492e98c9a00afc8b57916ad42fc4b2645836a46d9e3863025f4f0cbe4009082bbb653e482414c74134a9858c070fe43ff7a2a5211c42ffded0ac0a6f271917f
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) -->
@@ -14,7 +14,7 @@ Add the gem to your Gemfile's development section.
14
14
 
15
15
  ```ruby
16
16
  group :development, :test do
17
- gem 'devtools', '~> 0.1.1'
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/devtools.gemspec CHANGED
@@ -1,8 +1,6 @@
1
- # encoding: utf-8
2
-
3
1
  Gem::Specification.new do |gem|
4
2
  gem.name = 'devtools'
5
- gem.version = '0.1.2'
3
+ gem.version = '0.1.3'
6
4
  gem.authors = [ 'Markus Schirp' ]
7
5
  gem.email = [ 'mbj@schirp-dso.com' ]
8
6
  gem.description = 'A metagem for ROM-style development'
@@ -12,22 +10,26 @@ Gem::Specification.new do |gem|
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.5.0'
28
- gem.add_dependency 'rubocop', '~> 0.34.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.6.1'
28
+ gem.add_runtime_dependency 'flog', '~> 4.3.2'
29
+ gem.add_runtime_dependency 'reek', '~> 3.7.0'
30
+ gem.add_runtime_dependency 'rubocop', '~> 0.35.1'
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.9'
34
+ gem.add_runtime_dependency 'mutant-rspec', '~> 0.8.8'
33
35
  end
data/lib/devtools.rb CHANGED
@@ -1,24 +1,24 @@
1
- # encoding: utf-8
2
-
1
+ # Stdlib infrastructure
3
2
  require 'pathname'
4
3
  require 'rake'
5
4
  require 'timeout'
6
5
  require 'yaml'
7
6
  require 'fileutils'
8
7
 
9
- require 'devtools/platform'
10
- require 'devtools/site'
11
- require 'devtools/site/initializer'
12
- require 'devtools/project'
13
- require 'devtools/config'
14
- require 'devtools/project/initializer'
15
- require 'devtools/project/initializer/rake'
16
- require 'devtools/project/initializer/rspec'
8
+ # Non stdlib infrastructure
9
+ require 'procto'
10
+ require 'anima'
11
+ require 'concord'
12
+ require 'adamantium'
17
13
 
18
- # Provides access to metric tools
19
- module Devtools
14
+ # Wrapped tools
15
+ require 'flay'
16
+ require 'rspec'
17
+ require 'rspec/its'
18
+ require 'simplecov'
20
19
 
21
- extend Platform
20
+ # Main devtools namespace population
21
+ module Devtools
22
22
 
23
23
  ROOT = Pathname.new(__FILE__).parent.parent.freeze
24
24
  PROJECT_ROOT = Pathname.pwd.freeze
@@ -28,17 +28,12 @@ module Devtools
28
28
  RAKE_FILES_GLOB = ROOT.join('tasks/**/*.rake').to_s.freeze
29
29
  LIB_DIRECTORY_NAME = 'lib'.freeze
30
30
  SPEC_DIRECTORY_NAME = 'spec'.freeze
31
- RB_FILE_PATTERN = '**/*.rb'.freeze
32
31
  RAKE_FILE_NAME = 'Rakefile'.freeze
33
- REQUIRE = "require 'devtools'".freeze
34
- INIT_RAKE_TASKS = 'Devtools.init_rake_tasks'.freeze
35
32
  SHARED_SPEC_PATTERN = '{shared,support}/**/*.rb'.freeze
36
33
  UNIT_TEST_PATH_REGEXP = %r{\bspec/unit/}.freeze
37
34
  DEFAULT_CONFIG_DIR_NAME = 'config'.freeze
38
- ANNOTATION_WRAPPER = "\n# Added by devtools\n%s\n".freeze
39
35
 
40
- # Provides devtools for a project
41
- SITE = Site.new(Project.new(PROJECT_ROOT))
36
+ private_constant(*constants(false))
42
37
 
43
38
  # React to metric violation
44
39
  #
@@ -63,26 +58,13 @@ module Devtools
63
58
  self
64
59
  end
65
60
 
66
- # Initialize project and load shared specs
67
- #
68
- # Expects to be called from $application_root/spec/spec_helper.rb
61
+ # Return devtools root path
69
62
  #
70
- # @return [self]
63
+ # @return [Pathname]
71
64
  #
72
- # @api public
73
- def self.init_spec_helper
74
- SITE.init_spec_helper
75
- self
76
- end
77
-
78
- # Initialize devtools using default config
79
- #
80
- # @return [undefined]
81
- #
82
- # @api public
83
- def self.init
84
- SITE.init
85
- self
65
+ # @api private
66
+ def self.root
67
+ ROOT
86
68
  end
87
69
 
88
70
  # Return project
@@ -91,53 +73,22 @@ module Devtools
91
73
  #
92
74
  # @api private
93
75
  def self.project
94
- SITE.project
76
+ PROJECT
95
77
  end
96
78
 
97
- # Require shared examples
98
- #
99
- # @param [Pathname] dir
100
- # the directory containing the files to require
101
- #
102
- # @param [String] pattern
103
- # the file pattern to match inside directory
104
- #
105
- # @return [self]
106
- #
107
- # @api private
108
- def self.require_files(dir, pattern)
109
- Dir[dir.join(pattern)].each { |file| require file }
110
- self
111
- end
112
-
113
- # Detect ci
114
- #
115
- # @return [Boolean]
116
- #
117
- # @api private
118
- #
119
- def self.ci?
120
- ENV.key?('CI')
121
- end
122
-
123
- # Detect circle ci
124
- #
125
- # @return [Boolean]
126
- #
127
- # @api private
128
- #
129
- def self.circle_ci?
130
- ENV.key?('CIRCLECI')
131
- end
79
+ end # module Devtools
132
80
 
133
- # Detect travis ci
134
- #
135
- # @return [Boolean]
136
- #
137
- # @api private
138
- #
139
- def self.travis?
140
- ENV.key?('TRAVIS')
141
- end
81
+ # Devtools implementation
82
+ require 'devtools/config'
83
+ require 'devtools/project'
84
+ require 'devtools/project/initializer'
85
+ require 'devtools/project/initializer/rake'
86
+ require 'devtools/project/initializer/rspec'
87
+ require 'devtools/flay'
88
+ require 'devtools/rake/flay'
142
89
 
143
- end # module Devtools
90
+ # Devtools self initialization
91
+ module Devtools
92
+ # The project devtools is active for
93
+ PROJECT = Project.new(PROJECT_ROOT)
94
+ 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