Module: NRSER::Rash::Testing

Defined in:
lib/nrser/rash/testing.rb

Overview

TODO:

It seems like testing doesn't work in the state I came back to it 2018.02.22

Defined Under Namespace

Classes: FunctionTestCase, NoTestCasesError

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

._test_casesObject

Returns the value of attribute _test_cases.



78
79
80
# File 'lib/nrser/rash/testing.rb', line 78

def _test_cases
  @_test_cases
end

.module_or_function_nameObject

Returns the value of attribute module_or_function_name.



77
78
79
# File 'lib/nrser/rash/testing.rb', line 77

def module_or_function_name
  @module_or_function_name
end

.ref_pathObject

Returns the value of attribute ref_path.



79
80
81
# File 'lib/nrser/rash/testing.rb', line 79

def ref_path
  @ref_path
end

Class Method Details

.start(module_or_function_name) ⇒ Object



86
87
88
89
90
91
92
93
# File 'lib/nrser/rash/testing.rb', line 86

def self.start(module_or_function_name)
  
  define_test_class

  self.module_or_function_name = module_or_function_name
  self.ref_path = NRSER::Rash.ref_path(module_or_function_name)
  self._test_cases = []
end

.temp_env(hash, &block) ⇒ Object



291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/nrser/rash/testing.rb', line 291

def self.temp_env hash, &block
  old = Hash[hash.keys.map {|key| ENV[key] }]
  begin
    hash.each do |key, value|
      ENV[key] = value
    end
    block.()
  ensure
    old.each do |key, value|
      ENV[key] = value
    end
  end
end

.testObject



82
83
84
# File 'lib/nrser/rash/testing.rb', line 82

def self.test
  NRSER::Rash.logger.info "self: #{self.inspect}"
end

.test_case(target_method, &block) ⇒ Object

create and run a Minitest::Test with &block as the body, supplying target_method as an instance method under it's name and also the name 'target_method'



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/nrser/rash/testing.rb', line 170

def self.test_case(target_method, &block)
  # bail out if we're not in a testing state. this prevents the code
  # from going any further for other commands like `profile` and `call`.
  return unless NRSER::Rash::Testing.testing?

  method_name = target_method.name.to_s

  # since we're testing, `Testing.pattern` will be a string the user
  # supplied on the command line, like `Project.dir_name`. we're going
  # to compare it to the method path we're being asked to define
  # the test case for to see if we should acutally create the
  # `Minitest::Test` class.
  method_ref_path = NRSER::Rash.ref_path(target_method.receiver.name,
                                  target_method.name.to_s)[2..-1]

  # go through each segment in the ref path we're testing and bail if
  # it doesn't match the coresponding segment in the method's ref path.
  #
  # this only goes up until the testing ref path runs out, which allows
  # the user to specify something like `Url.Parse` to test all the
  # functions under the `NRSER::Rash::Functions::Url::Parse` module.
  Testing.ref_path.each_with_index do |segment, index|
    return unless segment == method_ref_path[index]
  end

  # if we made it to this point, we should be testing the function and
  # will define the `Test::Unit` subclass:
  _test_case = Class.new NRSER::Rash::Testing::FunctionTestCase do

    # allow easy access to the target method inside the test methods
    # by defining a method with the same name that points
    # to the target method
    define_method method_name, &target_method

    # the proxy method should be private so that functions that
    # start with `'test'` aren't run by `Test::Unit`
    private method_name

    # also define a version named `apply_target` to provide a
    # shortcut for programtic access in helpers like
    # `FunctionTestCase.assert_map` and what not.
    #
    # NOTE: i did this instead of just using `self.class.target_method`
    #       as defined below because i wanted the method to be exactly
    #       the same as when calling with the previous alias. i might
    #       remove it, not sure. it seems redundant.
    define_method :apply_target, &target_method

    # and include a direct reference the target method in a class
    # instance variable with an attribute reader so it's accessible
    # in case it's needed at some point (it's not at the moment).
    # 
    # it can be accessed from inside `FunctionTestCase` subclasses like:
    # 
    #    self.class.target_method
    #
    @target_method = target_method
    class << self
      attr_reader :target_method
    end
  end
  
  # i ran into some "warning: class variable access from toplevel" shit
  # at some point, and this was a part of fixing it. though it no longer
  # seems necessary, i'm going to leave it for a moment:
  # _test_case.instance_eval do
  #   @test_method = test_method
  # end

  # add the user-supplied methods
  _test_case.class_eval &block

  # programtically create a name for the class and use that to create
  # a constant referencing it in the invoking module, which causes the
  # class to assume that name and module as far as it's `name` method
  # and printing and such, which is nice for the unit test output.
  #
  # names are created by appending the `method_name` to 'Test_', with
  # '!' converted to '_bang' and '?' converted to '_q' (since constants
  # can't have '!' or '?' in them).
  #
  # example:
  #
  # say you had a module like
  #     
  #     module NRSER::Rash::Functions::SomeNamespace
  #       extend NRSER::Rash::Testing::Extensions
  #       
  #       def self.some_function
  #         "hooray!"
  #       end
  #       
  #       _test_case :some_function do
  #         def test_some_function
  #           assert_equal some_function, "horray!"
  #         end
  #       end
  #     end
  # 
  # then you would get a `Minitest::Test` subclass named
  # 
  #     NRSER::Rash::Functions::SomeNamespace::Test_some_function
  #
  # which seems reasonable enough.
  class_name =  "Test_" +
                method_name.to_s.gsub('!', '_bang').gsub('?', '_q')
  const_set class_name, _test_case

  # and finally, add the class to the `_test_cases` array, which allows
  # us to see what classes were defined after the modules are loaded.
  NRSER::Rash::Testing._test_cases << _test_case
end

.test_function(target_method, &block) ⇒ Object

create a Minitest::Test subclass with a single test method for target_method with &block as the body.



285
286
287
288
289
# File 'lib/nrser/rash/testing.rb', line 285

def self.test_function(target_method, &block)
  test_case target_method do
    define_method "test_#{ target_method.name }", &block
  end
end

.testing?Boolean

used to figure out if we're testing

Returns:

  • (Boolean)


96
97
98
# File 'lib/nrser/rash/testing.rb', line 96

def self.testing?
  !!module_or_function_name
end