watirgrid 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Tim Koopmans
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/NOTES.txt ADDED
@@ -0,0 +1,14 @@
1
+ = Release Notes
2
+ == 0.0.1
3
+ Added access control lists for the controller and provider. This lets the user specify ACLs by way of simple white/blacklist security similar to that used by the Unix /etc/hosts.allow and /etc/hosts.deny files. The ACL constructor takes an array of strings. The first string of a pair is always “allow” or “deny”, and it’s followed by the address or addresses to allow or deny access.
4
+
5
+ e.g. ./provider.rb -a deny,all,allow,127.0.0.1
6
+ This would deny all access to this provider by default and allow access only from the localhost (127.0.0.1). This is the default setting if no ACLs are specified from the command line. This would affect all connectivity from the controller to the providers.
7
+
8
+ e.g. ./controller.rb -a deny,all,allow,192.168.1.*
9
+ This would deny all access to the controller by default with access allowed from any host in the 192.168.1.* subnet. This would affect all connectivity from the providers to the controller.
10
+
11
+ ---
12
+
13
+ Added startup bin scripts for the provider and controller. Ruby Gems will automatically deploy these on installation.
14
+
data/README.rdoc ADDED
@@ -0,0 +1,56 @@
1
+ = watirgrid
2
+
3
+ WatirGrid allows for distributed testing across a grid network using Watir.
4
+
5
+ Basic instructions are:
6
+
7
+ Pick a server to host the 'controller' for the ring server and execute the following:
8
+ $ controller -l INFO
9
+
10
+ This should find your external facing IP and start the corresponding DRb and Ring Servers:
11
+ DRb server started on : druby://192.168.1.105:11235
12
+ Ring server started on: druby://192.168.1.105:12358
13
+
14
+ On each client PC, host the 'provider' for the distributed (DRb) Watir objects
15
+ $ provider -l INFO
16
+
17
+ This should find the recently started Ring Server and register a tuple for the Watir object:
18
+ DRb server started on : druby://192.168.1.105:64864
19
+ New tuple registered : druby://192.168.1.105:12358
20
+
21
+ You will now be able to execute commands across remote browsers on your grid network.
22
+
23
+ Check the watirgid_spec.rb for some examples ...
24
+
25
+ e.g.
26
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
27
+ browsers.start(:quantity => 2, :read_all => true)
28
+ browsers.size.should == 2
29
+ browsers.each do |browser, browser_id|
30
+ browser.goto("http://www.google.com")
31
+ browser.text_field(:name, 'q').set("watirgrid")
32
+ browser.button(:name, "btnI").click
33
+ end
34
+
35
+ For more help see:
36
+ $ controller -h
37
+ Usage: controller [options]
38
+ Specific options:
39
+ -d, --drb-server-port PORT Specify DRb Server port to listen on
40
+ -r, --ring-server-port PORT Specify Ring Server port to listen on
41
+ -l, --log-level LEVEL Specify log level {DEBUG|INFO|ERROR}
42
+ -h, --help Show this message
43
+
44
+ $ ./provider -h
45
+ Usage: provider [options]
46
+ Specific options:
47
+ -r, --ring-server-port PORT Specify Ring Server port to broadcast on
48
+ -b, --browser-type TYPE Specify browser type to register {ie|firefox|safari}
49
+ -l, --log-level LEVEL Specify log level {DEBUG|INFO|ERROR}
50
+ -h, --help Show this message
51
+
52
+ I'll update the wiki soon'ish!
53
+
54
+ == Copyright
55
+
56
+ Copyright (c) 2009 Tim Koopmans. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "watirgrid"
8
+ gem.summary = %Q{WatirGrid: Web Application Testing in Ruby across a grid network.}
9
+ gem.description = %Q{WatirGrid allows for distributed testing across a grid network using Watir.}
10
+ gem.email = "tim.koops@gmail.com"
11
+ gem.homepage = "http://github.com/90kts/watirgrid"
12
+ gem.authors = ["Tim Koopmans"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.version = "0.0.1"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+ rdoc.rdoc_dir = 'rdoc'
41
+ rdoc.title = "watirgrid #{version}"
42
+ rdoc.rdoc_files.include('README*')
43
+ rdoc.rdoc_files.include('lib/**/*.rb')
44
+ end
data/TODO.txt ADDED
@@ -0,0 +1,16 @@
1
+ == Docs
2
+ better instructions in general
3
+
4
+ == Providers
5
+ Remote registration of providers
6
+ Re-write tuple space during tear down
7
+ Response times
8
+ Network breakdown times
9
+
10
+ == Protocol
11
+ Support for tcp or http?
12
+
13
+ == Tests
14
+ How many providers is suitable with druby
15
+ Comparison in performance with proxied objects (DRbUndumped) vs. copied objects
16
+
data/bin/controller ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'controller'
4
+ require 'provider'
5
+
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: controller [options]"
9
+ opts.separator ""
10
+ opts.separator "Specific options:"
11
+ opts.on("-d PORT", "--drb-server-port", Integer,
12
+ "Specify DRb Server port to listen on") do |d|
13
+ options[:drb_server_port] = d
14
+ end
15
+ opts.on("-r PORT", "--ring-server-port", Integer,
16
+ "Specify Ring Server port to listen on") do |r|
17
+ options[:ring_server_port] = r
18
+ end
19
+ opts.on("-a ACLS", "--access-control-list", Array,
20
+ "Specify a comma separated Access Control List") do |a|
21
+ options[:acls] = a
22
+ end
23
+ opts.on("-l LEVEL", "--log-level", String,
24
+ "Specify log level {DEBUG|INFO|ERROR}") do |l|
25
+ case l
26
+ when 'DEBUG'
27
+ options[:loglevel] = Logger::DEBUG
28
+ when 'INFO'
29
+ options[:loglevel] = Logger::INFO
30
+ when 'ERROR'
31
+ options[:loglevel] = Logger::ERROR
32
+ else
33
+ options[:loglevel] = Logger::ERROR
34
+ end
35
+ end
36
+ opts.on_tail("-h", "--help", "Show this message") do
37
+ puts opts
38
+ exit
39
+ end
40
+ end.parse!
41
+
42
+ controller = Controller.new(
43
+ :drb_server_port => options[:drb_server_port] || 11235,
44
+ :ring_server_port => options[:ring_server_port] || 12358,
45
+ :acls => options[:acls] || %w{ deny all allow 127.0.0.1 },
46
+ :loglevel => options[:loglevel]
47
+ )
48
+ controller.start
49
+ DRb.thread.join
data/bin/provider ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'controller'
4
+ require 'provider'
5
+
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: provider [options]"
9
+ opts.separator ""
10
+ opts.separator "Specific options:"
11
+ opts.on("-r PORT", "--ring-server-port", Integer,
12
+ "Specify Ring Server port to broadcast on") do |r|
13
+ options[:ring_server_port] = r
14
+ end
15
+ opts.on("-b TYPE", "--browser-type", String,
16
+ "Specify browser type to register {ie|firefox|safari}") do |b|
17
+ options[:browser_type] = b
18
+ end
19
+ opts.on("-a ACLS", "--access-control-list", Array,
20
+ "Specify a comma separated Access Control List") do |a|
21
+ options[:acls] = a
22
+ end
23
+ opts.on("-l LEVEL", "--log-level", String,
24
+ "Specify log level {DEBUG|INFO|ERROR}") do |l|
25
+ case l
26
+ when 'DEBUG'
27
+ options[:loglevel] = Logger::DEBUG
28
+ when 'INFO'
29
+ options[:loglevel] = Logger::INFO
30
+ when 'ERROR'
31
+ options[:loglevel] = Logger::ERROR
32
+ else
33
+ options[:loglevel] = Logger::ERROR
34
+ end
35
+ end
36
+ opts.on_tail("-h", "--help", "Show this message") do
37
+ puts opts
38
+ exit
39
+ end
40
+ end.parse!
41
+
42
+ provider = Provider.new(
43
+ :ring_server_port => options[:ring_server_port] || 12358,
44
+ :browser_type => options[:browser_type] || nil,
45
+ :acls => options[:acls] || %w{ deny all allow 127.0.0.1 },
46
+ :loglevel => options[:loglevel])
47
+ provider.start
48
+ DRb.thread.join
data/lib/controller.rb ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ # controller.rb
3
+ # Rinda Ring Server Controlller
4
+
5
+ require 'rubygems'
6
+ require 'rinda/tuplespace'
7
+ require 'rinda/ring'
8
+ require 'logger'
9
+ require 'optparse'
10
+ require 'drb/acl'
11
+
12
+ module Rinda
13
+
14
+ ##
15
+ # Extend Rinda::RingServer to allow a hostname/ipaddress
16
+ # to be passed in as parameter arguments. Also pass back
17
+ # attribute for ring server uri.
18
+ #
19
+ class RingServer
20
+ attr_accessor :uri
21
+
22
+ def initialize(ts, host='', port=Ring_PORT)
23
+ @uri = "druby://#{host}:#{port}"
24
+ @ts = ts
25
+ @soc = UDPSocket.open
26
+ @soc.bind(host, port)
27
+ @w_service = write_service
28
+ @r_service = reply_service
29
+ end
30
+ end
31
+ end
32
+
33
+ class Controller
34
+
35
+ attr_accessor :drb_server_uri, :ring_server_uri
36
+
37
+ def initialize(params = {})
38
+ @host = params[:interface] || external_interface
39
+ @drb_server_port = params[:drb_server_port] || 0
40
+ @ring_server_port = params[:ring_server_port] || Rinda::Ring_PORT
41
+ @acls = params[:acls]
42
+
43
+ logfile = params[:logfile] || STDOUT
44
+ @log = Logger.new(logfile, 'daily')
45
+ @log.level = params[:loglevel] || Logger::INFO
46
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S "
47
+
48
+ @log.debug("DRB Server Port #{@drb_server_port}\nRing Server Port #{@ring_server_port}")
49
+ end
50
+
51
+ ##
52
+ # Start a new tuplespace on the ring server
53
+ def start
54
+ # create a parent Tuple Space
55
+ tuple_space = Rinda::TupleSpace.new
56
+
57
+ # Setup the security--remember to call before DRb.start_service()
58
+ DRb.install_acl(ACL.new(@acls))
59
+
60
+ # start the DRb Server
61
+ drb_server = DRb.start_service("druby://#{@host}:#{@drb_server_port}", tuple_space)
62
+
63
+ # obtain DRb Server uri
64
+ @drb_server_uri = drb_server.uri
65
+ @log.info("DRb server started on : #{@drb_server_uri}")
66
+
67
+ # start the Ring Server
68
+ ring_server = Rinda::RingServer.new(tuple_space, @host, @ring_server_port)
69
+
70
+ # obtain Ring Server uri
71
+ @ring_server_uri = ring_server.uri
72
+ @log.info("Ring server started on: #{@ring_server_uri}")
73
+
74
+ # abort all threads on an exception
75
+ Thread.abort_on_exception = true
76
+
77
+ # wait for explicit stop via ctrl-c
78
+ DRb.thread.join if __FILE__ == $0
79
+ end
80
+
81
+ ##
82
+ # Stop the controller by shutting down the DRb service
83
+ def stop
84
+ DRb.stop_service
85
+ @log.info("DRb server stopped on: #{@drb_server_uri}")
86
+ end
87
+
88
+ private
89
+
90
+ ##
91
+ # Get the external facing interface for this server
92
+ def external_interface
93
+ begin
94
+ UDPSocket.open {|s| s.connect('watir.com', 1); s.addr.last }
95
+ rescue
96
+ '127.0.0.1'
97
+ end
98
+ end
99
+
100
+ end
101
+
data/lib/provider.rb ADDED
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+ # provider.rb
3
+ # Rinda Ring Provider
4
+
5
+ require 'rubygems'
6
+ require 'rinda/ring'
7
+ require 'rinda/tuplespace'
8
+ require 'logger'
9
+ require 'optparse'
10
+ require 'drb/acl'
11
+
12
+ begin
13
+ require 'watir'
14
+ rescue LoadError
15
+ end
16
+
17
+ begin
18
+ require 'safariwatir'
19
+ rescue LoadError
20
+ end
21
+
22
+ begin
23
+ require 'firewatir'
24
+ include FireWatir
25
+ rescue LoadError
26
+ end
27
+
28
+ module Watir
29
+
30
+ ##
31
+ # Extend Watir with a Provider class
32
+ # to determine which browser type is supported by the
33
+ # remote DRb process. This returns the DRb front object.
34
+ class Provider
35
+
36
+ include DRbUndumped # all objects will be proxied, not copied
37
+
38
+ attr_reader :browser
39
+
40
+ def initialize(browser = nil)
41
+ browser = (browser || 'tmp').downcase.to_sym
42
+ case browser
43
+ when :safari
44
+ @browser = Watir::Safari
45
+ when :firefox
46
+ @browser = FireWatir::Firefox
47
+ when :ie
48
+ @browser = Watir::IE
49
+ else
50
+ @browser = find_supported_browser
51
+ end
52
+ end
53
+
54
+ def find_supported_browser
55
+ if Watir::Safari then return Watir::Safari end
56
+ if Watir::IE then return Watir::IE end
57
+ if FireWatir::Firefox then return FireWatir::Firefox end
58
+ end
59
+
60
+ def new_browser
61
+ if @browser.nil?
62
+ find_supported_browser.new
63
+ else
64
+ @browser.new
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ class Provider
73
+
74
+ attr_accessor :drb_server_uri, :ring_server_uri
75
+
76
+ def initialize(params = {})
77
+ @host = params[:interface] || external_interface
78
+ @drb_server_port = params[:drb_server_port] || 0
79
+ @ring_server_port = params[:ring_server_port] || Rinda::Ring_PORT
80
+
81
+ @renewer = params[:renewer] || Rinda::SimpleRenewer.new
82
+ @browser_type = params[:browser_type] || nil
83
+
84
+ logfile = params[:logfile] || STDOUT
85
+ @log = Logger.new(logfile, 'daily')
86
+ @log.level = params[:loglevel] || Logger::INFO
87
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S "
88
+
89
+ @log.debug("DRB Server Port #{@drb_server_port}\nRing Server Port #{@ring_server_port}")
90
+ end
91
+
92
+ ##
93
+ # Start providing watir objects on the ring server
94
+ def start
95
+ # create a DRb 'front' object
96
+ watir_provider = Watir::Provider.new(@browser_type)
97
+ architecture = Config::CONFIG['arch']
98
+ hostname = ENV['SERVER_NAME'] || %x{hostname}.strip
99
+
100
+ # Setup the security--remember to call before DRb.start_service()
101
+ DRb.install_acl(ACL.new(@acls))
102
+
103
+ # start the DRb Server
104
+ drb_server = DRb.start_service("druby://#{@host}:#{@drb_server_port}")
105
+
106
+ # obtain DRb Server uri
107
+ @drb_server_uri = drb_server.uri
108
+ @log.info("DRb server started on : #{@drb_server_uri}")
109
+
110
+ # create a service tuple
111
+ @tuple = [
112
+ :name,
113
+ :WatirProvider,
114
+ watir_provider,
115
+ 'A watir provider',
116
+ hostname,
117
+ architecture,
118
+ @browser_type
119
+ ]
120
+
121
+ # locate the Rinda Ring Server via a UDP broadcast
122
+ ring_server = Rinda::RingFinger.new(@host, @ring_server_port)
123
+ ring_server = ring_server.lookup_ring_any
124
+ @log.info("Ring server found on : druby://#{@host}:#{@ring_server_port}")
125
+
126
+ # advertise this service on the primary remote tuple space
127
+ ring_server.write(@tuple, @renewer)
128
+
129
+ # log DRb server uri
130
+ @log.info("New tuple registered : druby://#{@host}:#{@ring_server_port}")
131
+
132
+ # wait for explicit stop via ctrl-c
133
+ DRb.thread.join if __FILE__ == $0
134
+ end
135
+
136
+ ##
137
+ # Stop the provider by shutting down the DRb service
138
+ def stop
139
+ DRb.stop_service
140
+ @log.info("DRb server stopped on : #{@drb_server_uri}")
141
+ end
142
+
143
+ private
144
+
145
+ ##
146
+ # Get the external facing interface for this server
147
+ def external_interface
148
+ begin
149
+ UDPSocket.open {|s| s.connect('watir.com', 1); s.addr.last }
150
+ rescue
151
+ '127.0.0.1'
152
+ end
153
+ end
154
+
155
+ end
156
+
data/lib/watirgrid.rb ADDED
@@ -0,0 +1,123 @@
1
+ require 'rubygems'
2
+ require 'controller'
3
+ require 'provider'
4
+
5
+ module Watir
6
+
7
+ ##
8
+ # Extend Watir with a Grid class which
9
+ # implements a grid of browsers by connecting to a tuplespace
10
+ # and instatiating remote browser objects on nominated providers.
11
+ class Grid
12
+
13
+ attr_accessor :drb_server_uri, :ring_server, :browsers
14
+
15
+ def initialize(params = {})
16
+ @host = params[:interface] || external_interface
17
+ @drb_server_port = params[:drb_server_port] || 0
18
+ @ring_server_port = params[:ring_server_port] || Rinda::Ring_PORT
19
+ @renewer = params[:renewer] || Rinda::SimpleRenewer.new
20
+
21
+ @quantity = params[:quantity]
22
+
23
+ logfile = params[:logfile] || STDOUT
24
+ @log = Logger.new(logfile, 'daily')
25
+ @log.level = params[:loglevel] || Logger::ERROR
26
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S "
27
+ end
28
+
29
+ ##
30
+ # Start required services
31
+ def start(params = {})
32
+ start_drb_server
33
+ find_ring_server
34
+ get_tuples(params)
35
+ end
36
+
37
+ ##
38
+ # Yield a browser object when iterating over the grid of browsers
39
+ def each
40
+ threads = []
41
+ id = 0
42
+ @browsers.each do |browser|
43
+ threads << Thread.new do
44
+ id += 1
45
+ yield(browser, id)
46
+ end
47
+ end
48
+ threads.each {|thread| thread.join}
49
+ end
50
+
51
+ ##
52
+ # Return the size (quantity) of browsers started on the grid
53
+ def size
54
+ @browsers.size
55
+ end
56
+
57
+ private
58
+
59
+ ##
60
+ # Get the external facing interface for this server
61
+ def external_interface
62
+ begin
63
+ UDPSocket.open {|s| s.connect('watir.com', 1); s.addr.last }
64
+ rescue
65
+ '127.0.0.1'
66
+ end
67
+ end
68
+
69
+ ##
70
+ # Start the DRb Server
71
+ def start_drb_server
72
+ drb_server = DRb.start_service("druby://#{@host}:#{@drb_server_port}")
73
+ @drb_server_uri = drb_server.uri
74
+ @log.info("DRb server started on : #{@drb_server_uri}")
75
+ end
76
+
77
+ ##
78
+ # Locate the Rinda Ring Server via a UDP broadcast
79
+ def find_ring_server
80
+ @ring_server = Rinda::RingFinger.new(@host, @ring_server_port)
81
+ @ring_server = @ring_server.lookup_ring_any
82
+ @log.info("Ring server found on : druby://#{@host}:#{@ring_server_port}")
83
+ end
84
+
85
+ ##
86
+ # Get all tuple spaces on ringserver
87
+ def get_tuples(params = {})
88
+ quantity = params[:quantity] || -1
89
+ architecture = params[:architecture] || nil
90
+ browser_type = params[:browser_type] || nil
91
+
92
+ @browsers = []
93
+ services = @ring_server.read_all([
94
+ :name,
95
+ nil, # watir provider
96
+ nil, # browser front object
97
+ nil, # provider description
98
+ nil, # hostname
99
+ architecture,
100
+ browser_type])
101
+
102
+ @log.info("Found #{services.size} services.")
103
+ if services.size > 0 then
104
+ services[1..quantity].each do |service|
105
+ hostname = service[4]
106
+ if params[:hostnames] then
107
+ if params[:hostnames][hostname] then
108
+ @browsers << service[2].new_browser
109
+ @ring_server.take(service)if params[:take_all] == true
110
+ end
111
+ else
112
+ @browsers << service[2].new_browser
113
+ @ring_server.take(service)if params[:take_all] == true
114
+ end
115
+ end
116
+ else
117
+ @browsers
118
+ end
119
+ end
120
+ end
121
+
122
+ end
123
+
data/spec/grid_spec.rb ADDED
@@ -0,0 +1,121 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe 'WatirGrid' do
4
+ before(:all) do
5
+ controller = Controller.new(:ring_server_port => 12351,
6
+ :loglevel => Logger::ERROR)
7
+ controller.start
8
+ 1.upto(5) do
9
+ provider = Provider.new(:ring_server_port => 12351,
10
+ :loglevel => Logger::ERROR, :browser_type => 'safari')
11
+ provider.start
12
+ end
13
+ end
14
+
15
+ it 'should return how many browsers are available in the tuplespace' do
16
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
17
+ browsers.start(:read_all => true)
18
+ browsers.size.should == 4
19
+ end
20
+
21
+ it 'should read any 2 browsers in the tuplespace' do
22
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
23
+ browsers.start(:quantity => 2, :read_all => true)
24
+ browsers.size.should == 2
25
+ browsers.each do |browser, browser_id|
26
+ browser.goto(
27
+ "http://localhost:4567/load/#{browser_id}/#{browser.object_id}")
28
+ end
29
+ end
30
+
31
+ it 'should take any 1 browser in the tuplespace' do
32
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
33
+ browsers.start(:quantity => 1, :take_all => true)
34
+ browsers.size.should == 1
35
+ end
36
+
37
+ it 'should take all browsers remaining in tuplespace' do
38
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
39
+ browsers.start(:take_all => true)
40
+ browsers.size.should == 3
41
+ end
42
+
43
+ it 'should find no more browsers in the tuplespace' do
44
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
45
+ browsers.start(:read_all => true)
46
+ browsers.size.should == 0
47
+ end
48
+
49
+ it 'should register 3 new browsers in the tuplespace' do
50
+ 1.upto(3) do
51
+ provider = Provider.new(:ring_server_port => 12351,
52
+ :loglevel => Logger::ERROR, :browser_type => 'safari')
53
+ provider.start
54
+ end
55
+ end
56
+
57
+ it 'should take any 1 browser based on browser type' do
58
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
59
+ browsers.start(:quantity => 1,
60
+ :take_all => true, :browser_type => 'safari')
61
+ browsers.size.should == 1
62
+ end
63
+
64
+ it 'should fail to find any browsers based on a specific browser type' do
65
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
66
+ browsers.start(:quantity => 1,
67
+ :take_all => true, :browser_type => 'firefox')
68
+ browsers.size.should == 0
69
+ end
70
+
71
+ it 'should fail to find any browsers based on a unknown browser type' do
72
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
73
+ browsers.start(:quantity => 1,
74
+ :take_all => true, :browser_type => 'penguin')
75
+ browsers.size.should == 0
76
+ end
77
+
78
+ it 'should take any 1 browser based on specific architecture type' do
79
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
80
+ browsers.start(:quantity => 1,
81
+ :take_all => true, :architecture => 'universal-darwin10.0')
82
+ browsers.size.should == 1
83
+ end
84
+
85
+ it 'should fail to find any browsers based on unknown architecture type' do
86
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
87
+ browsers.start(:quantity => 1,
88
+ :take_all => true, :architecture => 'geos-1992')
89
+ browsers.size.should == 0
90
+ end
91
+
92
+ it 'should take any 1 browser based on specific hostname' do
93
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
94
+ browsers.start(:quantity => 1,
95
+ :take_all => true, :hostnames => {
96
+ "90kts.local" => "127.0.0.1"})
97
+ browsers.size.should == 1
98
+ end
99
+
100
+ it 'should fail to find any browsers based on unknown hostname' do
101
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
102
+ browsers.start(:quantity => 1,
103
+ :take_all => true, :hostnames => {
104
+ "tokyo" => "127.0.0.1"})
105
+ browsers.size.should == 0
106
+ end
107
+
108
+ it 'should find no more browsers in the tuplespace' do
109
+ browsers = Watir::Grid.new(:ring_server_port => 12351)
110
+ browsers.start(:read_all => true)
111
+ browsers.size.should == 0
112
+ end
113
+
114
+ it 'should register a new browser on a remote provider' do
115
+ pending('provision of remote registration') do
116
+ browsers.size.should == 0
117
+ end
118
+ end
119
+
120
+ end
121
+
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'watirgrid'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
data/spec/stub.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+
4
+ get '/load/:browser_id/:browser_object_id' do
5
+ params[:browser_object_id]
6
+ end
7
+
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Controller do
4
+ it 'should start a DRb and Ring Server when specifying NO interface or port' do
5
+ controller = Controller.new
6
+ controller.start
7
+ controller.drb_server_uri.should =~ /druby/
8
+ controller.stop
9
+ end
10
+
11
+ it 'should start a DRb and Ring Server on a specified interface' do
12
+ controller = Controller.new(:interface => '127.0.0.1')
13
+ controller.start
14
+ controller.drb_server_uri.should =~ /druby/
15
+ controller.stop
16
+ end
17
+
18
+ it 'should start a DRb and Ring Server on specified ports' do
19
+ controller = Controller.new(:drb_server_port => 11235,
20
+ :ring_server_port => 12358)
21
+ controller.start
22
+ controller.drb_server_uri.should =~ /druby/
23
+ controller.stop
24
+ end
25
+ end
26
+
27
+ describe Provider do
28
+ before(:all) do
29
+ @controller = Controller.new(:ring_server_port => 12350)
30
+ @controller.start
31
+ end
32
+
33
+ it 'should register a new provider on a specified port' do
34
+ provider = Provider.new(:ring_server_port => 12350)
35
+ provider.start
36
+ end
37
+
38
+ after(:all) do
39
+ @controller.stop
40
+ end
41
+ end
42
+
data/watirgrid.gemspec ADDED
@@ -0,0 +1,59 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{watirgrid}
8
+ s.version = ""
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tim Koopmans"]
12
+ s.date = %q{2009-11-05}
13
+ s.description = %q{WatirGrid allows for distributed testing across a grid network using Watir.}
14
+ s.email = %q{tim.koops@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "lib/controller.rb",
26
+ "lib/extend.rb",
27
+ "lib/provider.rb",
28
+ "lib/watirgrid.rb",
29
+ "spec/spec.opts",
30
+ "spec/spec_helper.rb",
31
+ "spec/tuple_spec.rb",
32
+ "spec/watirgrid_spec.rb",
33
+ "watirgrid.gemspec"
34
+ ]
35
+ s.homepage = %q{http://github.com/90kts/watirgrid}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.5}
39
+ s.summary = %q{WatirGrid: Web Application Testing in Ruby across a grid network.}
40
+ s.test_files = [
41
+ "spec/spec_helper.rb",
42
+ "spec/tuple_spec.rb",
43
+ "spec/watirgrid_spec.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
52
+ else
53
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
54
+ end
55
+ else
56
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
57
+ end
58
+ end
59
+
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: watirgrid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tim Koopmans
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-16 00:00:00 +11:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ description: WatirGrid allows for distributed testing across a grid network using Watir.
26
+ email: tim.koops@gmail.com
27
+ executables:
28
+ - controller
29
+ - provider
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - LICENSE
34
+ - README.rdoc
35
+ files:
36
+ - .document
37
+ - .gitignore
38
+ - LICENSE
39
+ - NOTES.txt
40
+ - README.rdoc
41
+ - Rakefile
42
+ - TODO.txt
43
+ - bin/controller
44
+ - bin/provider
45
+ - lib/controller.rb
46
+ - lib/provider.rb
47
+ - lib/watirgrid.rb
48
+ - spec/grid_spec.rb
49
+ - spec/spec.opts
50
+ - spec/spec_helper.rb
51
+ - spec/stub.rb
52
+ - spec/watirgrid_spec.rb
53
+ - watirgrid.gemspec
54
+ has_rdoc: true
55
+ homepage: http://github.com/90kts/watirgrid
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --charset=UTF-8
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.5
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: "WatirGrid: Web Application Testing in Ruby across a grid network."
82
+ test_files:
83
+ - spec/grid_spec.rb
84
+ - spec/spec_helper.rb
85
+ - spec/stub.rb
86
+ - spec/watirgrid_spec.rb