Module: BareTest

Defined in:
lib/baretest.rb,
lib/baretest/run.rb,
lib/baretest/uid.rb,
lib/baretest/setup.rb,
lib/baretest/suite.rb,
lib/baretest/layout.rb,
lib/baretest/status.rb,
lib/baretest/run/cli.rb,
lib/baretest/run/tap.rb,
lib/baretest/run/xml.rb,
lib/baretest/version.rb,
lib/baretest/irb_mode.rb,
lib/baretest/run/none.rb,
lib/baretest/run/spec.rb,
lib/baretest/assertion.rb,
lib/baretest/formatter.rb,
lib/baretest/commandline.rb,
lib/baretest/persistence.rb,
lib/baretest/run/minimal.rb,
lib/baretest/assertion/skip.rb,
lib/baretest/invalidselectors.rb,
lib/baretest/assertion/context.rb,
lib/baretest/assertion/failure.rb,
lib/baretest/assertion/support.rb

Defined Under Namespace

Modules: CommandLine, Formatter, IRBMode, VERSION Classes: Assertion, InvalidSelectors, Layout, Persistence, Run, Setup, Status, Suite, UID

Constant Summary collapse

MoreImportantStatus =

A lookup table to test which of two states is more important (MoreImportantStatus[] # => a or b)

{}
StatusOrder =

All states in the order of relevance, more relevant states first

:error,
:failure,
:pending,
:manually_skipped,
:dependency_missing,
:library_missing,
:component_missing,
:ignored,
:success
DefaultInitialPositiveGlob =

The standard glob used by baretest to load test files

'test/{suite,unit,isolation,integration,system}/**/*.rb'
ValidStateSelectors =

Selectors that are valid to be passed into process_selectors

[:new, :success, :failure, :error, :skipped, :pending]

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.componentsObject (readonly)

A hash of components - available via BareTest::use(name) and Suite#suite :use => name



68
69
70
# File 'lib/baretest.rb', line 68

def components
  @components
end

.extenderObject (readonly)

For mock integration and others, append modules that should extend the Test::Run instance.



74
75
76
# File 'lib/baretest.rb', line 74

def extender
  @extender
end

.formatObject (readonly)

A hash of formatters (require-string => module) to be used with Test::Run.



71
72
73
# File 'lib/baretest.rb', line 71

def format
  @format
end

.required_fileObject (readonly)

The full path to this file Needed to test baretest itself using baretest



82
83
84
# File 'lib/baretest.rb', line 82

def required_file
  @required_file
end

.toplevel_suiteObject (readonly)

The toplevel suite. That’s the one run_if_mainfile and define add suites and assertions to.



78
79
80
# File 'lib/baretest.rb', line 78

def toplevel_suite
  @toplevel_suite
end

Class Method Details

.clean_touches(assertion) ⇒ Object

Used by BareTest::Assertion::Support



35
36
37
# File 'lib/baretest/assertion/support.rb', line 35

def self.clean_touches(assertion) # :nodoc:
  @touch.delete(assertion)
end

.component(name) ⇒ Object



213
214
215
216
217
218
219
220
221
222
# File 'lib/baretest.rb', line 213

def self.component(name)
  component = @components[name]
  begin
    require "baretest/use/#{name}"
  rescue LoadError
  else
    component = @components[name]
  end
  component
end

.external(*path) ⇒ Object

Returns the absolute path to the external file Example

suite "#mkdir" do
  setup do
    @base = BareTest.external('suite_mkdir') # => "/.../PROJECT/test/external/suite_mkdir"


269
270
271
# File 'lib/baretest.rb', line 269

def self.external(*path)
  File.join(test_directory, 'external', *path)
end

.initObject

Initializes BareTest, is automatically called

Needed for bootstrapped selftest



202
203
204
205
206
207
208
209
210
# File 'lib/baretest.rb', line 202

def self.init # :nodoc:
  @components     = {}
  @format         = {}
  @extender       = []
  @toplevel_suite = BareTest::Suite.new
  @required_file  = ["", *$LOAD_PATH].map { |path|
    File.expand_path(File.join(path, __FILE__))
  }.find { |full| File.exist?(full) }
end

.load_standard_test_files(opts = {}) ⇒ Object

Loads all files in a test directory in order to load the suites and assertions. Used by the ‘baretest’ executable and the standard rake task.

Options:

:verbose

Will print information about the load process (default: false)

:setup_path

The path to the setup file, the first loaded file (default: ‘test/setup.rb’)

:chdir

The directory this routine chdirs before loading, will jump back to the original directory after loading (default: ‘.’)



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/baretest.rb', line 108

def self.load_standard_test_files(opts={})
  verbose    = opts.delete(:verbose)
  setup_path = opts.delete(:setup_path) || 'test/setup.rb'
  lib_path   = opts.delete(:lib_path) || 'test/lib'
  chdir      = opts.delete(:chdir) || '.'
  files      = opts.delete(:files)
  files      = [DefaultInitialPositiveGlob] if (files.nil? || files.empty?)
  Dir.chdir(chdir) do
    $LOAD_PATH.unshift(File.expand_path(lib_path)) if File.exist?(lib_path)
    load(setup_path) if File.exist?(setup_path)
    files.each do |glob|
      glob = "#{glob}/**/*.rb" if File.directory?(glob)
      Dir.glob(glob) { |path|
        helper_path = path.sub(%r{((?:^|/)test)/(suite|unit|integration|system)/}, '\1/helper/\2/')
        exists = (helper_path != path && File.exist?(helper_path))
        if verbose then
          if helper_path == path then
            puts "Could not resolve helper path for path #{path}"
          elsif exists
            puts "Loading helper file #{helper_path}"
          else
            puts "No helper file #{helper_path} to load"
          end
        end
        load(helper_path) if exists
        puts "Loading test file #{path}" if verbose
        load(path)
      }
    end
  end
end

.most_important_status(states) ⇒ Object

Determine which of the named states is the most important one (see StatusOrder)



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

def self.most_important_status(states)
  (StatusOrder & states).first # requires Array#& to be stable (keep order of first operand)
end

.new_component(name, &block) ⇒ Object

Create a new component for Suite’s :use option (see BareTest::Suite::new)

Raises:

  • (ArgumentError)


238
239
240
241
242
# File 'lib/baretest.rb', line 238

def self.new_component(name, &block)
  name = name.to_sym
  raise ArgumentError, "Component named #{name.inspect} already exists" if @components.has_key?(name)
  @components[name] = block
end

.process_selectors(selectors, base_directory = ".", default_initial_positive_glob = nil) ⇒ Object

Convert an array of selectors into a hash with those selectors preprocessed as far as possible. Example:

BareTest.process_selectors %w[-some/**/glob/*.rb %failure :tag1 -:tag2]
# => {
#      :files          => ...an array with paths...,
#      :include_tags   => [:tag1],
#      :exclude_tags   => [:tag2],
#      :include_states => [:failure]
#      :exclude_states => nil,
#    }

Raises:



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
192
193
194
195
196
197
# File 'lib/baretest.rb', line 157

def self.process_selectors(selectors, base_directory=".", default_initial_positive_glob=nil)
  files           = []
  include_tags    = []
  exclude_tags    = []
  include_states  = []
  exclude_states  = []

  default_initial_positive_glob ||= DefaultInitialPositiveGlob
  Dir.chdir(base_directory) do
    selectors.each do |selector|
      case selector
        when /\A-%(.*)/   then exclude_states << $1.to_sym
        when /\A-:(.*)/   then exclude_tags << $1.to_sym
        when /\A\+?%(.*)/ then include_states << $1.to_sym
        when /\A\+?:(.*)/ then include_tags << $1.to_sym
        when /\A-(.*)/    then
          files  = Dir[default_initial_positive_glob] if files.empty? && default_initial_positive_glob
          glob   = File.directory?($1) ? "#{$1}/**/*.rb" : $1
          files -= Dir[glob]
        when /\A\+?(.*)/  then
          glob   = File.directory?(selector) ? "#{selector}/**/*.rb" : selector
          files |= Dir[glob]
        else
          raise "Should never reach else - selector: #{selector.inspect}"
      end
    end
    files  = Dir[default_initial_positive_glob] if files.empty? && default_initial_positive_glob
    files.map! do |path| File.expand_path(path) end
  end

  invalid_states = (include_states|exclude_states)-ValidStateSelectors
  raise InvalidSelectors.new(invalid_states) unless invalid_states.empty?

  return {
    :files          => files,
    :include_tags   => include_tags,
    :exclude_tags   => exclude_tags,
    :include_states => include_states.empty? ? nil : include_states,
    :exclude_states => exclude_states.empty? ? nil : exclude_states
  }
end

.require(*paths) ⇒ Object

Tries to require a file, if it fails, it will require rubygems and retries



250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/baretest.rb', line 250

def self.require(*paths)
  paths.each do |path|
    begin
      Kernel.require path
    rescue LoadError
      begin
        Kernel.require 'rubygems'
      rescue LoadError
      end
      Kernel.instance_method(:require).bind(self).call path # ugly, but at least until rubygems 1.3.5, Kernel.require isn't overriden
    end
  end
end

.require_baretest(version) ⇒ Object

Enure that the suite is run wiht a minimal version of baretest



86
87
88
89
90
# File 'lib/baretest.rb', line 86

def self.require_baretest(version)
  if (version.split(".").map { |s| s.to_i } <=> BareTest::VERSION.to_a) > 0 then
    abort "Requires baretest version #{version}, you have #{BareTest::VERSION}"
  end
end

.require_ruby(version) ⇒ Object

Ensure that the suite is run with a minimal version of ruby



93
94
95
96
97
# File 'lib/baretest.rb', line 93

def self.require_ruby(version)
  if (version.split(".").map { |s| s.to_i } <=> RUBY_VERSION.split(".").map { |s| s.to_i }) > 0 then
    abort "Requires ruby version #{version}, you have #{RUBY_VERSION}"
  end
end

.suite(description = nil, opts = {}, &block) ⇒ Object

If no description was given, it adds the contained assertions and suites to the toplevel suite, if a description was given, a suite with the given description is created, added to the toplevel suite, and all the contained assertions and suites are added to the created suite.



227
228
229
230
231
232
233
234
235
# File 'lib/baretest.rb', line 227

def self.suite(description=nil, opts={}, &block)
  if description then
    @toplevel_suite.suite(description, opts, &block)
  elsif opts && !opts.empty?
    raise ArgumentError, "Suites with options must have names"
  else
    @toplevel_suite.instance_eval(&block)
  end
end

.test_directoryObject

Returns the absolute path to the test directory



274
275
276
# File 'lib/baretest.rb', line 274

def self.test_directory
  File.expand_path(path, 'test')
end

.touch(assertion, thing = nil) ⇒ Object

We don’t want to litter in Assertion Touches are associated with Used by BareTest::Assertion::Support#touch



23
24
25
26
# File 'lib/baretest/assertion/support.rb', line 23

def self.touch(assertion, thing=nil) # :nodoc:
  @touch[assertion] ||= Hash.new(0)
  @touch[assertion][thing] += 1
end

.touched(assertion, thing = nil) ⇒ Object

Used by BareTest::Assertion::Support#touched



29
30
31
32
# File 'lib/baretest/assertion/support.rb', line 29

def self.touched(assertion, thing=nil) # :nodoc:
  @touch[assertion] ||= Hash.new(0)
  @touch[assertion][thing]
end

.use(component) ⇒ Object

Shortcut for toplevel_suite.use. Preferably use the :use option instead.



245
246
247
# File 'lib/baretest.rb', line 245

def self.use(component)
  @toplevel_suite.use(component)
end