#!/usr/bin/env ruby require 'reap/task' require 'facet/string/margin' # _____ _ ___ _ _____ _ # |_ _|__ __| |_ | __|_ _| |_ |_ _|_ _ __| |__ # | |/ -_|_-< _| | _|\ \ / _|_ | |/ _` (_-< / / # |_|\___/__/\__| |___/_\_\\__(_) |_|\__,_/__/_\_\ # # = Test Extraction Task # # The Reap extract test task scans every package script # looking for =begin testing ... =end sections. # With appropriat headers, it copies these sections # to files in the test dir, which then can be run # using the Reap test taks. # class Reap::TestExt < Reap::Task task_desc "Extract unit-tests from lib scripts." task_help %{ reap testext 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'. } #attr_accessor :dir, :files, :options task_attr :tst def init tst.dir ||= 'test' tst.files ||= [ 'lib/**/*.rb' ] #tst.options end def run #test_libs = tst.libs.join(':') files = FileList.new files.include(*tst.files) if files.empty? puts "No script files found." return end print "Reap is scanning and copying embedded tests..." if tst.dir.strip.empty? puts "Test directory must be specified." return end unless File.directory?(tst.dir) puts "Test directory doesn't exist: #{File.expand_path( tst.dir )}" return end files.each { |file| $stdout << '.'; $stdout.flush 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 } puts "done." 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