autopilot 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/aup +11 -0
- data/examples/run_mac.rb +19 -0
- data/lib/auto_pilot.rb +5 -0
- data/lib/auto_pilot/CLI.rb +93 -0
- data/lib/auto_pilot/browser.rb +63 -0
- data/lib/auto_pilot/files.rb +63 -0
- data/lib/auto_pilot/poller.rb +41 -0
- data/lib/auto_pilot/selenium_runner.rb +116 -0
- data/lib/auto_pilot/servlet.rb +68 -0
- data/test/files_test.rb +58 -0
- data/test/mac_firefox_test.rb +30 -0
- data/test/poller_test.rb +40 -0
- data/test/selenium_runner_test.rb +40 -0
- data/test/selenium_servlet_test.rb +185 -0
- metadata +59 -0
data/bin/aup
ADDED
data/examples/run_mac.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#$:.unshift File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'auto_pilot'
|
7
|
+
#include AutoPilot
|
8
|
+
|
9
|
+
runner = AutoPilot::SeleniumRunner.new(AutoPilot::FIREFOX)
|
10
|
+
runner.timeout=1200
|
11
|
+
runner.clean = true
|
12
|
+
runner.dir = "results"
|
13
|
+
|
14
|
+
#runner.suites << "http://localhost:8083/catalog/selenium/TestRunner.html?test=tests/mock/QuickSuite1.html"
|
15
|
+
#runner.suites << "http://localhost:8083/catalog/selenium/TestRunner.html?test=tests/mock/QuickSuite2.html"
|
16
|
+
runner.suites << "http://localhost:3000/javascripts/selenium-core-0.7.0/core/TestRunner.html?test=../tests/laptops/LaptopsSuite.html"
|
17
|
+
runner.run
|
18
|
+
|
19
|
+
|
data/lib/auto_pilot.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'auto_pilot'
|
3
|
+
|
4
|
+
module AutoPilot
|
5
|
+
# The CLI class encapsulates the behavior of autopilot when it is invoked
|
6
|
+
# as a command-line utility. This allows other programs to embed AP and
|
7
|
+
# preserve it's command-line semantics.
|
8
|
+
class CLI
|
9
|
+
# Invoke autopilot using the ARGV array as the option parameters. This
|
10
|
+
# is what the command-line autopilot (aup) utility does.
|
11
|
+
def self.execute!
|
12
|
+
new.execute!
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute!
|
16
|
+
runner = AutoPilot::SeleniumRunner.new(AutoPilot::FIREFOX)
|
17
|
+
runner.timeout = options[:timeout] if options[:timeout]
|
18
|
+
runner.interval = options[:interval] if options[:interval]
|
19
|
+
runner.port = options[:port] if options[:port]
|
20
|
+
runner.dir = options[:dir] if options[:dir]
|
21
|
+
runner.clean = true if options[:clean]
|
22
|
+
|
23
|
+
for suite in options[:suites]
|
24
|
+
runner.suites << suite
|
25
|
+
end
|
26
|
+
runner.run
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :args, :options
|
30
|
+
|
31
|
+
def initialize(args = ARGV)
|
32
|
+
@args = args
|
33
|
+
@options = { :suites => [] }
|
34
|
+
|
35
|
+
OptionParser.new do |opts|
|
36
|
+
opts.banner = "Usage: #{$0} [options] [args]"
|
37
|
+
|
38
|
+
opts.separator ""
|
39
|
+
opts.separator "AutoPilot Options -----------------------"
|
40
|
+
opts.separator ""
|
41
|
+
|
42
|
+
opts.on("-s", "--suite SUITE",
|
43
|
+
"A test suite to execute. Multiple suites may",
|
44
|
+
"be specified, and are loaded in the given order."
|
45
|
+
) { |value| @options[:suites] << value }
|
46
|
+
|
47
|
+
opts.on("-t", "--timeout [TIMEOUT]",
|
48
|
+
"The timeout value in seconds to run a suite before giving up",
|
49
|
+
"and moving on to the next suite."
|
50
|
+
) { |value| @options[:timeout] = value.to_i }
|
51
|
+
|
52
|
+
opts.on("-i", "--interval [INTERVAL]",
|
53
|
+
"The polling interval value in seconds to poll the server posted for results."
|
54
|
+
) { |value| @options[:interval] = value.to_i }
|
55
|
+
|
56
|
+
opts.on("-c", "--clean [CLEAN]",
|
57
|
+
"Flag to clean previous results. "
|
58
|
+
) { |value| @options[:clean] = true }
|
59
|
+
|
60
|
+
opts.on("-b", "--browser [BROWSER]",
|
61
|
+
"Browser to use: FIREFOX (or FF, default), IE, SAFARI."
|
62
|
+
) do |value|
|
63
|
+
case value
|
64
|
+
when "FIREFOX", "FF"
|
65
|
+
@options[:browser] = FIREFOX
|
66
|
+
when "IE"
|
67
|
+
@options[:browser] = IE
|
68
|
+
when "SAFARI"
|
69
|
+
@options[:browser] = SAFARI
|
70
|
+
else
|
71
|
+
abort "Incorrect browser name: #{value}."
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-d", "--dir [DIR]",
|
76
|
+
"Directory to store the results. Defaults to ./tmp."
|
77
|
+
) { |value| @options[:dir] = value }
|
78
|
+
|
79
|
+
opts.on("-p", "--port [PORT]",
|
80
|
+
"Port on which to run the servlet server."
|
81
|
+
) { |value| @options[:port] = value }
|
82
|
+
|
83
|
+
if args.empty?
|
84
|
+
puts opts
|
85
|
+
exit
|
86
|
+
else
|
87
|
+
opts.parse!(args)
|
88
|
+
end
|
89
|
+
end #OptionParser.new
|
90
|
+
end #initialize
|
91
|
+
end #CLI
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module AutoPilot
|
2
|
+
|
3
|
+
# Represents a browser instance.
|
4
|
+
class Browser
|
5
|
+
attr_accessor :name, :suite, :port
|
6
|
+
def initialize(name, suite, port=3001)
|
7
|
+
@name = name
|
8
|
+
@suite = suite
|
9
|
+
@port = port
|
10
|
+
end
|
11
|
+
|
12
|
+
def start #:nodoc:
|
13
|
+
url_suffix = "&auto=true&resultsUrl=http://localhost:#{@port}/postResults"
|
14
|
+
windows_url_suffix = "^&auto=true^&resultsUrl=http://localhost:#{@port}/postResults"
|
15
|
+
if(HOST_OS == MACOS) #assuming Firefox for now--Safari is more problematic
|
16
|
+
`open "#{suite}#{url_suffix}"` if(@name == SAFARI)
|
17
|
+
|
18
|
+
@browser_process = Process.fork {`/Applications/FireFox.app/Contents/MacOS/firefox-bin "#{@suite}#{url_suffix}"`} if(@name == FIREFOX)
|
19
|
+
Process.detach(@browser_process)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Linux: NOT IMPLEMENTED.
|
23
|
+
if(HOST_OS == LINUX)
|
24
|
+
if(@name == FIREFOX)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Windows
|
29
|
+
if(HOST_OS == WINDOWS)
|
30
|
+
`start #{suite}#{windows_url_suffix}` if(@name == IE)
|
31
|
+
|
32
|
+
`start firefox.exe #{@suite}#{windows_url_suffix}` if(@name == FIREFOX)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def stop #:nodoc:
|
37
|
+
if(HOST_OS == MACOS) #assuming Firefox for now
|
38
|
+
# puts 'SIGKILL', @browser_process
|
39
|
+
# Process.kill('SIGKILL', @browser_process)
|
40
|
+
|
41
|
+
if(@name == FIREFOX)
|
42
|
+
line = `ps -A | grep "FireFox.app"`
|
43
|
+
puts line
|
44
|
+
process = line.split
|
45
|
+
puts "Killing #{@name}, process # #{process[0]}"
|
46
|
+
`kill -9 #{process[0]}`
|
47
|
+
elsif(@name == SAFARI)
|
48
|
+
line = `ps -A | grep "Safari.app"`
|
49
|
+
process = line.split
|
50
|
+
puts "Killing #{@name}, process # #{process[0]}"
|
51
|
+
`kill #{process[0]}`
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if(HOST_OS == WINDOWS)
|
56
|
+
`TASKKILL /F /IM iexplore.exe /T` if(@name == IE)
|
57
|
+
|
58
|
+
`TASKKILL /F /IM firefox.exe /T` if(@name == FIREFOX)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module AutoPilot
|
4
|
+
|
5
|
+
# File to which "pass" or "fail" is written for each suite run by autopilot.
|
6
|
+
class PassFailFile
|
7
|
+
FILE_NAME = "result.txt"
|
8
|
+
attr_reader :dir, :data
|
9
|
+
|
10
|
+
def initialize(dir)
|
11
|
+
@dir = dir
|
12
|
+
@data = data
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO just make alias or make write destructive?
|
16
|
+
def write data
|
17
|
+
append(data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def append(data)
|
21
|
+
FileUtils.mkdir(@dir) unless File.exist?(@dir)
|
22
|
+
File.open(self.path, 'a'){|out| out.write "#{data}\n"}
|
23
|
+
end
|
24
|
+
|
25
|
+
def clean!
|
26
|
+
FileUtils.rm_f self.path if File.exist? self.path
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.clean(dir)
|
30
|
+
path = dir + File::SEPARATOR + FILE_NAME
|
31
|
+
FileUtils.rm_f path if File.exist? path
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO make a default and configurable name for the file
|
35
|
+
def path
|
36
|
+
@dir + File::SEPARATOR + FILE_NAME
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# File where the posted results for a suite are written.
|
41
|
+
# The file's name is written as suite_name_year.month.day_hour.minute.second.html
|
42
|
+
class ResultsFile
|
43
|
+
attr_reader :dir, :suite_name, :data
|
44
|
+
|
45
|
+
def initialize(dir, suite_name, data)
|
46
|
+
@dir = dir
|
47
|
+
@suite_name = suite_name
|
48
|
+
@data = data
|
49
|
+
end
|
50
|
+
|
51
|
+
def write
|
52
|
+
FileUtils.mkdir(@dir) unless File.exist?(@dir)
|
53
|
+
File.open(path, 'w'){|out| out.write @data}
|
54
|
+
end
|
55
|
+
|
56
|
+
def path
|
57
|
+
time = Time.now
|
58
|
+
time_stamp = time.strftime("%Y.%m.%d_%I.%M.%S%p")
|
59
|
+
@dir + File::SEPARATOR + @suite_name.delete(" ") +"_" + time_stamp + ".html"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module AutoPilot
|
2
|
+
# Represents the state of the results. Are we still waiting
|
3
|
+
# for results to post?
|
4
|
+
class ResultsState
|
5
|
+
@@waiting = false
|
6
|
+
def ResultsState.waiting?
|
7
|
+
@@waiting
|
8
|
+
end
|
9
|
+
def ResultsState.waiting=(waiting)
|
10
|
+
@@waiting = waiting
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Poller for the ResultsState.
|
15
|
+
class ResultsStatePoller
|
16
|
+
attr_accessor :timeout, :interval
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
self.timeout = DEFAULT_TIMEOUT
|
20
|
+
self.interval = DEFAULT_INTERVAL
|
21
|
+
@stop = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def start
|
25
|
+
total_time = 0
|
26
|
+
while ResultsState.waiting?
|
27
|
+
puts "still waiting: #{total_time} of #{self.timeout}"
|
28
|
+
sleep self.interval
|
29
|
+
total_time += self.interval
|
30
|
+
break if total_time >= self.timeout || self.stop?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def stop
|
34
|
+
@stop = true
|
35
|
+
end
|
36
|
+
def stop?
|
37
|
+
@stop
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end #module
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# TODO write up a description of this file
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'webrick'
|
5
|
+
require 'rexml/document'
|
6
|
+
require 'rbconfig'
|
7
|
+
include WEBrick
|
8
|
+
include REXML
|
9
|
+
include Config
|
10
|
+
|
11
|
+
module AutoPilot
|
12
|
+
DEFAULT_RESULTS_DIR = 'tmp'
|
13
|
+
DEFAULT_TIMEOUT = 300 #seconds
|
14
|
+
DEFAULT_INTERVAL = 5 #seconds
|
15
|
+
DEFAULT_PORT = 2000
|
16
|
+
|
17
|
+
MACOS = "darwin"
|
18
|
+
WINDOWS = "mswin32"
|
19
|
+
LINUX = "linux"
|
20
|
+
SOLARIS = "solaris"
|
21
|
+
|
22
|
+
SAFARI = :safari
|
23
|
+
IE = :internet_explorer
|
24
|
+
FIREFOX = :firefox
|
25
|
+
|
26
|
+
host_os = nil
|
27
|
+
if(CONFIG["host_os"].index(WINDOWS) != nil)
|
28
|
+
host_os = WINDOWS
|
29
|
+
elsif(CONFIG["host_os"].index(MACOS) != nil)
|
30
|
+
host_os = MACOS
|
31
|
+
elsif(CONFIG["host_os"].index(LINUX) != nil)
|
32
|
+
host_os = LINUX
|
33
|
+
elsif(CONFIG["host_os"].index(SOLARIS) != nil)
|
34
|
+
host_os = SOLARIS
|
35
|
+
end
|
36
|
+
HOST_OS = host_os.freeze
|
37
|
+
|
38
|
+
# Controller for AutoPilot.
|
39
|
+
class SeleniumRunner
|
40
|
+
attr_accessor :port, :timeout, :interval, :suites, :browser, :dir
|
41
|
+
attr_writer :clean
|
42
|
+
|
43
|
+
def initialize(browser_name)
|
44
|
+
@port = DEFAULT_PORT
|
45
|
+
@timeout = DEFAULT_TIMEOUT
|
46
|
+
@interval = DEFAULT_INTERVAL
|
47
|
+
@suites = []
|
48
|
+
@clean = false
|
49
|
+
@browser_name = browser_name
|
50
|
+
@dir = DEFAULT_RESULTS_DIR
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_location
|
54
|
+
#puts Dir.pwd[-7..-1]
|
55
|
+
#abort("Please run this script from the \'webtest\' directory!") if(Dir.pwd[-7..-1] != "webtest")
|
56
|
+
end
|
57
|
+
|
58
|
+
def clean?
|
59
|
+
@clean
|
60
|
+
end
|
61
|
+
|
62
|
+
def run
|
63
|
+
server = nil
|
64
|
+
|
65
|
+
FileUtils.rm_r(dir) if self.clean? && File.exist?(dir)
|
66
|
+
PassFailFile.clean(dir)
|
67
|
+
|
68
|
+
# Thread that runs the http server
|
69
|
+
server_thread = Thread.new do
|
70
|
+
server = HTTPServer.new(:Port => @port)
|
71
|
+
server.mount("/postResults", SeleniumTestResultsServlet, @dir)
|
72
|
+
trap("INT"){ server.shutdown }
|
73
|
+
server.start
|
74
|
+
end
|
75
|
+
|
76
|
+
# Thread that runs the test processor
|
77
|
+
@suites.each do |suite|
|
78
|
+
#make sure the server is running
|
79
|
+
begin
|
80
|
+
puts suite
|
81
|
+
res = Net::HTTP.get_response(URI.parse(suite))
|
82
|
+
next unless res.code == '200'
|
83
|
+
rescue Errno::ECONNREFUSED => error
|
84
|
+
puts error
|
85
|
+
next
|
86
|
+
end
|
87
|
+
|
88
|
+
processor_thread = Thread.new do
|
89
|
+
ResultsState.waiting = true
|
90
|
+
poller = ResultsStatePoller.new
|
91
|
+
poller.timeout = @timeout
|
92
|
+
poller.interval = @interval
|
93
|
+
start_time = Time.now
|
94
|
+
trap("INT"){ poller.stop; break }
|
95
|
+
poller.start
|
96
|
+
end
|
97
|
+
|
98
|
+
# Open the file in the browser.
|
99
|
+
# Mac OS
|
100
|
+
browser = Browser.new(@browser_name, suite, @port)
|
101
|
+
puts "starting browser ", browser.name
|
102
|
+
browser.start
|
103
|
+
|
104
|
+
# Join the thread, then quit the browser
|
105
|
+
processor_thread.join
|
106
|
+
|
107
|
+
# Quit the browser
|
108
|
+
puts "quitting browser #{@browser_name}"
|
109
|
+
browser.stop
|
110
|
+
end
|
111
|
+
|
112
|
+
server.shutdown
|
113
|
+
server_thread.join
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end #module
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module AutoPilot
|
4
|
+
|
5
|
+
# Servlet that listens for a Selenium Test Suite's posted results.
|
6
|
+
class SeleniumTestResultsServlet < HTTPServlet::AbstractServlet
|
7
|
+
def initialize(config, *options)
|
8
|
+
super(config, *options)
|
9
|
+
@dir = DEFAULT_RESULTS_DIR
|
10
|
+
@dir = @options[0] if @options
|
11
|
+
end
|
12
|
+
def do_GET(request, response)
|
13
|
+
response['Content-Type'] = "text/html"
|
14
|
+
response.body = "<html><body>You're on the selenium results servlet.</body></html>"
|
15
|
+
end
|
16
|
+
def do_POST(request, response)
|
17
|
+
response['Content-Type'] = "text/html"
|
18
|
+
#puts(request.query)
|
19
|
+
name_of_suite = suite_name(request.query["suite"])
|
20
|
+
response.body = create_body(request, name_of_suite)
|
21
|
+
|
22
|
+
#TODO add SeleniumTestResultsConfig class for the dirs
|
23
|
+
results_file = ResultsFile.new(@dir, name_of_suite, response.body)
|
24
|
+
results_file.write
|
25
|
+
pass_fail_file = PassFailFile.new(@dir)
|
26
|
+
pass_fail_file.write "#{request.query['result']}: #{name_of_suite}"
|
27
|
+
ResultsState.waiting = false
|
28
|
+
#puts results_file.data
|
29
|
+
response.body
|
30
|
+
end
|
31
|
+
def create_body(request, name_of_suite)
|
32
|
+
query = request.query
|
33
|
+
result = "<html><head><title>#{name_of_suite} Results</title></head><body>"
|
34
|
+
result << "<table>"
|
35
|
+
result << "<tr><td>Suite Name</td><td><b>" + name_of_suite + "</b></td></tr>"
|
36
|
+
result << "<tr><td>Result</td><td>" + query["result"] + "</td></tr>"
|
37
|
+
result << "<tr><td>Total Time</td><td>" + query["totalTime"] + "</td></tr>"
|
38
|
+
result << "<tr><td>Tests Passed</td><td>" + query["numTestPasses"] + "</td></tr>"
|
39
|
+
result << "<tr><td>Test Failures</td><td>" + query["numTestFailures"] + "</td></tr>"
|
40
|
+
result << "<tr><td>Commands Passed</td><td>" + query["numCommandPasses"] + "</td></tr>"
|
41
|
+
result << "<tr><td>Commands Failed</td><td>" + query["numCommandFailures"] + "</td></tr>"
|
42
|
+
result << "<tr><td>Command Erros</td><td>" + query["numCommandErrors"] + "</td></tr>"
|
43
|
+
result << "<tr><td>Browser Info</td><td>#{request['User-Agent']}</td></tr>"
|
44
|
+
result << "</table>"
|
45
|
+
result << query["suite"]
|
46
|
+
|
47
|
+
# get each test table
|
48
|
+
testNum = 1
|
49
|
+
while query["testTable.#{testNum}"]
|
50
|
+
result << query["testTable.#{testNum}"]
|
51
|
+
testNum = testNum.next
|
52
|
+
end
|
53
|
+
|
54
|
+
result << "</body></html>"
|
55
|
+
end
|
56
|
+
|
57
|
+
# grab the suite name from the first table cell of the suite's table
|
58
|
+
def suite_name(suite_table)
|
59
|
+
print "----------------------\n"
|
60
|
+
suite = Document.new(suite_table)
|
61
|
+
puts suite
|
62
|
+
#"suite"
|
63
|
+
suite_node = XPath.first(suite.root, "//TD/B")
|
64
|
+
suite_node = XPath.first(suite.root, "//td/b") if suite_node == nil
|
65
|
+
return suite_node.text
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/test/files_test.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'auto_pilot'
|
5
|
+
|
6
|
+
module AutoPilot
|
7
|
+
class FilesTest < Test::Unit::TestCase
|
8
|
+
RESULTS_DIR = 'results'
|
9
|
+
SUITE_NAME = 'SuiteName'
|
10
|
+
SUITE_DATA = '<html><body><p>Some test data for the suite test results</p></body></html>'
|
11
|
+
|
12
|
+
def setup
|
13
|
+
end
|
14
|
+
def teardown
|
15
|
+
FileUtils.rm_r RESULTS_DIR if File.exist? RESULTS_DIR
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_results_writer
|
19
|
+
puts "testing the results writer"
|
20
|
+
file = ResultsFile.new(RESULTS_DIR, SUITE_NAME, SUITE_DATA)
|
21
|
+
|
22
|
+
assert(!File.exist?(file.path), "File #{file.path} already exists!")
|
23
|
+
file.write
|
24
|
+
assert(File.exist?(file.path), "File #{file.path} already exists!")
|
25
|
+
assert_equal(SUITE_DATA, file.data)
|
26
|
+
|
27
|
+
# verify data written to file.
|
28
|
+
file_data = File.read(file.path)
|
29
|
+
assert_equal(SUITE_DATA, file_data)
|
30
|
+
|
31
|
+
FileUtils.rm_f(file.path) if File.exist?(file.path)
|
32
|
+
assert(!File.exist?(file.path), "File #{file.path} already exists!")
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_pass_fail_writer
|
36
|
+
puts "testing the pass/fail writer"
|
37
|
+
|
38
|
+
passed = "passed"
|
39
|
+
failed = "failed"
|
40
|
+
file = PassFailFile.new(RESULTS_DIR)
|
41
|
+
puts "file's path: #{file.path}"
|
42
|
+
FileUtils.rm_f(file.path) if File.exist?(file.path)
|
43
|
+
|
44
|
+
assert(!File.exist?(file.path), "File #{file.path} already exists!")
|
45
|
+
file.write passed
|
46
|
+
assert(File.exist?(file.path), "File #{file.path} missing!")
|
47
|
+
|
48
|
+
file.append failed
|
49
|
+
# verify data written to file.
|
50
|
+
file_data = File.read(file.path)
|
51
|
+
assert_equal("#{passed}\n#{failed}\n", file_data)
|
52
|
+
|
53
|
+
file.clean!
|
54
|
+
assert(!File.exist?(file.path), "File #{file.path} already exists!")
|
55
|
+
end
|
56
|
+
end #class
|
57
|
+
|
58
|
+
end #module
|
@@ -0,0 +1,30 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'auto_pilot'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
module AutoPilot
|
8
|
+
class AutoPilotTest < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
end
|
11
|
+
def teardown
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_firefox_launcher
|
15
|
+
browser = Browser.new(AutoPilot::FIREFOX, '')
|
16
|
+
browser.start
|
17
|
+
sleep 5
|
18
|
+
lines = `ps -A | grep "FireFox.app"`
|
19
|
+
puts lines
|
20
|
+
assert lines =~ /\/Applications\/FireFox.app/
|
21
|
+
browser.stop
|
22
|
+
sleep 1
|
23
|
+
lines = `ps -A | grep "FireFox.app"`
|
24
|
+
puts lines
|
25
|
+
assert lines !~ /\/Applications\/FireFox.app/
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/test/poller_test.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'auto_pilot'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
module AutoPilot
|
8
|
+
|
9
|
+
class PollerTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
end
|
12
|
+
def teardown
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_poller
|
16
|
+
puts "testing the poller"
|
17
|
+
poller = ResultsStatePoller.new
|
18
|
+
ResultsState.waiting = true
|
19
|
+
|
20
|
+
# validate default values for attributes
|
21
|
+
assert_equal(DEFAULT_TIMEOUT, poller.timeout)
|
22
|
+
assert_equal(DEFAULT_INTERVAL, poller.interval)
|
23
|
+
|
24
|
+
# now change the attributes
|
25
|
+
poller.timeout = DEFAULT_TIMEOUT + 10
|
26
|
+
poller.interval = DEFAULT_INTERVAL + 10
|
27
|
+
|
28
|
+
assert_not_equal(poller.timeout, DEFAULT_TIMEOUT)
|
29
|
+
assert_not_equal(poller.interval, DEFAULT_INTERVAL)
|
30
|
+
|
31
|
+
# run the poller
|
32
|
+
poller.timeout = 1
|
33
|
+
poller.interval = 1
|
34
|
+
start_time = Time.now
|
35
|
+
poller.start
|
36
|
+
end_time = Time.now
|
37
|
+
assert(end_time - start_time >= poller.timeout, "Poller timeout was longer than start and end time difference.")
|
38
|
+
end
|
39
|
+
end #class
|
40
|
+
end # module
|
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'auto_pilot'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
module AutoPilot
|
8
|
+
|
9
|
+
class AutoPilotTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
end
|
12
|
+
def teardown
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_poller
|
16
|
+
puts "testing the poller"
|
17
|
+
poller = ResultsStatePoller.new
|
18
|
+
ResultsState.waiting = true
|
19
|
+
|
20
|
+
# validate default values for attributes
|
21
|
+
assert_equal(DEFAULT_TIMEOUT, poller.timeout)
|
22
|
+
assert_equal(DEFAULT_INTERVAL, poller.interval)
|
23
|
+
|
24
|
+
# now change the attributes
|
25
|
+
poller.timeout = DEFAULT_TIMEOUT + 10
|
26
|
+
poller.interval = DEFAULT_INTERVAL + 10
|
27
|
+
|
28
|
+
assert_not_equal(poller.timeout, DEFAULT_TIMEOUT)
|
29
|
+
assert_not_equal(poller.interval, DEFAULT_INTERVAL)
|
30
|
+
|
31
|
+
# run the poller
|
32
|
+
poller.timeout = 1
|
33
|
+
poller.interval = 1
|
34
|
+
start_time = Time.now
|
35
|
+
poller.start
|
36
|
+
end_time = Time.now
|
37
|
+
assert(end_time - start_time >= poller.timeout, "Poller timeout was longer than start and end time difference.")
|
38
|
+
end
|
39
|
+
end #class
|
40
|
+
end # module
|
@@ -0,0 +1,185 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'auto_pilot'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
# TODO this test needs filling out, such as checking the results files, and actually using some asserts ;-)
|
8
|
+
module AutoPilot
|
9
|
+
|
10
|
+
# TODO This test suite needs to be revisited.
|
11
|
+
class ServletTest < Test::Unit::TestCase
|
12
|
+
RESULTS_DIR = 'tmp'
|
13
|
+
SUITE_NAME = 'SuiteName'
|
14
|
+
|
15
|
+
SUITE="suite=<table border='1' cellpadding='1' cellspacing='1'>
|
16
|
+
<TBODY>
|
17
|
+
<TR>
|
18
|
+
<TD bgcolor='#CFFFCF'><B>Regression Test Suite</B></TD>
|
19
|
+
</TR>
|
20
|
+
<TR>
|
21
|
+
<TD bgcolor='#CFFFCF'><a href=
|
22
|
+
'./regression/CreateCustomPlatePlan_RICurve_Test.html'>CreateCustomPlatePlan_RICurve_Test</a></TD>
|
23
|
+
</TR>
|
24
|
+
<TR>
|
25
|
+
<TD bgcolor='#CFFFCF'><a href='./regression/CreateBulkPlatePlan_RICurve.html'>CreateBulkPlatePlan_RICurve</a></TD>
|
26
|
+
</TR>
|
27
|
+
</TBODY>
|
28
|
+
</table>"
|
29
|
+
TEST_1="testTable.1=<div>
|
30
|
+
<table border='1' cellpadding='1' cellspacing='1'>
|
31
|
+
<TBODY>
|
32
|
+
<TR bgcolor='#CFFFCF'>
|
33
|
+
<TD rowspan='1' colspan='3'>Create Custom Plate Plan RI
|
34
|
+
Curve<br></TD>
|
35
|
+
</TR>
|
36
|
+
<TR bgcolor='white'>
|
37
|
+
<TD>open</TD>
|
38
|
+
<TD>
|
39
|
+
/fortius/servlet/fortius/action/InvalidateSession</TD>
|
40
|
+
<TD></TD>
|
41
|
+
</TR>
|
42
|
+
<TR bgcolor='white'>
|
43
|
+
<TD>pause</TD>
|
44
|
+
<TD>500</TD>
|
45
|
+
<TD></TD>
|
46
|
+
</TR>
|
47
|
+
<TR bgcolor='white'>
|
48
|
+
<TD>open</TD>
|
49
|
+
<TD>
|
50
|
+
/fortius/servlet/fortius/action/Index/skipuserlogin/true</TD>
|
51
|
+
<TD>go to the Fortius Home Page</TD>
|
52
|
+
</TR>
|
53
|
+
<TR bgcolor='#CFFFCF'>
|
54
|
+
<TD>verifyTextPresent</TD>
|
55
|
+
<TD>Fortius Home</TD>
|
56
|
+
<TD> </TD>
|
57
|
+
</TR>
|
58
|
+
</TBODY>
|
59
|
+
</table>
|
60
|
+
</div>"
|
61
|
+
TEST_2="testTable.2=<div>
|
62
|
+
<table border='1' cellpadding='1' cellspacing='1'>
|
63
|
+
<TBODY>
|
64
|
+
<TR bgcolor='#CFFFCF'>
|
65
|
+
<TD rowspan='1' colspan='3'>Create Bulk Plate Plan RI
|
66
|
+
Curve<br></TD>
|
67
|
+
</TR>
|
68
|
+
<TR bgcolor='white'>
|
69
|
+
<TD>open</TD>
|
70
|
+
<TD>
|
71
|
+
/fortius/servlet/fortius/action/InvalidateSession</TD>
|
72
|
+
<TD></TD>
|
73
|
+
</TR>
|
74
|
+
<TR bgcolor='white'>
|
75
|
+
<TD>pause</TD>
|
76
|
+
<TD>500</TD>
|
77
|
+
<TD></TD>
|
78
|
+
</TR>
|
79
|
+
<TR bgcolor='white'>
|
80
|
+
<TD>open</TD>
|
81
|
+
<TD>
|
82
|
+
/fortius/servlet/fortius/action/Index/skipuserlogin/true</TD>
|
83
|
+
<TD>go to the Fortius Home Page</TD>
|
84
|
+
</TR>
|
85
|
+
<TR bgcolor='#CFFFCF'>
|
86
|
+
<TD>verifyTextPresent</TD>
|
87
|
+
<TD>Fortius Home</TD>
|
88
|
+
<TD> </TD>
|
89
|
+
</TR>
|
90
|
+
<TR bgcolor='white'>
|
91
|
+
<TD>open</TD>
|
92
|
+
<TD>
|
93
|
+
<TD>create sample workorder</TD>
|
94
|
+
</TR>
|
95
|
+
<TR bgcolor='white'>
|
96
|
+
<TD>storeValue</TD>
|
97
|
+
<TD>workorderId</TD>
|
98
|
+
<TD>workorderId</TD>
|
99
|
+
</TR>
|
100
|
+
<TR bgcolor='white'>
|
101
|
+
<TD>storeValue</TD>
|
102
|
+
<TD>workorderName</TD>
|
103
|
+
<TD>workorderName</TD>
|
104
|
+
</TR>
|
105
|
+
<TR bgcolor='white'>
|
106
|
+
<TD>storeValue</TD>
|
107
|
+
<TD>kinaseId</TD>
|
108
|
+
<TD>kinaseId</TD>
|
109
|
+
</TR>
|
110
|
+
<TR bgcolor='white'>
|
111
|
+
<TD>clickAndWait</TD>
|
112
|
+
<TD>id=workorder</TD>
|
113
|
+
<TD>go to Workorder page</TD>
|
114
|
+
</TR>
|
115
|
+
<TR bgcolor='#CFFFCF'>
|
116
|
+
<TD>assertTextPresent</TD>
|
117
|
+
<TD>PROCESSING</TD>
|
118
|
+
<TD> </TD>
|
119
|
+
</TR>
|
120
|
+
</TBODY>
|
121
|
+
</table>
|
122
|
+
</div>"
|
123
|
+
|
124
|
+
BASIC_POST_DATA = "result=passed&totalTime=6&numTestPasses=6&numTestFailures=0&numCommandPasses=3&numCommandFailures=0&numCommandErrors=0"
|
125
|
+
POST_DATA = "#{BASIC_POST_DATA}&#{SUITE}&#{TEST_1}&#{TEST_2}"
|
126
|
+
SERVER_PORT = 1999
|
127
|
+
|
128
|
+
def setup
|
129
|
+
@server = HTTPServer.new(:Port => SERVER_PORT)
|
130
|
+
@server_thread = Thread.new do
|
131
|
+
@server.mount("/postResults", SeleniumTestResultsServlet)
|
132
|
+
trap("INT"){ @server.shutdown }
|
133
|
+
@server.start
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def teardown
|
138
|
+
@server.shutdown
|
139
|
+
@server_thread.join
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def test_servlet_responds
|
144
|
+
#
|
145
|
+
Net::HTTP.start('localhost', SERVER_PORT) do |http|
|
146
|
+
response = http.get('/postResults')
|
147
|
+
puts response.body
|
148
|
+
end
|
149
|
+
|
150
|
+
Net::HTTP.start('localhost', SERVER_PORT) do |http|
|
151
|
+
response = http.post('/postResults', POST_DATA)
|
152
|
+
#puts response.body
|
153
|
+
end
|
154
|
+
|
155
|
+
#TODO scan for some text to verify results--perhaps something from each query param value
|
156
|
+
|
157
|
+
#
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_servlet_with_poller
|
161
|
+
# use threads so that there can be a timeout before the post gets processed
|
162
|
+
3.times do
|
163
|
+
pthread = Thread.new do
|
164
|
+
ResultsState.waiting = true
|
165
|
+
poller = ResultsStatePoller.new
|
166
|
+
poller.timeout = 20
|
167
|
+
poller.interval = 1
|
168
|
+
start_time = Time.now
|
169
|
+
poller.start
|
170
|
+
end
|
171
|
+
|
172
|
+
hthread = Thread.new do
|
173
|
+
sleep 5
|
174
|
+
Net::HTTP.start('localhost', SERVER_PORT) do |http|
|
175
|
+
response = http.post('/postResults', POST_DATA)
|
176
|
+
puts response.body
|
177
|
+
end
|
178
|
+
end
|
179
|
+
pthread.join
|
180
|
+
hthread.join
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end # module
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: autopilot
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.3
|
7
|
+
date: 2006-06-21 00:00:00 -04:00
|
8
|
+
summary: AutoPilot is a Selenium Fitrunner launcher.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: jamie@dangosaur.us
|
12
|
+
homepage: ""
|
13
|
+
rubyforge_project: auto_pilot
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Jamie Orchard-Hays
|
30
|
+
files:
|
31
|
+
- examples/run_mac.rb
|
32
|
+
- lib/auto_pilot
|
33
|
+
- lib/auto_pilot.rb
|
34
|
+
- lib/auto_pilot/browser.rb
|
35
|
+
- lib/auto_pilot/CLI.rb
|
36
|
+
- lib/auto_pilot/files.rb
|
37
|
+
- lib/auto_pilot/poller.rb
|
38
|
+
- lib/auto_pilot/selenium_runner.rb
|
39
|
+
- lib/auto_pilot/servlet.rb
|
40
|
+
- test/files_test.rb
|
41
|
+
- test/mac_firefox_test.rb
|
42
|
+
- test/poller_test.rb
|
43
|
+
- test/selenium_runner_test.rb
|
44
|
+
- test/selenium_servlet_test.rb
|
45
|
+
- bin/aup
|
46
|
+
test_files: []
|
47
|
+
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
extra_rdoc_files: []
|
51
|
+
|
52
|
+
executables:
|
53
|
+
- aup
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
dependencies: []
|
59
|
+
|