loggability 0.7.0 → 0.8.0.pre.65

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4cd7d81cde7a350d212b84b58c36a2b83d235da4
4
- data.tar.gz: 5320e44d3b6264f03c5f524bd9791cdd8837342a
3
+ metadata.gz: 080af7dac1d884020028cd90faa021b2162279ed
4
+ data.tar.gz: 5030296da798cc5802812a0b1a7fcee1223161b7
5
5
  SHA512:
6
- metadata.gz: 22ec6cf0983afc06ddbaa7d26db5fc1684fbfc4c8ce11f688ef64501da200d49b94607b43b9d84431985d49b9655361054b76c1ab981ce650857c51db78f69de
7
- data.tar.gz: 3047401b261320512aa47dcd2d839648df9abc2a1def4b8bb3181efe957a09bd988ad0d8fe66198e125aa776fad87fb995a0190d9cd58119327c9a78df669958
6
+ metadata.gz: eed60ff758345f3996dd7ad517bbb4de4ea4d52ff8a4520eeaa380e01e1244df5cddf71784b76a5cf6dfc529a74a2a9c411823317b8cea28743f44020a6c4338
7
+ data.tar.gz: c65f9e7137429f584aad8cba285b437793df9461c977b36ab34c44e595b7306f9ef457c2db1347c080742c01add876c313476c66b58da6ede67916696b714072
checksums.yaml.gz.sig CHANGED
Binary file
data/Manifest.txt CHANGED
@@ -9,11 +9,15 @@ lib/loggability/formatter.rb
9
9
  lib/loggability/formatter/color.rb
10
10
  lib/loggability/formatter/default.rb
11
11
  lib/loggability/formatter/html.rb
12
+ lib/loggability/logclient.rb
12
13
  lib/loggability/logger.rb
14
+ lib/loggability/loghost.rb
15
+ lib/loggability/override.rb
13
16
  lib/loggability/spechelpers.rb
14
- spec/lib/helpers.rb
17
+ spec/helpers.rb
15
18
  spec/loggability/formatter/color_spec.rb
16
19
  spec/loggability/formatter/html_spec.rb
17
20
  spec/loggability/formatter_spec.rb
18
21
  spec/loggability/logger_spec.rb
22
+ spec/loggability/override_spec.rb
19
23
  spec/loggability_spec.rb
data/README.rdoc CHANGED
@@ -206,6 +206,36 @@ methods on Loggability::Logger:
206
206
  Loggability.output_to( "/tmp/my_project_log.html" )
207
207
 
208
208
 
209
+ === Temporarily Overriding Logging Behavior
210
+
211
+ Sometimes you want to log one particular chunk of code at a different
212
+ level, or to a different destination, and then restore everything back
213
+ to the way it was afterwards.
214
+
215
+ Loggability has a few ways of doing that:
216
+
217
+ # Log only fatal errors...
218
+ Loggability.with_level( :fatal ) do
219
+ ...
220
+ end
221
+
222
+ # Log everything to an array for the block
223
+ logs = []
224
+ Loggability.outputting_to( logs ) do
225
+ ...
226
+ end
227
+
228
+ # Log using the HTML formatter
229
+ Loggability.formatted_with( :html ) do
230
+ ...
231
+ end
232
+
233
+ # Or chain them together:
234
+ Loggability.with_level( :debug ).outputting_to( $stderr ).formatted_with( :color ) do
235
+ Client.connect!
236
+ end
237
+
238
+
209
239
  == Contributing
210
240
 
211
241
  You can check out the current development source with
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ end
11
11
  Hoe.plugin :mercurial
12
12
  Hoe.plugin :signing
13
13
  Hoe.plugin :deveiate
14
+ Hoe.plugin :bundler
14
15
 
15
16
  Hoe.plugins.delete :rubyforge
16
17
 
@@ -22,11 +23,12 @@ hoespec = Hoe.spec 'loggability' do
22
23
  self.developer 'Michael Granger', 'ged@FaerieMUD.org'
23
24
 
24
25
  self.dependency 'hoe-deveiate', '~> 0.3', :developer
26
+ self.dependency 'hoe-bundler', '~> 1.2', :developer
25
27
  self.dependency 'simplecov', '~> 0.7', :developer
26
28
  self.dependency 'configurability', '~> 2.0', :developer
27
29
 
28
- self.spec_extras[:licenses] = ["Ruby"]
29
- self.require_ruby_version( '>=1.8.7' )
30
+ self.license "Ruby"
31
+ self.require_ruby_version( '>=1.9.3' )
30
32
  self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
31
33
  self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
32
34
 
@@ -36,7 +38,7 @@ end
36
38
  ENV['VERSION'] ||= hoespec.spec.version.to_s
37
39
 
38
40
  # Ensure the specs pass before checking in
39
- task 'hg:precheckin' => [ :check_history, :check_manifest, :spec ]
41
+ task 'hg:precheckin' => [ :check_history, 'bundler:gemfile', :check_manifest, :spec ]
40
42
 
41
43
 
42
44
  desc "Build a coverage report"
@@ -0,0 +1,48 @@
1
+ # -*- ruby -*-
2
+ #encoding: utf-8
3
+
4
+ require 'loggability' unless defined?( Loggability )
5
+
6
+ # Methods to install for objects which call +log_to+.
7
+ module Loggability::LogClient
8
+
9
+ ##
10
+ # The key of the log host this client targets
11
+ attr_accessor :log_host_key
12
+
13
+ ### Return the Loggability::Logger object associated with the log host the
14
+ ### client is logging to.
15
+ ### :TODO: Use delegation for efficiency.
16
+ def log
17
+ @__log ||= Loggability[ self ].proxy_for( self )
18
+ end
19
+
20
+
21
+ ### Inheritance hook -- set the log host key of subclasses to the same
22
+ ### thing as the extended class.
23
+ def inherited( subclass )
24
+ super
25
+ Loggability.log.debug "Setting up subclass %p of %p to log to %p" %
26
+ [ subclass, self, self.log_host_key ]
27
+ subclass.log_host_key = self.log_host_key
28
+ end
29
+
30
+
31
+ # Stuff that gets added to instances of Classes that are log hosts.
32
+ module InstanceMethods
33
+
34
+ ### Fetch the key of the log host the instance of this client targets
35
+ def log_host_key
36
+ return self.class.log_host_key
37
+ end
38
+
39
+
40
+ ### Delegate to the class's logger.
41
+ def log
42
+ @__log ||= Loggability[ self.class ].proxy_for( self )
43
+ end
44
+
45
+ end # module InstanceMethods
46
+
47
+ end # module Loggability::LogClient
48
+
@@ -163,7 +163,7 @@ class Loggability::Logger < ::Logger
163
163
  dev = if self.logdev.respond_to?( :dev )
164
164
  self.logdev.dev.class
165
165
  else
166
- self.logdev.target.class
166
+ self.logdev
167
167
  end
168
168
 
169
169
  return "#<%p:%#x severity: %s, formatter: %s, outputting to: %p>" % [
@@ -185,6 +185,25 @@ class Loggability::Logger < ::Logger
185
185
  end
186
186
 
187
187
 
188
+ ### Return a Hash that contains its settings suitable for restoration via
189
+ ### #restore_settings later.
190
+ def settings
191
+ return {
192
+ level: self.level,
193
+ logdev: self.logdev,
194
+ formatter: self.formatter,
195
+ }
196
+ end
197
+
198
+
199
+ ### Restore the level, logdev, and formatter from the given +settings+.
200
+ def restore_settings( settings )
201
+ self.level = settings[:level] if settings[ :level ]
202
+ self.output_to( settings[:logdev] ) if settings[ :logdev ]
203
+ self.format_with( settings[:formatter] ) if settings[ :formatter ]
204
+ end
205
+
206
+
188
207
  #
189
208
  # :section: Severity Level
190
209
  #
@@ -196,8 +215,8 @@ class Loggability::Logger < ::Logger
196
215
  end
197
216
 
198
217
 
199
- ### Set the logger level to +newlevel+, which can be a numeric level (e.g., Logger::DEBUG, etc.),
200
- ### or a symbolic level (e.g., :debug, :info, etc.)
218
+ ### Set the logger level to +newlevel+, which can be a numeric level (e.g.,
219
+ ### Logger::DEBUG, etc.), or a symbolic level (e.g., :debug, :info, etc.)
201
220
  def level=( newlevel )
202
221
  newlevel = LOG_LEVELS[ newlevel.to_sym ] if
203
222
  newlevel.respond_to?( :to_sym ) && LOG_LEVELS.key?( newlevel.to_sym )
@@ -218,7 +237,10 @@ class Loggability::Logger < ::Logger
218
237
  ### logging to IO objects and files (given a filename in a String), this method can also
219
238
  ### set up logging to any object that responds to #<<.
220
239
  def output_to( target, *args )
221
- if target.respond_to?( :write ) || target.is_a?( String )
240
+ if target.is_a?( Logger::LogDevice ) ||
241
+ target.is_a?( Loggability::Logger::AppendingLogDevice )
242
+ self.logdev = target
243
+ elsif target.respond_to?( :write ) || target.is_a?( String )
222
244
  opts = { :shift_age => args.shift || 0, :shift_size => args.shift || 1048576 }
223
245
  self.logdev = Logger::LogDevice.new( target, opts )
224
246
  elsif target.respond_to?( :<< )
@@ -0,0 +1,40 @@
1
+ # -*- ruby -*-
2
+ #encoding: utf-8
3
+
4
+ require 'loggability' unless defined?( Loggability )
5
+
6
+ # Extension for 'log hosts'. A <b>log host</b> is an object that hosts a Loggability::Logger
7
+ # object, and is typically the top of some kind of hierarchy, like a namespace
8
+ # module for a project:
9
+ #
10
+ # module MyProject
11
+ #
12
+ # end
13
+ #
14
+ # This module isn't mean to be used directly -- it's installed via the Loggability#log_as
15
+ # declaration, which also does some other initialization that you'll likely want.
16
+ #
17
+ #
18
+ module Loggability::LogHost
19
+
20
+ # The logger that will be used when the logging subsystem is reset
21
+ attr_accessor :default_logger
22
+
23
+ # The logger that's currently in effect
24
+ attr_reader :logger
25
+ alias_method :log, :logger
26
+
27
+ # The key associated with the logger for this host
28
+ attr_accessor :log_host_key
29
+
30
+
31
+ ### Set the logger associated with the LogHost to +newlogger+. If +newlogger+ isn't a
32
+ ### Loggability::Logger, it will be converted to one.
33
+ def logger=( newlogger )
34
+ @logger = Loggability::Logger( newlogger )
35
+ end
36
+ alias_method :log=, :logger=
37
+
38
+ end # module Loggability::LogHost
39
+
40
+
@@ -0,0 +1,171 @@
1
+ # -*- ruby -*-
2
+ #encoding: utf-8
3
+
4
+ require 'monitor'
5
+ require 'loggability' unless defined?( Loggability )
6
+
7
+
8
+ # A class which encapsulates the logic and data of temporarily overriding one or
9
+ # more aspects of logging for the execution of one or more blocks of code.
10
+ #
11
+ # It's not meant to be used directly, but via one of the override aggregate methods
12
+ # on Loggability:
13
+ #
14
+ # * Loggability.with_level
15
+ # * Loggability.outputting_to
16
+ # * Loggability.formatted_with
17
+ #
18
+ class Loggability::Override
19
+ include MonitorMixin
20
+
21
+
22
+ ### Return an Override with its logging level set to +newlevel+.
23
+ def self::with_level( new_level )
24
+ return self.new( level: new_level )
25
+ end
26
+
27
+
28
+ ### Return an Override with its logging output set to +new_destination+.
29
+ def self::outputting_to( new_destination )
30
+ return self.new( logdev: new_destination )
31
+ end
32
+
33
+
34
+ ### Return an Override with its logging formatter set to +formatter+.
35
+ def self::formatted_with( new_formatter )
36
+ return self.new( formatter: new_formatter )
37
+ end
38
+
39
+
40
+ ### Create a new Override with the specified +settings+ that will be applied
41
+ ### during a call to #call, and then reverted when #call returns. Valid +settings+
42
+ ### are:
43
+ ###
44
+ ### [:level]
45
+ ### Set the level of all Loggers to the value.
46
+ ### [:logdev]
47
+ ### Set the destination log device of all Loggers to the value.
48
+ ### [:formatter]
49
+ ### Set the formatter for all Loggers to the value (a Loggability::Formatter).
50
+ ###
51
+ def initialize( settings={} )
52
+ super()
53
+
54
+ @settings = settings
55
+ @overridden_settings = {}
56
+ end
57
+
58
+
59
+ ### Copy constructor -- make copies of the internal data structures
60
+ ### when duplicated.
61
+ def initialize_copy( original )
62
+ @settings = original.settings.dup
63
+ @overridden_settings = {}
64
+ end
65
+
66
+
67
+ ######
68
+ public
69
+ ######
70
+
71
+ # The Override's settings Hash (the settings that will be applied during
72
+ # an overridden #call).
73
+ attr_reader :settings
74
+
75
+ # The original settings preserved by the Override during a call to #call,
76
+ # keyed by the logger they belong to.
77
+ attr_reader :overridden_settings
78
+
79
+
80
+ ### Call the provided block with configured overrides applied, and then restore
81
+ ### the previous settings before control is returned.
82
+ def call
83
+ self.apply_overrides
84
+ yield
85
+ ensure
86
+ self.restore_overridden_settings
87
+ end
88
+
89
+
90
+ #
91
+ # Mutator Methods
92
+ #
93
+
94
+ ### Return a clone of the receiving Override with its logging level
95
+ ### set to +newlevel+.
96
+ def with_level( new_level )
97
+ return self.clone_with( level: new_level )
98
+ end
99
+
100
+
101
+ ### Return a clone of the receiving Override with its logging output
102
+ ### set to +new_destination+.
103
+ def outputting_to( new_destination )
104
+ return self.clone_with( logdev: new_destination )
105
+ end
106
+
107
+
108
+ ### Return a clone of the receiving Override with its logging formatter
109
+ ### set to +formatter+.
110
+ def formatted_with( new_formatter )
111
+ return self.clone_with( formatter: new_formatter )
112
+ end
113
+
114
+
115
+ ### Return the object as a human-readable string suitable for debugging.
116
+ def inspect
117
+ return "#<%p:%#016x formatter: %s, level: %s, output: %s>" % [
118
+ self.class,
119
+ self.object_id * 2,
120
+ self.settings[:formatter] || '-',
121
+ self.settings[:level] || '-',
122
+ self.settings[:logdev] ? self.settings[:logdev].class : '-',
123
+ ]
124
+ end
125
+
126
+
127
+ #########
128
+ protected
129
+ #########
130
+
131
+ ### Return a clone that has been modified with the specified +new_settings+.
132
+ def clone_with( new_settings )
133
+ newobj = self.dup
134
+ newobj.settings.merge!( new_settings )
135
+
136
+ return newobj
137
+ end
138
+
139
+
140
+ ### Apply any configured overrides to all loggers.
141
+ def apply_overrides
142
+ self.synchronize do
143
+ raise LocalJumpError, "can't be called re-entrantly" unless
144
+ @overridden_settings.empty?
145
+ @overridden_settings = self.gather_current_settings
146
+ end
147
+
148
+ Loggability.log_hosts.each do |key, host|
149
+ host.logger.restore_settings( self.settings )
150
+ end
151
+ end
152
+
153
+
154
+ ### Return a Hash of Loggers with the settings they currently have.
155
+ def gather_current_settings
156
+ return Loggability.log_hosts.values.each_with_object( {} ) do |host, hash|
157
+ hash[ host ] = host.logger.settings
158
+ end
159
+ end
160
+
161
+
162
+ ### Restore the last settings saved by #apply_overrides to their corresponding
163
+ ### loggers.
164
+ def restore_overridden_settings
165
+ @overridden_settings.each do |host, settings|
166
+ host.logger.restore_settings( settings )
167
+ end
168
+ @overridden_settings.clear
169
+ end
170
+
171
+ end # class Loggability::Override
data/lib/loggability.rb CHANGED
@@ -9,10 +9,10 @@ require 'date'
9
9
  module Loggability
10
10
 
11
11
  # Package version constant
12
- VERSION = '0.7.0'
12
+ VERSION = '0.8.0'
13
13
 
14
14
  # VCS revision
15
- REVISION = %q$Revision: 7e7b1c51eb3e $
15
+ REVISION = %q$Revision: 44b025b728e6 $
16
16
 
17
17
  # The key for the global logger (Loggability's own logger)
18
18
  GLOBAL_KEY = :__global__
@@ -53,6 +53,12 @@ module Loggability
53
53
  @log_hosts = {}
54
54
 
55
55
 
56
+ # Automatically log the log host and log client mixins when they're referenced
57
+ autoload :LogHost, 'loggability/loghost'
58
+ autoload :LogClient, 'loggability/logclient'
59
+ autoload :Override, 'loggability/override'
60
+
61
+
56
62
  ### Return the library's version string
57
63
  def self::version_string( include_buildnum=false )
58
64
  vstring = "%s %s" % [ self.name, VERSION ]
@@ -145,6 +151,21 @@ module Loggability
145
151
  end
146
152
 
147
153
 
154
+ ### Aggregate method: set the log level on all loggers to +level+ for the duration
155
+ ### of the +block+, restoring the original levels afterward. If no block is given, returns a
156
+ ### Loggability::Override object that set the log level to +level+ while its +#call+
157
+ ### method is being called.
158
+ def self::with_level( level, &block )
159
+ override = Loggability::Override.with_level( level )
160
+
161
+ if block
162
+ return override.call( &block )
163
+ else
164
+ return override
165
+ end
166
+ end
167
+
168
+
148
169
  ##
149
170
  # :method: output_to
150
171
  # :call-seq:
@@ -161,6 +182,21 @@ module Loggability
161
182
  end
162
183
 
163
184
 
185
+ ### Aggregate method: set all loggers to log to +destination+ for the duration of the
186
+ ### +block+, restoring the original destination afterward. If no block is given, returns a
187
+ ### Loggability::Override object that will log to +destination+ whenever its +#call+ method is
188
+ ### called.
189
+ def self::outputting_to( newdevice, &block )
190
+ override = Loggability::Override.outputting_to( newdevice )
191
+
192
+ if block
193
+ return override.call( &block )
194
+ else
195
+ return override
196
+ end
197
+ end
198
+
199
+
164
200
  ##
165
201
  # :method: format_with
166
202
  # :call-seq:
@@ -179,83 +215,19 @@ module Loggability
179
215
  end
180
216
 
181
217
 
182
- # Extension for 'log hosts'. A <b>log host</b> is an object that hosts a Loggability::Logger
183
- # object, and is typically the top of some kind of hierarchy, like a namespace
184
- # module for a project:
185
- #
186
- # module MyProject
187
- #
188
- # end
189
- #
190
- # This module isn't mean to be used directly -- it's installed via the Loggability#log_as
191
- # declaration, which also does some other initialization that you'll likely want.
192
- #
193
- #
194
- module LogHost
195
-
196
- # The logger that will be used when the logging subsystem is reset
197
- attr_accessor :default_logger
198
-
199
- # The logger that's currently in effect
200
- attr_reader :logger
201
- alias_method :log, :logger
202
-
203
- # The key associated with the logger for this host
204
- attr_accessor :log_host_key
218
+ ### Aggregate method: set all loggers to log with the given +formatter+ for the duration
219
+ ### of the +block+, restoring the original formatters afterward. If no block is given,
220
+ ### returns a Loggability::Override object that will override all formatters whenever its
221
+ ### +#call+ method is called.
222
+ def self::formatted_with( formatter, &block )
223
+ override = Loggability::Override.formatted_with( formatter )
205
224
 
206
-
207
- ### Set the logger associated with the LogHost to +newlogger+. If +newlogger+ isn't a
208
- ### Loggability::Logger, it will be converted to one.
209
- def logger=( newlogger )
210
- @logger = Loggability::Logger( newlogger )
211
- end
212
- alias_method :log=, :logger=
213
-
214
- end # module LogHost
215
-
216
-
217
- # Methods to install for objects which call +log_to+.
218
- module LogClient
219
-
220
- ##
221
- # The key of the log host this client targets
222
- attr_accessor :log_host_key
223
-
224
- ### Return the Loggability::Logger object associated with the log host the
225
- ### client is logging to.
226
- ### :TODO: Use delegation for efficiency.
227
- def log
228
- @__log ||= Loggability[ self ].proxy_for( self )
229
- end
230
-
231
-
232
- ### Inheritance hook -- set the log host key of subclasses to the same
233
- ### thing as the extended class.
234
- def inherited( subclass )
235
- super
236
- Loggability.log.debug "Setting up subclass %p of %p to log to %p" %
237
- [ subclass, self, self.log_host_key ]
238
- subclass.log_host_key = self.log_host_key
225
+ if block
226
+ return override.call( &block )
227
+ else
228
+ return override
239
229
  end
240
-
241
-
242
- # Stuff that gets added to instances of Classes that are log hosts.
243
- module InstanceMethods
244
-
245
- ### Fetch the key of the log host the instance of this client targets
246
- def log_host_key
247
- return self.class.log_host_key
248
- end
249
-
250
-
251
- ### Delegate to the class's logger.
252
- def log
253
- @__log ||= Loggability[ self.class ].proxy_for( self )
254
- end
255
-
256
- end # module InstanceMethods
257
-
258
- end # module LogClient
230
+ end
259
231
 
260
232
 
261
233
  #
data/spec/helpers.rb ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ BEGIN {
6
+ require 'pathname'
7
+ basedir = Pathname.new( __FILE__ ).dirname.parent
8
+
9
+ libdir = basedir + "lib"
10
+
11
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
12
+ }
13
+
14
+ # SimpleCov test coverage reporting; enable this using the :coverage rake task
15
+ if ENV['COVERAGE']
16
+ $stderr.puts "\n\n>>> Enabling coverage report.\n\n"
17
+ require 'simplecov'
18
+ SimpleCov.start do
19
+ add_filter 'spec'
20
+ end
21
+ end
22
+
23
+ begin
24
+ require 'configurability'
25
+ rescue LoadError
26
+ end
27
+
28
+ require 'loggability'
29
+ require 'loggability/spechelpers'
30
+
31
+
32
+ # Helpers specific to Loggability specs
33
+ module SpecHelpers
34
+
35
+ ### An object identity matcher for collections.
36
+ class AllBeMatcher
37
+
38
+ def initialize( expected )
39
+ @expected = expected
40
+ end
41
+
42
+ def matches?( collection )
43
+ @collection = collection
44
+ return collection.all? {|obj| obj.equal?(@expected) }
45
+ end
46
+
47
+ def description
48
+ "to all be %p" % [ @expected ]
49
+ end
50
+
51
+ def failure_message
52
+ "but they were: %p" % [ @collection ]
53
+ end
54
+
55
+ end # class AllBeMatcher
56
+
57
+
58
+ ### An object kind matcher for collections
59
+ class AllBeAMatcher
60
+
61
+ def initialize( expected_class )
62
+ @expected_class = expected_class
63
+ end
64
+
65
+ def matches?( collection )
66
+ @collection = collection
67
+ return collection.all? {|obj| obj.is_a?(@expected_class) }
68
+ end
69
+
70
+ def description
71
+ "to all be a %p" % [ @expected_class ]
72
+ end
73
+
74
+ def failure_message
75
+ unmatched = @collection.find {|obj| !obj.is_a?(@expected_class) }
76
+ "but (at least) one was not. It was a %p (%s)" % [
77
+ unmatched.class,
78
+ unmatched.class.ancestors.map(&:inspect).join(' < '),
79
+ ]
80
+ end
81
+
82
+ end # class AllBeAMatcher
83
+
84
+
85
+ ###############
86
+ module_function
87
+ ###############
88
+
89
+ ### Return true if the actual value includes the specified +objects+.
90
+ def all_be( expected_object )
91
+ AllBeMatcher.new( expected_object )
92
+ end
93
+
94
+ ### Returns +true+ if every object in the collection inherits from the +expected_class+.
95
+ def all_be_a( expected_class )
96
+ AllBeAMatcher.new( expected_class )
97
+ end
98
+
99
+ end # module SpecHelpers
100
+
101
+
102
+ ### Mock with RSpec
103
+ RSpec.configure do |c|
104
+ c.treat_symbols_as_metadata_keys_with_true_values = true
105
+ c.run_all_when_everything_filtered = true
106
+ c.filter_run :focus
107
+ c.order = 'random'
108
+ c.mock_with( :rspec ) do |mock|
109
+ mock.syntax = :expect
110
+ end
111
+
112
+ c.include( SpecHelpers )
113
+ c.include( Loggability::SpecHelpers )
114
+ c.filter_run_excluding( :configurability ) unless defined?( Configurability )
115
+ end
116
+