Top Level Namespace
Defined Under Namespace
Classes: MySQLReport, Result, ServiceAPI, SimpleFileReport, State, String
Instance Method Summary collapse
-
#die(line) ⇒ Object
——————————————————————————————————————— Utility method to show a line of output and exit.
-
#get(name) ⇒ Object
——————————————————————————————————————— Allow test scripts to get values from the global state.
-
#load_test(name, state) ⇒ Object
——————————————————————————————————————— Loads test file.
-
#method_missing(method_name, *args) ⇒ Object
——————————————————————————————————————— Finally, add missing_method hook to enable test suite DSL to call test cases by their names.
-
#out(level, line) ⇒ Object
——————————————————————————————————————— General purpose log output.
- #respond_to?(method_name, include_private = false) ⇒ Boolean
-
#restore_state(tag) ⇒ Object
——————————————————————————————————————— Restore global state to a previously saved state.
-
#run_suite(name) ⇒ Object
——————————————————————————————————————— Run a separate test suite file as part of current test suite.
-
#run_test(name, ignore = false) ⇒ Object
——————————————————————————————————————— Entry point for running one test.
-
#save_state(tag) ⇒ Object
——————————————————————————————————————— Saves the current state.
-
#set(name, value) ⇒ Object
——————————————————————————————————————— Allow test scripts to set values in the global state.
-
#show_state_diff(tag_a, tag_b = nil) ⇒ Object
——————————————————————————————————————— Print out the difference from the state named by tag_a to the state named by tag_b (these are states previously saved with save_state(). If tag_b is not provided, diff is shown to the current global state..
-
#show_usage(opts) ⇒ Object
——————————————————————————————————————— Show Usage message.
-
#unset(name) ⇒ Object
——————————————————————————————————————— Allow test scripts to remove values from the global state.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args) ⇒ Object
Finally, add missing_method hook to enable test suite DSL to call test cases by their names.
Note: In some ruby versions (at least 1.9.0) we can use File.exists? here instead of having to keep the list of test files in $TEST_FILES and checking that. However, in some other ruby versions (at least 1.9.2p290) File.exists? ends up invoking some non-existent methods which trigger a method_missing call, which leads to an infinite loop (until stack space runs out) if method_missing relies on File.exists?.
368 369 370 371 372 373 374 375 376 |
# File 'lib/restest.rb', line 368 def method_missing(method_name, *args) if ($TEST_FILES[method_name.to_s]) run_test(method_name) elsif (method_name == :ignore) && $TEST_FILES[args[0].to_s] run_test(args[0], true) else super end end |
Instance Method Details
#die(line) ⇒ Object
Utility method to show a line of output and exit. Use when a fatal misconfiguration or error is seen.
37 38 39 40 |
# File 'lib/restest.rb', line 37 def die(line) puts "[ERROR] #{line}" exit(1) end |
#get(name) ⇒ Object
Allow test scripts to get values from the global state.
54 55 56 |
# File 'lib/restest.rb', line 54 def get(name) return $GLOBAL_STATE.get(name) end |
#load_test(name, state) ⇒ Object
Loads test file
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/restest.rb', line 137 def load_test(name, state) if (!File.exists?("tests/#{name}")) die("No test file #{name}") end state.set_in_test('filename', name) file = File.new("tests/#{name}", "r") doc = false out(3, "Reading test file tests/#{name}") # line 1: service-class-name api-name line = file.gets line =~ /(\S*)\s*(\S*)/ if (!$1 || !$2) die("Test #{name} missing service and/or API") end state.set_in_test('service', $1) state.set_in_test('api', $2) # then process 'set' or 'validate' directives while ((line = file.gets) != nil) next if line =~ /^\s*$/ next if line =~ /^#/ if (line =~ /^set (\S*)\s+=\s+(.*)/) state.set_in_test($1, $2) elsif (line =~ /^validate (\S+)\s+(\S+)\s+(.*)/) state.set_validate($1, "#{$2} #{$3}") elsif (line =~ /^doc (.*)/) state.set_in_test('doc', $1) doc = true else die("Unknown directive [#{line}] in #{name}") end end if (!doc) die("Test #{name} has no documentation (doc line)") end end |
#out(level, line) ⇒ Object
General purpose log output. Log level is zero by default, increased by one for each -v argument.
45 46 47 48 49 |
# File 'lib/restest.rb', line 45 def out(level, line) if ($LOG_LEVEL >= level) puts line end end |
#respond_to?(method_name, include_private = false) ⇒ Boolean
378 379 380 381 382 383 384 |
# File 'lib/restest.rb', line 378 def respond_to?(method_name, include_private = false) if ($TEST_FILES[method_name.to_s]) return true else super end end |
#restore_state(tag) ⇒ Object
Restore global state to a previously saved state.
82 83 84 85 86 87 |
# File 'lib/restest.rb', line 82 def restore_state(tag) $GLOBAL_STATE.vars = $SAVED_STATES[tag] if ($GLOBAL_STATE.vars == nil) die("Attempted to restore to a saved stage [#{tag}] which does not exist!") end end |
#run_suite(name) ⇒ Object
Run a separate test suite file as part of current test suite. The global state is saved and then restored to isolate state changes made by the included test suite.
126 127 128 129 130 131 132 |
# File 'lib/restest.rb', line 126 def run_suite(name) out(1, "\n\n--Running included test suite #{name}") save_state("_pre_run_suite") load(name) restore_state("_pre_run_suite") out(1, "\n--Completed included test suite #{name}") end |
#run_test(name, ignore = false) ⇒ Object
Entry point for running one test. Called from test script by invoking the name of the test file (see method_missing)
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/restest.rb', line 184 def run_test(name, ignore=false) out(1, "\n\n\nRunning test #{name}") if ($LOG_LEVEL > 0) save_state('_internal_trace') end test_state = State.new($GLOBAL_STATE) load_test(name, test_state) service = test_state.get('service') api = test_state.get('api') out(1, "Service class: [#{service}] Calling API: [#{api}]") if ($INTERACTIVE) print "Interactive mode... <enter> to run this test now, <c>ontinue: " STDOUT.flush input = gets.chomp! $INTERACTIVE = false if (input == "c") end before = Time.now() allow_retries = test_state.get('allow_retries') if (allow_retries != nil) times = allow_retries.to_i sleep_sec = test_state.get('retry_sleep').to_i if (sleep_sec < 1) die("allow_retries is set but retry_sleep is not") end out(1, "Test allow retries: allow_retries: #{times} retry_sleep: #{sleep_sec}") begin out(1, "Tries left: #{times}") test_state = State.new($GLOBAL_STATE) load_test(name, test_state) testobj = Object::const_get(service).new result = testobj.send(api, test_state) times -= 1 sleep(sleep_sec) if !result.is_ok end while (times > 0 && !result.is_ok && result.allow_retry) else testobj = Object::const_get(service).new result = testobj.send(api, test_state) end if ($LOG_LEVEL > 0) show_state_diff('_internal_trace') end duration = Integer((Time.now() - before) * 1000) out(1, "Duration of test: #{duration} ms") prefix = "" if (ignore) prefix="IGNORE-" end if (result.is_ok) out(0, "[#{prefix}OK] (#{duration}ms) #{service}.#{api}: #{test_state.get('doc')}") $TESTS_OK += 1 if !ignore else out(0, "[#{prefix}FAIL] (#{duration}ms) #{service}.#{api}: #{test_state.get('doc')} #{result.}") $TESTS_FAIL += 1 if !ignore end if ($REPORT != nil) if (result.is_ok) status = "#{prefix}OK" else status = "#{prefix}FAIL" end $REPORT.log(status, duration, service, api, name, result.) end if (result.abort_suite_run) die("Test suite run has been aborted by previous test!") end end |
#save_state(tag) ⇒ Object
Saves the current state.
75 76 77 |
# File 'lib/restest.rb', line 75 def save_state(tag) $SAVED_STATES[tag] = $GLOBAL_STATE.vars.clone() end |
#set(name, value) ⇒ Object
Allow test scripts to set values in the global state.
61 62 63 |
# File 'lib/restest.rb', line 61 def set(name, value) $GLOBAL_STATE.set(name, value) end |
#show_state_diff(tag_a, tag_b = nil) ⇒ Object
Print out the difference from the state named by tag_a to the state named by tag_b (these are states previously saved with save_state(). If tag_b is not provided, diff is shown to the current global state.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/restest.rb', line 93 def show_state_diff(tag_a, tag_b = nil) a = $SAVED_STATES[tag_a] if (tag_b == nil) b = $GLOBAL_STATE.vars else b = $SAVED_STATES[tag_b] end if (a == nil || b == nil) puts "[ERROR] Unable to show diff from state #{tag_a} to state #{tag_b}" return end b.each { |k,v| if (a[k] == nil) puts " ADDED: '#{k}' => '#{v}'" elsif (a[k] != v) puts " CHANGED: '#{k}' from '#{a[k]}' to '#{v}'" end } a.each { |k,v| if (b[k] == nil) puts " REMOVED: '#{k}' was '#{a[k]}'" end } end |
#show_usage(opts) ⇒ Object
Show Usage message
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 |
# File 'lib/restest.rb', line 268 def show_usage(opts) puts opts puts <<EOF Running a test suite ==================== To run a test suite, simply run the test suite file as it is an executable ruby script. A configuration file argument must be provided. The configuration file is responsible for setting state values which are specific to a test environment, and thus not suitable to set elsewhere. These include values such as hostnames, user names, test domains, etc. (TODO: Until the framework packaging is organized, you need to run it from the test suite directory. So for the share tests for example, "cd share-tests" first. This is a temporary limitation.) The initial share test script is called "suite1" so run it by: % ./suite1 -c config.ENV (Where ENV is the share environment to run it against. There are separate config files for each share env.) EOF end |
#unset(name) ⇒ Object
Allow test scripts to remove values from the global state.
68 69 70 |
# File 'lib/restest.rb', line 68 def unset(name) $GLOBAL_STATE.unset(name) end |