Class: Protest::TestCase

Inherits:
Object
  • Object
show all
Defined in:
lib/protest/test_case.rb

Overview

A TestCase defines a suite of related tests. You can further categorize your tests by declaring nested contexts inside the class. See TestCase.context.

Defined Under Namespace

Classes: TestWrapper

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, location, &block) ⇒ TestCase

Initialize a new instance of a single test. This test can be run in isolation by calling TestCase#run.



148
149
150
151
152
# File 'lib/protest/test_case.rb', line 148

def initialize(name, location, &block)
  @test = block
  @location = location
  @name = name
end

Class Attribute Details

.description=(value) ⇒ Object

Fancy name for your test case, reports can use this to give nice, descriptive output when running your tests.



130
131
132
# File 'lib/protest/test_case.rb', line 130

def description=(value)
  @description = value
end

Class Method Details

.afterObject

Add a teardown block to be run after each test in this context. This method is aliased as after for your comfort.



136
137
138
139
140
141
# File 'lib/protest/test_case.rb', line 136

def self.teardown(&block)
  define_method :teardown do
    instance_eval(&block)
    super()
  end
end

.beforeObject

Add a setup block to be run before each test in this context. This method is aliased as before for your comfort.



135
136
137
138
139
140
# File 'lib/protest/test_case.rb', line 135

def self.setup(&block)
  define_method :setup do
    super()
    instance_eval(&block)
  end
end

.context(description, &block) ⇒ Object Also known as: describe, story

Define a new test context nested under the current one. All setup and teardown blocks defined on the current context will be inherited by the new context. This method is aliased as describe and story for your comfort.



120
121
122
123
124
125
# File 'lib/protest/test_case.rb', line 120

def self.context(description, &block)
  subclass = Class.new(self)
  subclass.class_eval(&block) if block
  subclass.description = description
  const_set(sanitize_description(description), subclass)
end

.global_setup(&block) ⇒ Object Also known as: before_all

Add a setup block that will be run once for the entire test case, before the first test is run.

Keep in mind that while setup blocks are evaluated on the context of the test, and thus you can share state between them, your tests will not be able to access instance variables set in a global_setup block.

This is usually not needed (and generally using it is a code smell, since you could make a test dependent on the state of other tests, which is a huge problem), but it comes in handy when you need to do expensive operations in your test setup/teardown and the tests won’t modify the state set on this operations. For example, creating large amount of records in a database or filesystem, when your tests will only read these records.

This method is aliased as before_all for your comfort.



77
78
79
80
81
82
83
84
# File 'lib/protest/test_case.rb', line 77

def self.global_setup(&block)
  (class << self; self; end).class_eval do
    define_method :do_global_setup do
      super()
      instance_eval(&block)
    end
  end
end

.global_teardown(&block) ⇒ Object Also known as: after_all

Add a teardown block that will be run once for the entire test case, after the last test is run.

Keep in mind that while teardown blocks are evaluated on the context of the test, and thus you can share state between the tests and the teardown blocks, you will not be able to access instance variables set in a test from your global_teardown block.

See TestCase.global_setup for a discussion on why these methods are best avoided unless you really need them and use them carefully.

This method is aliased as after_all for your comfort.



107
108
109
110
111
112
113
114
# File 'lib/protest/test_case.rb', line 107

def self.global_teardown(&block)
  (class << self; self; end).class_eval do
    define_method :do_global_teardown do
      instance_eval(&block)
      super()
    end
  end
end

.itObject

Add a test to be run in this context. This method is aliased as it, should and scenario for your comfort.



141
142
143
# File 'lib/protest/test_case.rb', line 141

def self.test(name, &block)
  tests << new(name, caller.at(0), &block)
end

.run(runner) ⇒ Object

Run all tests in this context. Takes a Runner instance in order to provide output.



30
31
32
33
34
35
36
37
38
39
# File 'lib/protest/test_case.rb', line 30

def self.run(runner)
  runner.report(TestWrapper.new(:setup, self))
  tests.each {|test| runner.report(test) }
  runner.report(TestWrapper.new(:teardown, self))
rescue Exception => e
  # If any exception bubbles up here, then it means it was during the
  # global setup/teardown blocks, so let's just skip the rest of this
  # context.
  return
end

.scenarioObject

Add a test to be run in this context. This method is aliased as it, should and scenario for your comfort.



143
144
145
# File 'lib/protest/test_case.rb', line 143

def self.test(name, &block)
  tests << new(name, caller.at(0), &block)
end

.setup(&block) ⇒ Object

Add a setup block to be run before each test in this context. This method is aliased as before for your comfort.



54
55
56
57
58
59
# File 'lib/protest/test_case.rb', line 54

def self.setup(&block)
  define_method :setup do
    super()
    instance_eval(&block)
  end
end

.shouldObject

Add a test to be run in this context. This method is aliased as it, should and scenario for your comfort.



142
143
144
# File 'lib/protest/test_case.rb', line 142

def self.test(name, &block)
  tests << new(name, caller.at(0), &block)
end

.teardown(&block) ⇒ Object

Add a teardown block to be run after each test in this context. This method is aliased as after for your comfort.



88
89
90
91
92
93
# File 'lib/protest/test_case.rb', line 88

def self.teardown(&block)
  define_method :teardown do
    instance_eval(&block)
    super()
  end
end

.test(name, &block) ⇒ Object

Add a test to be run in this context. This method is aliased as it, should and scenario for your comfort.



48
49
50
# File 'lib/protest/test_case.rb', line 48

def self.test(name, &block)
  tests << new(name, caller.at(0), &block)
end

.testsObject

Tests added to this context.



42
43
44
# File 'lib/protest/test_case.rb', line 42

def self.tests
  @tests ||= []
end

Instance Method Details

#assert(condition, message = "Expected condition to be satisfied") ⇒ Object

Ensure a condition is met. This will raise AssertionFailed if the condition isn’t met. You can override the default failure message by passing it as an argument.

Raises:



177
178
179
180
# File 'lib/protest/test_case.rb', line 177

def assert(condition, message="Expected condition to be satisfied")
  @report.on_assertion
  raise AssertionFailed, message unless condition
end

#assert_equal(expected, actual, message = nil) ⇒ Object

Passes if expected == actual. You can override the default failure message by passing it as an argument.



184
185
186
# File 'lib/protest/test_case.rb', line 184

def assert_equal(expected, actual, message=nil)
  assert expected == actual, message || "#{expected.inspect} expected but was #{actual.inspect}"
end

#assert_raise(exception_class = Exception, message = nil) ⇒ Object

Passes if the code block raises the specified exception. If no exception is specified, passes if any exception is raised, otherwise it fails. You can override the default failure message by passing it as an argument.



192
193
194
195
196
197
198
199
# File 'lib/protest/test_case.rb', line 192

def assert_raise(exception_class=Exception, message=nil)
  begin
    yield
  rescue exception_class => e
  ensure
    assert e, message || "Expected #{exception_class.name} to be raised"
  end
end

#nameObject

Name of the test



208
209
210
# File 'lib/protest/test_case.rb', line 208

def name
  @name
end

#pending(message = "Not Yet Implemented") ⇒ Object

Make the test be ignored as pending. You can override the default message that will be sent to the report by passing it as an argument.

Raises:



203
204
205
# File 'lib/protest/test_case.rb', line 203

def pending(message="Not Yet Implemented")
  raise Pending, message, [@location, *caller].uniq
end

#raise_exceptions?Boolean

Tests must not re-raise exceptions

Returns:

  • (Boolean)


213
214
215
# File 'lib/protest/test_case.rb', line 213

def raise_exceptions?
  false
end

#real?Boolean

This is a real test

Returns:

  • (Boolean)


218
219
220
# File 'lib/protest/test_case.rb', line 218

def real?
  true
end

#run(report) ⇒ Object

Run a test in isolation. Any setup and teardown blocks defined for this test case will be run as expected.

You need to provide a Runner instance to handle errors/pending tests/etc.

If the test’s block is nil, then the test will be marked as pending and nothing will be run.



161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/protest/test_case.rb', line 161

def run(report)
  @report = report
  pending if test.nil?

  begin
    setup
    instance_eval(&test)
  ensure
    teardown
    @report = nil
  end
end