lib/linecook/test/file_test.rb in linecook-0.6.2 vs lib/linecook/test/file_test.rb in linecook-1.0.0

- old
+ new

@@ -2,76 +2,194 @@ module Test module FileTest module ClassMethods attr_accessor :class_dir - def self.extended(base) + attr_reader :cleanup_method_registry + + def cleanup_methods + @cleanup_methods ||= begin + cleanup_methods = {} + + ancestors.reverse.each do |ancestor| + next unless ancestor.kind_of?(ClassMethods) + ancestor.cleanup_method_registry.each_pair do |key, value| + if value.nil? + cleanup_methods.delete(key) + else + cleanup_methods[key] = value + end + end + end + + cleanup_methods + end + end + + def reset_cleanup_methods + @cleanup_methods = nil + end + + protected + + def self.initialize(base) # Infers the test directory from the calling file. # 'some_class_test.rb' => 'some_class_test' - calling_file = caller[2].gsub(/:\d+(:in .*)?$/, "") + calling_file = caller[1].gsub(/:\d+(:in .*)?$/, "") base.class_dir = calling_file.chomp(File.extname(calling_file)) + + base.reset_cleanup_methods + unless base.instance_variable_defined?(:@cleanup_method_registry) + base.instance_variable_set(:@cleanup_method_registry, {}) + end + + unless base.instance_variable_defined?(:@cleanup_paths) + base.instance_variable_set(:@cleanup_paths, ['.']) + end + + unless base.instance_variable_defined?(:@cleanup) + base.instance_variable_set(:@cleanup, true) + end end + + def inherited(base) # :nodoc: + ClassMethods.initialize(base) + super + end + + def define_method_cleanup(method_name, dirs) + reset_cleanup_methods + cleanup_method_registry[method_name.to_sym] = dirs + end + + def remove_method_cleanup(method_name) + reset_cleanup_methods + cleanup_method_registry.delete(method_name.to_sym) + end + + def undef_method_cleanup(method_name) + reset_cleanup_methods + cleanup_method_registry[method_name.to_sym] = nil + end + + def cleanup_paths(*dirs) + @cleanup_paths = dirs + end + + def cleanup(*method_names) + if method_names.empty? + @cleanup = true + else + method_names.each do |method_name| + define_method_cleanup method_name, @cleanup_paths + end + end + end + + def no_cleanup(*method_names) + if method_names.empty? + @cleanup = false + else + method_names.each do |method_name| + undef_method_cleanup method_name + end + end + end + + def method_added(sym) + if @cleanup && !cleanup_method_registry.has_key?(sym.to_sym) && sym.to_s[0, 5] == "test_" + cleanup sym + end + end end module ModuleMethods module_function def included(base) - base.extend base.kind_of?(Class) ? ClassMethods : ModuleMethods + base.extend ClassMethods + base.extend ModuleMethods unless base.kind_of?(Class) + + ClassMethods.initialize(base) super end end - + extend ModuleMethods - - attr_reader :user_dir - attr_reader :method_dir - + def setup super - @user_dir = Dir.pwd - @method_dir = File.expand_path(method_name, self.class.class_dir) - - cleanup method_dir - FileUtils.mkdir_p method_dir - Dir.chdir method_dir + cleanup end - - def teardown - Dir.chdir user_dir + def teardown + Dir.chdir(user_dir) + unless ENV["KEEP_OUTPUTS"] == "true" - cleanup class_dir + cleanup + + dir = method_dir + while dir != class_dir + dir = File.dirname(dir) + Dir.rmdir(dir) + end rescue(SystemCallError) end - + super end - - def cleanup(dir) - FileUtils.rm_r(dir) if File.exists?(dir) + + def user_dir + @user_dir ||= File.expand_path('.') end - + + def class_dir + @class_dir ||= File.expand_path(self.class.class_dir, user_dir) + end + + def method_dir + @method_dir ||= File.expand_path(method_name.to_s, class_dir) + end + + def cleanup_methods + self.class.cleanup_methods + end + + def cleanup + if cleanup_paths = cleanup_methods[method_name.to_sym] + cleanup_paths.each {|relative_path| remove(relative_path) } + end + end + def path(relative_path) - File.expand_path(relative_path, method_dir) + path = File.expand_path(relative_path, method_dir) + + unless path.index(method_dir) == 0 + raise "does not make a path relative to method_dir: #{relative_path.inspect}" + end + + path end - def prepare(relative_path) + def prepare(relative_path, content=nil, &block) target = path(relative_path) - target_dir = File.dirname(target) - FileUtils.mkdir_p(target_dir) unless File.exists?(target_dir) + if File.exists?(target) + FileUtils.rm(target) + else + target_dir = File.dirname(target) + FileUtils.mkdir_p(target_dir) unless File.exists?(target_dir) + end + FileUtils.touch(target) + File.open(target, 'w') {|io| io << content } if content + File.open(target, 'a', &block) if block + target end - def file(relative_path, &block) - target = prepare(relative_path) - block ? File.open(target, 'w', &block) : FileUtils.touch(target) - target - end - - def class_dir - self.class.class_dir + def remove(relative_path) + full_path = path(relative_path) + FileUtils.rm_r(full_path) if File.exists?(full_path) end end end end