#!/usr/bin/env ruby require 'reap/task' require 'facet/string/margin' require 'facet/progressbar' # _____ _ ___ _ _____ _ # |_ _|__ __| |_ | __|_ _| |_ |_ _|_ _ __| |__ # | |/ -_|_-< _| | _|\ \ / _|_ | |/ _` (_-< / / # |_|\___/__/\__| |___/_\_\\__(_) |_|\__,_/__/_\_\ # # = Test Extraction Task # # The Reap extract test task scans every package script # looking for =begin test... =end sections. # With appropriat headers, it copies these sections # to files in the test dir, which then can be run # using the Reap test task. # class Reap::ExTest < Reap::Task task_desc "Extract embedded unit tests from scripts." task_help %{ reap extest Extracts embedded tests from program files and places them in the test directory. The exact layout of files is reflected in the test directory. You can then use Reap's test task to run the tests. dir Specify the test directory. Default is 'test'. files Specify files to extract. Default is 'lib/**/*.rb'. } alias_method :tst, :task def run # setup tst.dir ||= 'test' tst.files ||= [ 'lib/**/*.rb' ] tst.files = [ tst.files ].flatten #tst.options ? # text extract #test_libs = tst.libs.join(':') files = FileList.new files.include(*tst.files) if files.empty? tell "No script files found." return end tell "Reap is scanning and copying embedded tests..." if tst.dir.strip.empty? tell "Test directory must be specified." return end unless File.directory?(tst.dir) tell "Test directory doesn't exist: #{File.expand_path( tst.dir )}" return end pbar = Console::ProgressBar.new( 'Extracting', files.size ) files.each { |file| pbar.inc testing = extract( file ) unless testing.strip.empty? complete_test = create( testing, file ) libpath = File.dirname( file ) testfile = "test_" + File.basename( file ) fp = File.join(tst.dir,libpath,testfile) unless File.directory?( File.dirname( fp ) ) FileUtils.mkdir_p( File.dirname(fp) ) end File.open( fp, "w" ) { |fw| fw << complete_test } end } pbar.finish end private def extract( file ) return nil if ! File.file?( file ) tests = ""; inside = false fstr = File.read( file ) fstr.split(/\n/).each do |l| if l =~ /^=begin[ ]*test/i tests << "\n" inside = true next elsif inside and l =~ /^=[ ]*end/ inside = false next end if inside tests << l << "\n" end end tests end def create( testing, file ) fp = file.split(/[\/]/) if fp[0] == 'lib' reqf = "require '#{fp[1..-1].join('/')}'" else reqf = '' end teststr = <<-HERE.margin `# _____ _ `# |_ _|__ ___| |_ `# | |/ _ \\/ __| __| `# | | __/\\__ \\ |_ `# |_|\\___||___/\\__| `# `# for #{file} `# `# Extracted #{Time.now} `# Unit Tools Reap Test Extractor `# ` `#{reqf} ` HERE teststr << testing << "\n" teststr end end