Class: Shoulda::Context::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/shoulda/context/context.rb

Overview

:nodoc:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, parent, &blk) ⇒ Context



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/shoulda/context/context.rb', line 301

def initialize(name, parent, &blk)
  Shoulda::Context.add_context(self)
  self.name               = name
  self.parent             = parent
  self.setup_blocks       = []
  self.teardown_blocks    = []
  self.shoulds            = []
  self.should_eventuallys = []
  self.subcontexts        = []
  self.subject_block      = nil

  if block_given?
    merge_block(&blk)
  else
    merge_block { warn "  * WARNING: Block missing for context '#{full_name}'" }
  end
  Shoulda::Context.remove_context
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &blk) ⇒ Object



481
482
483
# File 'lib/shoulda/context/context.rb', line 481

def method_missing(method, *args, &blk)
  test_unit_class.send(method, *args, &blk)
end

Instance Attribute Details

#nameObject

my name



286
287
288
# File 'lib/shoulda/context/context.rb', line 286

def name
  @name
end

#parentObject

may be another context, or the original test::unit class.



287
288
289
# File 'lib/shoulda/context/context.rb', line 287

def parent
  @parent
end

#setup_blocksObject

blocks given via setup methods



289
290
291
# File 'lib/shoulda/context/context.rb', line 289

def setup_blocks
  @setup_blocks
end

#should_eventuallysObject

array of hashes representing the should eventually statements



292
293
294
# File 'lib/shoulda/context/context.rb', line 292

def should_eventuallys
  @should_eventuallys
end

#shouldsObject

array of hashes representing the should statements



291
292
293
# File 'lib/shoulda/context/context.rb', line 291

def shoulds
  @shoulds
end

#subcontextsObject

array of contexts nested under myself



288
289
290
# File 'lib/shoulda/context/context.rb', line 288

def subcontexts
  @subcontexts
end

#subject_blockObject

accessor with cache



295
296
297
298
# File 'lib/shoulda/context/context.rb', line 295

def subject_block
  return @subject_block if @subject_block
  parent.subject_block
end

#teardown_blocksObject

blocks given via teardown methods



290
291
292
# File 'lib/shoulda/context/context.rb', line 290

def teardown_blocks
  @teardown_blocks
end

Instance Method Details

#am_subcontext?Boolean



375
376
377
# File 'lib/shoulda/context/context.rb', line 375

def am_subcontext?
  parent.is_a?(self.class) # my parent is the same class as myself.
end

#buildObject



463
464
465
466
467
468
469
470
471
# File 'lib/shoulda/context/context.rb', line 463

def build
  shoulds.each do |should|
    create_test_from_should_hash(should)
  end

  subcontexts.each { |context| context.build }

  print_should_eventuallys
end

#context(name, &blk) ⇒ Object



329
330
331
# File 'lib/shoulda/context/context.rb', line 329

def context(name, &blk)
  self.subcontexts << Context.new(name, self, &blk)
end

#create_test_from_should_hash(should) ⇒ Object



389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/shoulda/context/context.rb', line 389

def create_test_from_should_hash(should)
  test_name = [test_name_prefix, full_name, "should", "#{should[:name]}. "].flatten.join(' ').to_sym

  if test_methods[test_unit_class][test_name.to_s] then
    raise DuplicateTestError, "'#{test_name}' is defined more than once."
  end

  test_methods[test_unit_class][test_name.to_s] = true

  context = self
  test_unit_class.send(:define_method, test_name) do
    @shoulda_context = context
    begin
      context.run_parent_setup_blocks(self)
      if should[:before]
        if self.respond_to?(:instance_exec)
          self.instance_exec(&should[:before])
        else
          # deprecated in Rails 4.x
          should[:before].bind(self).call
        end
      end
      context.run_current_setup_blocks(self)
      if self.respond_to?(:instance_exec)
        self.instance_exec(&should[:block])
      else
        # deprecated in Rails 4.x
        should[:block].bind(self).call
      end
    ensure
      context.run_all_teardown_blocks(self)
    end
  end
end

#full_nameObject



370
371
372
373
# File 'lib/shoulda/context/context.rb', line 370

def full_name
  parent_name = parent.full_name if am_subcontext?
  return [parent_name, name].join(" ").strip
end

#merge_block(&blk) ⇒ Object



320
321
322
323
324
325
326
327
# File 'lib/shoulda/context/context.rb', line 320

def merge_block(&blk)
  if self.respond_to?(:instance_exec)
    self.instance_exec(&blk)
  else
    # deprecated in Rails 4.x
    blk.bind(self).call
  end
end


456
457
458
459
460
461
# File 'lib/shoulda/context/context.rb', line 456

def print_should_eventuallys
  should_eventuallys.each do |should|
    test_name = [full_name, "should", "#{should[:name]}. "].flatten.join(' ')
    puts "  * DEFERRED: " + test_name
  end
end

#run_all_setup_blocks(binding) ⇒ Object



424
425
426
427
# File 'lib/shoulda/context/context.rb', line 424

def run_all_setup_blocks(binding)
  run_parent_setup_blocks(binding)
  run_current_setup_blocks(binding)
end

#run_all_teardown_blocks(binding) ⇒ Object



444
445
446
447
448
449
450
451
452
453
454
# File 'lib/shoulda/context/context.rb', line 444

def run_all_teardown_blocks(binding)
  teardown_blocks.reverse.each do |teardown_block|
    if binding.respond_to?(:instance_exec)
      binding.instance_exec(&teardown_block)
    else
      # deprecated in Rails 4.x
      teardown_block.bind(binding).call
    end
  end
  self.parent.run_all_teardown_blocks(binding) if am_subcontext?
end

#run_current_setup_blocks(binding) ⇒ Object



433
434
435
436
437
438
439
440
441
442
# File 'lib/shoulda/context/context.rb', line 433

def run_current_setup_blocks(binding)
  setup_blocks.each do |setup_block|
    if binding.respond_to?(:instance_exec)
      binding.instance_exec(&setup_block)
    else
      # deprecated in Rails 4.x
      setup_block.bind(binding).call
    end
  end
end

#run_parent_setup_blocks(binding) ⇒ Object



429
430
431
# File 'lib/shoulda/context/context.rb', line 429

def run_parent_setup_blocks(binding)
  self.parent.run_all_setup_blocks(binding) if am_subcontext?
end

#setup(&blk) ⇒ Object



333
334
335
# File 'lib/shoulda/context/context.rb', line 333

def setup(&blk)
  self.setup_blocks << blk
end

#should(name_or_matcher, options = {}, &blk) ⇒ Object



341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/shoulda/context/context.rb', line 341

def should(name_or_matcher, options = {}, &blk)
  if name_or_matcher.respond_to?(:description) && name_or_matcher.respond_to?(:matches?)
    name = name_or_matcher.description
    blk = lambda { assert_accepts name_or_matcher, subject }
  else
    name = name_or_matcher
  end

  if blk
    self.shoulds << { :name => name, :before => options[:before], :block => blk }
  else
    self.should_eventuallys << { :name => name }
  end
end

#should_eventually(name, &blk) ⇒ Object



362
363
364
# File 'lib/shoulda/context/context.rb', line 362

def should_eventually(name, &blk)
  self.should_eventuallys << { :name => name, :block => blk }
end

#should_not(matcher) ⇒ Object



356
357
358
359
360
# File 'lib/shoulda/context/context.rb', line 356

def should_not(matcher)
  name = matcher.description
  blk = lambda { assert_rejects matcher, subject }
  self.shoulds << { :name => "not #{name}", :block => blk }
end

#subject(&block) ⇒ Object



366
367
368
# File 'lib/shoulda/context/context.rb', line 366

def subject(&block)
  self.subject_block = block
end

#teardown(&blk) ⇒ Object



337
338
339
# File 'lib/shoulda/context/context.rb', line 337

def teardown(&blk)
  self.teardown_blocks << blk
end

#test_methodsObject



383
384
385
386
387
# File 'lib/shoulda/context/context.rb', line 383

def test_methods
  @test_methods ||= Hash.new { |h,k|
    h[k] = Hash[k.instance_methods.map { |n| [n, true] }]
  }
end

#test_name_prefixObject



473
474
475
476
477
478
479
# File 'lib/shoulda/context/context.rb', line 473

def test_name_prefix
  if defined?(Minitest) || defined?(MiniTest)
    'test_:'
  else
    'test:'
  end
end

#test_unit_classObject



379
380
381
# File 'lib/shoulda/context/context.rb', line 379

def test_unit_class
  am_subcontext? ? parent.test_unit_class : parent
end