class QED::Session

The Session class encapsulates a set of demonstrations and the procedure for looping through them and running each in turn.

Constants

CODE_TYPES
DEMO_TYPES

Default recognized demos file types.

Attributes

settings[R]

Returns instance of Settings class.

Public Class Methods

cli(*argv) click to toggle source

Command line interface for running demos.

When running ‘qed` on the command line tool, QED can use either a automatic configuration file, via the RC library, or setup configuration via an explicitly required file.

Using a master configuraiton file, add a ‘config :qed` entry. For example:

config :qed, :profile=>:simplecov do
  require 'simplecov'
  SimpleCov.start do
    coverage_dir 'log/coverage'
  end
end

To not use RC, just create a requirable file such as ‘config/qed-coverage.rb`

QED.configure do |qed|
  require 'simplecov'
  SimpleCov.start do
    coverage_dir 'log/coverage'
  end
end

Then when running qed use:

$ qed -r ./config/qed-coverage.rb
# File lib/qed/cli/qed.rb, line 47
def self.cli(*argv)
  require 'optparse'
  require 'shellwords'

  # we are loading this here instead of above so simplecov coverage works better
  # (actually, this is really not a problem anymore, but we'll leave it for now)
  require 'qed/session'

  Utils.load_config

  options = cli_parse(argv)

  settings = Settings.new(options)
  session  = Session.new(settings)
  success  = session.run

  exit -1 unless success
end
cli_parse(argv) click to toggle source

Build an instance of OptionParser.

# File lib/qed/cli/qed.rb, line 69
def self.cli_parse(argv)
  options = {}

  parser = OptionParser.new do |opt|
    opt.banner = "Usage: qed [options] <files...>"

    opt.separator("Report Formats (pick one):")

    #opt.on('--dotprogress', '-d', "use dot-progress reporter [default]") do
    #  options[:format] = :dotprogress
    #end
    opt.on('--verbatim', '-v', "shortcut for verbatim reporter") do
      options[:format] = :verbatim
    end
    opt.on('--tapy', '-y', "shortcut for TAP-Y reporter") do
      options[:format] = :tapy
    end
    #opt.on('--bullet', '-b', "use bullet-point reporter") do
    #  options[:format] = :bullet
    #end
    #opt.on('--html', '-h', "use underlying HTML reporter") do
    #  options[:format] = :html
    #end
    #opt.on('--script', "psuedo-reporter") do
    #  options[:format] = :script  # psuedo-reporter
    #end
    opt.on('--format', '-f FORMAT', "use custom reporter") do |format|
      options[:format] = format.to_sym
    end

    opt.separator("Control Options:")

    opt.on('-p', '--profile NAME', "load runtime profile") do |name|
      options[:profile] = name
    end
    opt.on('--comment', '-c', "run comment code") do
      options[:mode] = :comment
    end
    opt.on('--loadpath', "-I PATH", "add paths to $LOAD_PATH") do |paths|
      options[:loadpath] = paths.split(/[:;]/).map{|d| File.expand_path(d)}
    end
    opt.on('--require', "-r LIB", "require feature (immediately)") do |paths|
      requires = paths.split(/[:;]/)
      requires.each do |file|
        require file
      end
    end
    opt.on('--rooted', '-R', "run from project root instead of temporary directory") do
      options[:rooted] = true
    end
    opt.on('--trace', '-t [COUNT]', "number of backtraces for exceptions (0 for all)") do |cnt|
      #options[:trace] = true
      ENV['trace'] = cnt
    end
    opt.on('--warn', "run with warnings turned on") do
      $VERBOSE = true # wish this were called $WARN!
    end
    opt.on('--debug', "exit immediately upon raised exception") do
      $DEBUG = true
    end

    opt.separator("Optional Commands:")

    opt.on_tail('--version', "display version") do
      puts "QED #{QED::VERSION}"
      exit
    end
    opt.on_tail('--copyright', "display copyrights") do
      puts "Copyright (c) 2008 Thomas Sawyer, Apache 2.0 License"
      exit
    end
    opt.on_tail('--help', '-h', "display this help message") do
      puts opt

      unless settings.profiles.empty?
        puts "Available Profiles:"
        #require 'confection'
        QED.profiles.each do |name|
          next if name.strip == ''
          puts "    -p #{name}"
        end
      end

      exit -1
    end
  end

  parser.parse!(argv)

  options[:files] = argv unless argv.empty?

  return options
end
new(settings={}) click to toggle source

New Session

# File lib/qed/session.rb, line 29
def initialize(settings={})
  require_reporters

  case settings
  when Settings
    @settings = settings
  else
    @settings = Settings.new(settings)
  end
end

Public Instance Methods

clear_directory() click to toggle source

Clear temporary testing directory.

# File lib/qed/session.rb, line 162
def clear_directory
  settings.clear_directory
end
demo_files() click to toggle source

Returns a list of demo files. The files returned depends on the files attribute and if none given, then the current run mode.

# File lib/qed/session.rb, line 188
def demo_files
  @demo_files ||= (
    if mode == :comment
      demo_files_in_comment_mode
    else
      demo_files_in_normal_mode
    end
  )
end
demo_files_in_comment_mode() click to toggle source

Collect default files to process in code comment mode.

TODO: Sure removing applique files is the best approach here?

# File lib/qed/session.rb, line 206
def demo_files_in_comment_mode
  files = demos_gather(CODE_TYPES)
  files = files.reject{ |f| f.index('applique/') }  # don't include applique files ???
  files
end
demo_files_in_normal_mode() click to toggle source

Collect default files to process in normal demo mode.

# File lib/qed/session.rb, line 199
def demo_files_in_normal_mode
  demos_gather #(DEMO_TYPES)
end
demos() click to toggle source

Returns an Array of Demo instances.

# File lib/qed/session.rb, line 115
def demos
  @demos ||= demo_files.map{ |file| Demo.new(file, :mode=>mode, :at=>directory) }
end
demos_gather(extensions=DEMO_TYPES) click to toggle source

Gather list of demo files. Uses omit to remove certain files based on the name of their parent directory.

# File lib/qed/session.rb, line 214
def demos_gather(extensions=DEMO_TYPES)
  files = self.files
  #files << default_location if files.empty?
  files = files.map{|pattern| Dir[pattern]}.flatten.uniq
  files = files.map do |file|
    if File.directory?(file)
      Dir[File.join(file,'**','*.{' + extensions.join(',') + '}')]
    else
      file
    end
  end
  files = files.flatten.uniq
  #files = files.reject{ |f| f =~ Regexp.new("/\/(#{omit.join('|')})\//") }
  files = files.reject{ |f| omit.any?{ |o| f.index("/#{o}/") } }
  files.map{|f| File.expand_path(f) }.uniq.sort
end
directory() click to toggle source
# File lib/qed/session.rb, line 86
def directory
  settings.tmpdir
end
files() click to toggle source

Demonstration files (or globs).

# File lib/qed/session.rb, line 41
def files
  settings.files
end
format() click to toggle source

Output format.

# File lib/qed/session.rb, line 51
def format
  settings.format
end
loadpath() click to toggle source

Paths to be added to $LOAD_PATH.

# File lib/qed/session.rb, line 66
def loadpath
  settings.loadpath
end
mode() click to toggle source

Parse mode.

# File lib/qed/session.rb, line 61
def mode
  settings.mode
end
observers() click to toggle source

List of observers to pass to the evaluator. Only includes the reporter instance, by default.

# File lib/qed/session.rb, line 122
def observers
  [reporter]
end
omit() click to toggle source

File patterns to omit.

# File lib/qed/session.rb, line 46
def omit
  settings.omit
end
prepare_loadpath() click to toggle source

Add to load path (from -I option).

# File lib/qed/session.rb, line 172
def prepare_loadpath
  loadpath.each{ |dir| $LOAD_PATH.unshift(File.expand_path(dir)) }
end
profile() click to toggle source

Selected profile.

# File lib/qed/session.rb, line 81
def profile
  settings.profile
end
reporter() click to toggle source

Instance of selected Reporter subclass.

# File lib/qed/session.rb, line 105
def reporter
  @reporter ||= (
    name = Reporter.constants.find{ |c| /#{format}/ =~ c.to_s.downcase }
    Reporter.const_get(name).new(:trace => trace?)
  )
end
require_libraries() click to toggle source

Require libraries (from -r option).

# File lib/qed/session.rb, line 177
def require_libraries
  requires.each{ |file| require(file) }
end
require_reporters() click to toggle source

Require all reporters.

# File lib/qed/session.rb, line 98
def require_reporters
  Dir[File.dirname(__FILE__) + '/reporter/*'].each do |file|
    require file
  end
end
requires() click to toggle source

Libraries to be required.

# File lib/qed/session.rb, line 71
def requires
  settings.requires
end
reset_assertion_counts() click to toggle source

Set $ASSERTION_COUNTS to zero point.

# File lib/qed/session.rb, line 167
def reset_assertion_counts
  $ASSERTION_COUNTS = Hash.new{ |h,k| h[k] = 0 }
end
rooted() click to toggle source

Operate from project root?

# File lib/qed/session.rb, line 76
def rooted
  settings.rooted
end
run() click to toggle source

Run session.

# File lib/qed/session.rb, line 129
def run
  abort "No documents." if demo_files.empty?

  clear_directory

  reset_assertion_counts

  #require_profile  # <-- finally runs the profile

  prepare_loadpath
  require_libraries

  Dir.chdir(directory) do
    # pre-parse demos
    demos.each{ |demo| demo.steps }

    # Let's do it.
    observers.each{ |o| o.before_session(self) }
    begin
      demos.each do |demo|
        Evaluator.run(demo, :observers=>observers, :settings=>settings) #demo.run(*observers)
        #pid = fork { demo.run(*observers) }
        #Process.detach(pid)
      end
    ensure
      observers.each{ |o| o.after_session(self) }
    end
  end

  reporter.success?
end
total_step_count() click to toggle source

Get the total test count. This method tallies up the number of assertive steps.

# File lib/qed/session.rb, line 241
def total_step_count
  count = 0
  demos.each do |demo|
    demo.steps.each do |step|
      count += 1 if step.assertive?
    end
  end
  count
end
trace?() click to toggle source

Trace execution?

# File lib/qed/session.rb, line 56
def trace?
  settings.trace
end