Class: Ki::Tester
Overview
Modifies run time environment for tests and automatically restores original state
-
note: cleanup is triggered by calling the #after method
Defined Under Namespace
Classes: DummyIO
Instance Attribute Summary collapse
-
#cleaners ⇒ Object
readonly
List of Procs which should be executed.
-
#test_name ⇒ Object
readonly
Name of the test round that uses this tester.
Class Method Summary collapse
-
.copy_visible_files(src, dest) ⇒ String
Copies contents of src to dest * excludes files and directories beginning with a ‘.’.
- .final_tester_check ⇒ Object
-
.verify_files(source_root, *args) ⇒ Boolean
Verifies that files exist in target directory.
-
.write_files(dest_root, files = {}) ⇒ String
Writes defined files to target directory * note: dest_root and target directories are automatically created.
Instance Method Summary collapse
-
#after ⇒ void
Executes all pending cleanup operations * cleaners lists all procs that will be executed * all exceptions from procs are caught and raised together * Tester helper methods schedule cleanup operations to cleaners if needed.
-
#catch_stdio(&block) ⇒ Object
Redirects $stdin, $stdout, $stderr streams to the Tester instance * if called without block, streams are restored when after is called.
-
#chdir(dest, &block) ⇒ Object
Changes working directory to target.
- #clear? ⇒ Boolean
- #env(key, value) ⇒ Object
-
#initialize(test_name = nil) ⇒ Tester
constructor
A new instance of Tester.
- #restore_extensions ⇒ Object
-
#tmpdir(src = nil, &block) ⇒ String, Object
Creates a temporary directory * if called without a block removes directory when after is called.
Constructor Details
#initialize(test_name = nil) ⇒ Tester
Returns a new instance of Tester.
56 57 58 59 60 |
# File 'lib/util/test.rb', line 56 def initialize(test_name = nil) @test_name = test_name @cleaners = [] $testers << self end |
Instance Attribute Details
#cleaners ⇒ Object (readonly)
List of Procs which should be executed
39 40 41 |
# File 'lib/util/test.rb', line 39 def cleaners @cleaners end |
#test_name ⇒ Object (readonly)
Name of the test round that uses this tester
42 43 44 |
# File 'lib/util/test.rb', line 42 def test_name @test_name end |
Class Method Details
.copy_visible_files(src, dest) ⇒ String
Copies contents of src to dest
-
excludes files and directories beginning with a ‘.’
220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/util/test.rb', line 220 def self.copy_visible_files(src, dest) Dir.glob(File.join(src, "**/*")).each do |file_src| file_path = file_src[src.size+1..-1] if File.file?(file_src) FileUtils.cp(file_src, File.join(dest, file_path)) elsif File.directory?(file_src) FileUtils.mkdir(File.join(dest, file_path)) end end dest end |
.final_tester_check ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/util/test.rb', line 202 def self.final_tester_check catcher = ExceptionCatcher.new $testers.each do |tester| if !tester.clear? puts "Tester#{tester.test_name ? " '#{tester.test_name}'" : ""} has not been cleared! Please add the missing .after() command. Clearing it automatically." catcher.catch do tester.after end end end catcher.check end |
.verify_files(source_root, *args) ⇒ Boolean
Verifies that files exist in target directory. If files or directories are missing, contents are wrong, type is wrong or there are unwanted files raises an exception.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/util/test.rb', line 260 def self.verify_files(source_root, *args) check_for_extra_files, files = args if files.nil? && check_for_extra_files.kind_of?(Hash) files = check_for_extra_files check_for_extra_files = nil end files.each_pair do |file, contents| file_path = File.join(source_root, file) is_dir = file.end_with?("/") || contents.nil? if !File.exists?(file_path) raise "#{ is_dir ? "Directory" : "File"} '#{file_path}' is missing!" end if is_dir != File.directory?(file_path) raise "Existing #{ is_dir ? "file" : "directory"} '#{file_path}' should be a #{ is_dir ? "directory" : "file"}!" end if !is_dir file_contents = IO.read(file_path) [contents].flatten.each do |o| if o.kind_of?(Regexp) if !file_contents.match(o) raise "File '#{file_path}' does not match regexp #{o.inspect}, file contents: '#{file_contents}'" end elsif o.kind_of?(String) if file_contents != o raise "File '#{file_path}' is broken! Expected '#{o}' but was '#{file_contents}'" end elsif o.kind_of?(Proc) if !o.call(file_contents) raise "File '#{file_path}' did not pass test!" end else raise "Unsupported checker! File '#{file_path}' object: #{o.inspect}" end end end end if check_for_extra_files files_and_dirs = {} files.each_pair do |k, v| file_arr=k.split("/") c = file_arr.size while c > 0 c -= 1 files_and_dirs[File.join(source_root, file_arr)]=true file_arr.delete_at(-1) end end Dir.glob(File.join(source_root, "**/*")).each do |file| if !files_and_dirs[file] raise "#{ File.directory?(file) ? "Directory" : "File"} '#{file}' exists, but it should not exist!" end end end end |
.write_files(dest_root, files = {}) ⇒ String
Writes defined files to target directory
-
note: dest_root and target directories are automatically created
239 240 241 242 243 244 245 246 247 248 |
# File 'lib/util/test.rb', line 239 def self.write_files(dest_root, files={}) files.each_pair { |file_path, content| dir = File.dirname(file_path) if dir != "." FileUtils.mkdir_p(File.join(dest_root, dir)) end File.safe_write(File.join(dest_root, file_path), content) } dest_root end |
Instance Method Details
#after ⇒ void
This method returns an undefined value.
Executes all pending cleanup operations
-
cleaners lists all procs that will be executed
-
all exceptions from procs are caught and raised together
-
Tester helper methods schedule cleanup operations to cleaners if needed
187 188 189 190 191 192 193 194 195 196 |
# File 'lib/util/test.rb', line 187 def after catcher = ExceptionCatcher.new @cleaners.each do |after_block| catcher.catch do after_block.call end end @cleaners.clear catcher.check end |
#catch_stdio(&block) ⇒ Object
Redirects $stdin, $stdout, $stderr streams to the Tester instance
-
if called without block, streams are restored when after is called
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/util/test.rb', line 113 def catch_stdio(&block) original_streams = [$stdin, $stdout, $stderr] cleanup = -> { $stdin, $stdout, $stderr = original_streams } stdin.clear stdout.clear stderr.clear $stdin = stdin $stdout = stdout $stderr = stderr if block begin block.call ensure cleanup.call end else @cleaners << cleanup end self end |
#chdir(dest, &block) ⇒ Object
Changes working directory to target
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/util/test.rb', line 140 def chdir(dest, &block) if block Dir.chdir(dest, &block) else if !defined? @original_dir @original_dir = Dir.pwd @cleaners << -> { Dir.chdir(@original_dir); @original_dir=nil } end Dir.chdir(dest) end end |
#clear? ⇒ Boolean
198 199 200 |
# File 'lib/util/test.rb', line 198 def clear? @cleaners.empty? end |
#env(key, value) ⇒ Object
152 153 154 155 156 157 |
# File 'lib/util/test.rb', line 152 def env(key, value) current = ENV[key] @cleaners << -> {ENV[key]=current} ENV[key]=value self end |
#restore_extensions ⇒ Object
326 327 328 329 330 331 332 |
# File 'lib/util/test.rb', line 326 def restore_extensions original_commands = KiCommand::KiExtensions.dup cleaners << lambda do KiCommand::KiExtensions.clear KiCommand::KiExtensions.register(original_commands) end end |
#tmpdir(src = nil, &block) ⇒ String, Object
Creates a temporary directory
-
if called without a block removes directory when after is called
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/util/test.rb', line 74 def tmpdir(src=nil, &block) dest = Dir.mktmpdir cleanup = -> { FileUtils.remove_entry_secure(dest) } if src catcher = ExceptionCatcher.new catcher.catch do Tester.copy_visible_files(src, dest) end # if there is a problem copying files, cleanup and raise original exception if catcher.exceptions? catcher.catch do cleanup.call end catcher.check end end if block begin block.call(dest) ensure cleanup.call end else @cleaners << cleanup dest end end |