devtools 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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