Module: MiniSpec::ClassAPI

Included in:
Minispec
Defined in:
lib/minispec/api/class.rb,
lib/minispec/api/class/let.rb,
lib/minispec/api/class/after.rb,
lib/minispec/api/class/tests.rb,
lib/minispec/api/class/around.rb,
lib/minispec/api/class/before.rb,
lib/minispec/api/class/helpers.rb

Instance Method Summary collapse

Instance Method Details

#after(*matchers, &proc) ⇒ Object

Note:

‘after` hooks will run even on failed tests. however it wont run if some exception arise inside test.

same as ‘before` except it will run after matched tests.



7
8
9
10
11
12
13
# File 'lib/minispec/api/class/after.rb', line 7

def after *matchers, &proc
  proc || raise(ArgumentError, 'block is missing')
  matchers.flatten!
  matchers = [:*] if matchers.empty?
  return if after?.find {|x| x[0] == matchers && x[1].source_location == proc.source_location}
  after?.push([matchers, proc])
end

#after?(filter = nil) ⇒ Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/minispec/api/class/after.rb', line 15

def after? filter = nil
  hooks_filter(@after ||= [], filter)
end

#after_all(&proc) ⇒ Object Also known as: after!

Note:

this callback will run even if there are failed tests.

code to run once after all tests finished. this callback will run only once. for callbacks that runs after any test @see #after



35
36
37
38
# File 'lib/minispec/api/class/after.rb', line 35

def after_all &proc
  proc || raise(ArgumentError, 'block is missing')
  @after_all = proc
end

#after_all?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/minispec/api/class/after.rb', line 41

def after_all?
  @after_all
end

#alias_helper(target, source) ⇒ Object



101
102
103
104
105
# File 'lib/minispec/api/class/helpers.rb', line 101

def alias_helper target, source
  proc, opts = helpers[source]
  proc || raise(ArgumentError, '%s helper does not exists' % source.inspect)
  helper(target, opts, &proc)
end

#around(*matchers, &proc) ⇒ Object

a block to wrap each test evaluation

Examples:

describe SomeClass do

  around do |test|
    DB.connect
    test.run
    DB.disconnect
  end
end


16
17
18
19
20
21
22
# File 'lib/minispec/api/class/around.rb', line 16

def around *matchers, &proc
  proc || raise(ArgumentError, 'block is missing')
  matchers.flatten!
  matchers = [:*] if matchers.empty?
  return if around?.find {|x| x[0] == matchers && x[1].source_location == proc.source_location}
  around?.push([matchers, proc])
end

#around?(filter = nil) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/minispec/api/class/around.rb', line 24

def around? filter = nil
  hooks_filter(@around ||= [], filter)
end

#around_all(&proc) ⇒ Object Also known as: around!

a block to wrap all tests evaluation



40
41
42
43
# File 'lib/minispec/api/class/around.rb', line 40

def around_all &proc
  proc || raise(ArgumentError, 'block is missing')
  @around_all = proc
end

#around_all?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/minispec/api/class/around.rb', line 46

def around_all?
  @around_all
end

#before(*matchers, &proc) ⇒ Object

run some code before any or matching tests. if called without arguments the hook will run before any test. if any arguments passed it will run only before matched tests. strings, symbols and regexps accepted as arguments. also :except option accepted.

describe Specs do

  before /shoes/, except: /red/ do
    # ...
  end

end

Examples:

callback to run before any test

describe SomeTest do

  before do
    # ...
  end
end

callback to run only before :cart test

describe Specs do

  before :cart do
    # ...
  end

  testing :cart do
    # ...
  end
end

callback to run before any test that match /cart/

describe Specs do

  before /cart/ do
    # ...
  end

  testing :cart do
    # ...
  end
end

callback to run before any test that match /cart/ except :load_cart

describe Specs do

  before /cart/, except: :load_cart do
    # ...
  end

end

callback to run before any test that match /shoes/

but ones that match /red/


61
62
63
64
65
66
67
# File 'lib/minispec/api/class/before.rb', line 61

def before *matchers, &proc
  proc || raise(ArgumentError, 'block is missing')
  matchers.flatten!
  matchers = [:*] if matchers.empty?
  return if before?.find {|x| x[0] == matchers && x[1].source_location == proc.source_location}
  before?.push([matchers, proc])
end

#before?(filter = nil) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/minispec/api/class/before.rb', line 69

def before? filter = nil
  hooks_filter(@before ||= [], filter)
end

#before_all(&proc) ⇒ Object Also known as: before!

code to run once at spec initialization, just before start running tests. this callback will run only once - at spec initialization. for callbacks that runs before any test @see #before



87
88
89
90
# File 'lib/minispec/api/class/before.rb', line 87

def before_all &proc
  proc || raise(ArgumentError, 'block is missing')
  @before_all = proc
end

#before_all?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/minispec/api/class/before.rb', line 93

def before_all?
  @before_all
end

#continue_on_failures(status) ⇒ Object

by default MiniSpec will stop evaluating a test on first failed assertion. ‘continue_on_failures true` will make MiniSpec continue evaluating regardless failures.

Examples:

set globally


MiniSpec.setup do
  continue_on_failures true
end

set per spec


describe SomeTest do
  continue_on_failures true

  # ...
end


79
80
81
# File 'lib/minispec/api/class.rb', line 79

def continue_on_failures status
  @continue_on_failures = status
end

#continue_on_failures?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/minispec/api/class.rb', line 82

def continue_on_failures?
  @continue_on_failures
end

#helper(helper, opts = {}, &proc) ⇒ Object

Note:

helpers can be overridden by name,

Note:

tested object are passed to helper via first argument. any arguments passed to helper are sent after tested object.

Note:

if a block used on left side, it will be passed as last argument and the helper is responsible to call it. please note that block will be passed as usual argument rather than a block.

Note:

if you need the current context to be passed into helper use ‘:with_context` option. when doing so, the context will come as last argument.

define custom assertion helpers.

that’s it, if some spec inherits ‘:a_duck?` helper you can use `helper(:a_duck?) { … }` to override it.

Examples:


describe SomeTest do

  helper :a_pizza? do |food|
    does(food) =~  /cheese/
    does(food) =~ /olives/
  end

  testing :foods do
    food = Cook.some_food(with: 'cheese', and: 'olives')
    is(food).a_pizza? #=> passed

    food = Cook.some_food(with: 'potatoes')
    is(food).a_pizza? #=> failed
  end
end

any other arguments are sent after tested object


describe SomeTest do

  helper :a_pizza? do |food, ingredients|
    does(food) =~ /dough/
    does(ingredients).include? 'cheese'
    does(ingredients).include? 'olives'
  end

  testing :foods do
    ingredients = ['cheese', 'olives']
    food = Cook.some_food(ingredients)
    is(food).a_pizza? ingredients
  end
end

given block passed as last argument


# block comes as a usual argument rather than a block
helper :is_invalid do |attr, block|
  e = assert(&block).raise(FormulaValidationError)
  assert(e.attr) == attr
end

test 'validates name' do
  assert(:name).is_invalid do
    formula "name with spaces" do
      url "foo"
      version "1.0"
    end
  end
end

using ‘with_context` option to get context as last argument


describe SomeTest do

  helper :a_pizza?, with_context: true do |subject, ingredients, context|
    # context is a Hash containing :left_method, left_object, :left_proc and :negation keys
  end

  testing :foods do
    is(:smth).a_pizza? ['some', 'ingredients']
    # helper's context will look like:
    # {left_method: :is, left_object: :smth, left_proc: nil, negation: nil}

    is { smth }.a_pizza? ['some', 'ingredients']
    # helper's context will look like:
    # {left_method: :is, left_object: nil, left_proc: 'the -> { smth } proc', negation: nil}
  end
end


92
93
94
95
# File 'lib/minispec/api/class/helpers.rb', line 92

def helper helper, opts = {}, &proc
  proc || raise(ArgumentError, 'block is missing')
  helpers[helper] = [proc, opts]
end

#helpersObject



97
98
99
# File 'lib/minispec/api/class/helpers.rb', line 97

def helpers
  @helpers ||= {}
end

#hooks_filter(callbacks, filter) ⇒ Object



95
96
97
98
99
100
# File 'lib/minispec/api/class.rb', line 95

def hooks_filter callbacks, filter
  return callbacks unless filter
  callbacks.map do |(matchers,proc)|
    MiniSpec::Utils.any_match?(filter, matchers) ? [filter, matchers, proc] : nil
  end.compact
end

#import_after(base) ⇒ Object Also known as: import_after_from

import ‘:after` and `:after_all` hooks from base



24
25
26
27
# File 'lib/minispec/api/class/after.rb', line 24

def import_after base
  import_instance_variable(:after_all, base)
  base.after?.each {|(m,p)| self.after(m, &p)}
end

#import_around(base) ⇒ Object Also known as: import_around_from

import ‘:around` and `:around_all` from base



33
34
35
36
# File 'lib/minispec/api/class/around.rb', line 33

def import_around base
  import_instance_variable(:around_all, base)
  base.around?.each {|(m,p)| self.around(m, &p)}
end

#import_before(base) ⇒ Object Also known as: import_before_from

import ‘:before` and `:before_all` hooks from base



78
79
80
81
# File 'lib/minispec/api/class/before.rb', line 78

def import_before base
  import_instance_variable(:before_all, base)
  base.before?.each {|(m,p)| self.before(m, &p)}
end

#import_continue_on_failures(base) ⇒ Object Also known as: import_continue_on_failures_from



86
87
88
# File 'lib/minispec/api/class.rb', line 86

def import_continue_on_failures base
  import_instance_variable(:continue_on_failures, base)
end

#import_helpers(base) ⇒ Object Also known as: import_helpers_from



107
108
109
# File 'lib/minispec/api/class/helpers.rb', line 107

def import_helpers base
  base.helpers.each_pair {|h,(p,o)| self.helper(h, o, &p)}
end

#import_instance_variable(var, base) ⇒ Object



102
103
104
105
106
# File 'lib/minispec/api/class.rb', line 102

def import_instance_variable var, base
  return unless base.instance_variable_defined?('@%s' % var)
  val = base.instance_variable_get('@%s' % var)
  val.is_a?(Proc) ? send(var, &val) : send(var, val)
end

#import_tests(base) ⇒ Object Also known as: import_tests_from



22
23
24
25
# File 'lib/minispec/api/class/tests.rb', line 22

def import_tests base
  return if base == Minispec
  base.tests.each_pair {|l,(v,p)| self.send(v, l, &p)}
end

#import_vars(base) ⇒ Object Also known as: import_vars_from



35
36
37
# File 'lib/minispec/api/class/let.rb', line 35

def import_vars base
  base.vars.each_pair {|v,p| self.let(v, &p)}
end

#included(base) ⇒ Object

Examples:

module CPUTests
  include Minispec

  # CPU related tests
end

module RAMTests
  include Minispec

  # RAM related tests
end

describe :MacBook do
  include CPUTests
  include RAMTests

  # will run CPU and RAM tests + any tests defined here
end


24
25
26
27
28
29
# File 'lib/minispec/api/class.rb', line 24

def included base
  base.send(:include, Minispec)
  MiniSpec::IMPORTABLES.each do |importable|
    base.send('import_%s' % importable, self)
  end
end

#indentObject



154
# File 'lib/minispec/api/class.rb', line 154

def indent;    0            end

#let(meth, &proc) ⇒ Object

Examples:

describe Math do
  let(:x) { 0.1 }
  let(:y) { 1.0 }

  test 'x vs y' do
    assert(x) < y
  end
end


14
15
16
17
18
# File 'lib/minispec/api/class/let.rb', line 14

def let meth, &proc
  proc || raise(ArgumentError, 'block is missing')
  vars[meth] = proc
  define_method(meth) { @__ms__vars[meth] ||= self.instance_exec(&proc) }
end

#let!(meth, &proc) ⇒ Object

same as #let except it will compute the value on every run



21
22
23
24
25
# File 'lib/minispec/api/class/let.rb', line 21

def let! meth, &proc
  proc || raise(ArgumentError, 'block is missing')
  vars[meth] = proc
  define_method(meth, &proc)
end

#reset(*importables) ⇒ Object

Examples:

module CPUTests
  include Minispec

  # CPU related tests
end

module RAMTests
  include Minispec

  # RAM related tests
end

describe :MacBook do
  include CPUTests
  include RAMTests

  # we do not need :around hook nor included variables
  reset :around, :vars

  # will run CPU and RAM tests + any tests defined here
end


54
55
56
57
58
59
60
# File 'lib/minispec/api/class.rb', line 54

def reset *importables
  importables.each do |importable|
    MiniSpec::IMPORTABLES.include?(inheritable.to_sym) || raise(ArgumentError,
      'Do not know how to reset %s. Use one of %s' % [inheritable.inspect, MiniSpec::IMPORTABLES*', '])
    self.send('reset_%s' % inheritable)
  end
end

#reset_afterObject



19
20
21
# File 'lib/minispec/api/class/after.rb', line 19

def reset_after
  @after = []
end

#reset_after_allObject



45
46
47
# File 'lib/minispec/api/class/after.rb', line 45

def reset_after_all
  remove_instance_variable(:@after_all)
end

#reset_aroundObject



28
29
30
# File 'lib/minispec/api/class/around.rb', line 28

def reset_around
  @around = []
end

#reset_around_allObject



50
51
52
# File 'lib/minispec/api/class/around.rb', line 50

def reset_around_all
  remove_instance_variable(:@around_all)
end

#reset_beforeObject



73
74
75
# File 'lib/minispec/api/class/before.rb', line 73

def reset_before
  @before = []
end

#reset_before_allObject



97
98
99
# File 'lib/minispec/api/class/before.rb', line 97

def reset_before_all
  remove_instance_variable(:@before_all)
end

#reset_continue_on_failuresObject



91
92
93
# File 'lib/minispec/api/class.rb', line 91

def reset_continue_on_failures
  remove_instance_variable(:@continue_on_failures)
end

#reset_helpersObject



112
113
114
# File 'lib/minispec/api/class/helpers.rb', line 112

def reset_helpers
  @helpers = {}
end

#reset_testsObject



28
29
30
# File 'lib/minispec/api/class/tests.rb', line 28

def reset_tests
  @tests = {}
end

#reset_varsObject



40
41
42
# File 'lib/minispec/api/class/let.rb', line 40

def reset_vars
  @vars = {}
end

#run(reporter) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/minispec/api/class.rb', line 156

def run reporter
  reporter.puts(spec_name, indent: indent)
  instance = self.allocate
  runner   = proc do
    instance.__ms__boot
    tests.each_pair do |label,(verb,proc)|
      reporter.print('%s %s ' % [verb, label], indent: indent + 2)

      failures = instance.__ms__run_test(label)

      if skipped = instance.__ms__skipped?
        reporter.mark_as_skipped(spec_name, label, skipped)
        next
      end

      if failures.empty?
        reporter.mark_as_passed(spec_name, label)
        next
      end

      reporter.mark_as_failed(spec_fullname, label, verb, proc, failures)
    end
    instance.__ms__halt
  end
  if around_all = around_all?
    instance.instance_exec(runner, &around_all)
  else
    runner.call
  end
  reporter
rescue Exception => e
  # catch exceptions raised inside :before_all/:after_all/:around_all hooks.
  # exceptions raised inside tests are caught by instance#__ms__run_test
  reporter.failed_specs << [spec_name, spec_proc, e]
  reporter
end

#spec_nameObject Also known as: spec_fullname



151
# File 'lib/minispec/api/class.rb', line 151

def spec_name; self.name    end

#spec_procObject



153
# File 'lib/minispec/api/class.rb', line 153

def spec_proc; nil          end

#subject(&proc) ⇒ Object



27
28
29
# File 'lib/minispec/api/class/let.rb', line 27

def subject &proc
  let(:subject, &proc)
end

#testsObject



18
19
20
# File 'lib/minispec/api/class/tests.rb', line 18

def tests
  @tests ||= {}
end

#varsObject



31
32
33
# File 'lib/minispec/api/class/let.rb', line 31

def vars
  @vars ||= {}
end