statt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +33 -0
  3. data/lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/cloud.rb +35 -0
  4. data/lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/ec2.rb +7 -0
  5. data/lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/ec2_client.rb +62 -0
  6. data/lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/hub.rb +22 -0
  7. data/lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/remote_command.rb +47 -0
  8. data/lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/server.rb +56 -0
  9. data/lib/selenium-grid/examples/ec2/test/unit/all_test.rb +2 -0
  10. data/lib/selenium-grid/examples/ec2/test/unit/cloud_test.rb +27 -0
  11. data/lib/selenium-grid/examples/ec2/test/unit/ec2_client_test.rb +137 -0
  12. data/lib/selenium-grid/examples/ec2/test/unit/hub_test.rb +24 -0
  13. data/lib/selenium-grid/examples/ec2/test/unit/remote_command_test.rb +46 -0
  14. data/lib/selenium-grid/examples/ec2/test/unit/server_test.rb +22 -0
  15. data/lib/selenium-grid/examples/ec2/test/unit/test_helper.rb +4 -0
  16. data/lib/selenium-grid/examples/ruby/flickr_example.rb +16 -0
  17. data/lib/selenium-grid/examples/ruby/lib/array_extension.rb +13 -0
  18. data/lib/selenium-grid/examples/ruby/lib/multi_process_behaviour_runner.rb +28 -0
  19. data/lib/selenium-grid/examples/ruby/paris_spec.rb +34 -0
  20. data/lib/selenium-grid/examples/ruby/perigord_spec.rb +22 -0
  21. data/lib/selenium-grid/examples/ruby/spec_helper.rb +59 -0
  22. data/lib/selenium-grid/lib/ruby/file_extensions.rb +9 -0
  23. data/lib/selenium-grid/lib/ruby/java/classpath.rb +28 -0
  24. data/lib/selenium-grid/lib/ruby/java/vm.rb +31 -0
  25. data/lib/selenium-grid/lib/ruby/s_grid/hub.rb +29 -0
  26. data/lib/selenium-grid/lib/ruby/s_grid/remote_control.rb +40 -0
  27. data/lib/selenium-grid/lib/ruby/tcp_socket_extensions.rb +24 -0
  28. data/lib/selenium-grid/sample-scripts/launch-remote-controls.rb +20 -0
  29. data/lib/statt.rb +23 -0
  30. data/lib/statt/client.rb +27 -0
  31. data/lib/statt/motor.rb +20 -0
  32. data/spec/client_spec.rb +19 -0
  33. data/spec/motor_spec.rb +13 -0
  34. data/spec/spec_helper.rb +10 -0
  35. data/spec/statt_spec.rb +7 -0
  36. metadata +89 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 davidtrogers
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.
@@ -0,0 +1,33 @@
1
+ = statt
2
+ Statt is a selenium testing environment that can be used with Cucumber to construct requirements based tests that fully cover web based user interfaces containing javascript and ajax. It will allow you to either create the selenium tests using cucumber directly, or will create the features from selenium IDE generated html files. This will be valuable if someone else is creating your features for you, for example, a QA tester.
3
+
4
+ Roadmap
5
+
6
+ Release 0.1
7
+ - full selenium setup including locally spawned selenium server
8
+ - cucumber integration
9
+ - database setup using factory girl
10
+ - full api for selenium methods (cucumber steps)
11
+
12
+ Release 0.2
13
+ - optimizations for speed
14
+ - factory generation based on models
15
+ - dynamic test data inserted into tests based on factory setup
16
+ - model optimization hints
17
+ - multiple instances running simultaneously for further speed improvements
18
+
19
+
20
+ == Note on Patches/Pull Requests
21
+
22
+ * Fork the project.
23
+ * Make your feature addition or bug fix.
24
+ * Add tests for it. This is important so I don't break it in a
25
+ future version unintentionally.
26
+ * Commit, do not mess with rakefile, version, or history.
27
+ (if you want to have your own version, that is fine but
28
+ bump version in a commit by itself I can ignore when I pull)
29
+ * Send me a pull request. Bonus points for topic branches.
30
+
31
+ == Copyright
32
+
33
+ Copyright (c) 2009 davidtrogers. See LICENSE for details.
@@ -0,0 +1,35 @@
1
+ module SeleniumGrid
2
+ module AWS
3
+
4
+ class Cloud
5
+ FILE = "cloud.yml"
6
+ attr_accessor :hub, :farms
7
+
8
+ def self.load
9
+ begin
10
+ YAML.load(File.read(FILE))
11
+ rescue Errno::ENOENT
12
+ new
13
+ end
14
+ end
15
+
16
+ def self.update
17
+ cloud = self.load
18
+ yield cloud
19
+ ensure
20
+ cloud.write unless cloud.nil?
21
+ end
22
+
23
+ def write
24
+ File.open(FILE, "w") {|file| file.write(self.to_yaml)}
25
+ end
26
+
27
+ def farms
28
+ @farms ||= []
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require "yaml"
3
+ require File.dirname(__FILE__) + '/cloud'
4
+ require File.dirname(__FILE__) + '/ec2_client'
5
+ require File.dirname(__FILE__) + '/server'
6
+ require File.dirname(__FILE__) + '/hub'
7
+ require File.dirname(__FILE__) + '/remote_command'
@@ -0,0 +1,62 @@
1
+ module SeleniumGrid
2
+ module AWS
3
+ module Ec2Client
4
+
5
+ def describe(instance_id)
6
+ output = ec2_shell "ec2-describe-instances #{instance_id}"
7
+ output =~ /INSTANCE\s+(i-.*)$/
8
+ fields = $1.split(/\s+/)
9
+ if output =~ /running/
10
+ {:instance_id => fields[0],
11
+ :ami => fields[1],
12
+ :public_dns => fields[2],
13
+ :private_dns => fields[3],
14
+ :status => fields[4] }
15
+ else
16
+ {:instance_id => fields[0],
17
+ :ami => fields[1],
18
+ :status => fields[2] }
19
+ end
20
+ end
21
+
22
+ def launch(ami, options ={})
23
+ output = ec2_shell "ec2-run-instances #{ami} -k #{options[:keypair]}"
24
+ output =~ /INSTANCE\s+(i-\S+)\s+ami-/
25
+ if $1 != nil
26
+ $1
27
+ else
28
+ raise InstanceLaunchError, output
29
+ end
30
+ end
31
+
32
+ def shutdown(instance_id)
33
+ ec2_shell "ec2-terminate-instances #{instance_id}"
34
+ end
35
+
36
+ def version
37
+ ec2_shell "ec2-version"
38
+ end
39
+
40
+ def authorize_port(port)
41
+ puts "Opening port #{port}..."
42
+ ec2_shell "ec2-authorize default -p #{port}"
43
+ end
44
+
45
+ def ec2_shell(command)
46
+ puts "[EC2] '#{command}'" if tracing?
47
+ output = `${EC2_HOME}/bin/#{command}`
48
+ puts "[EC2] #{output}" if tracing?
49
+ output
50
+ end
51
+
52
+ def tracing?
53
+ ENV['TRACE_EC2_COMMANDS']
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ class InstanceLaunchError < StandardError
60
+ end
61
+
62
+ end
@@ -0,0 +1,22 @@
1
+ module SeleniumGrid
2
+ module AWS
3
+
4
+ class Hub < Server
5
+
6
+ def url
7
+ "http://#{public_dns}:4444"
8
+ end
9
+
10
+ def private_url
11
+ "http://#{private_dns}:4444"
12
+ end
13
+
14
+ def console_url
15
+ "#{url}/console"
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+
@@ -0,0 +1,47 @@
1
+ module SeleniumGrid
2
+ module AWS
3
+
4
+ class RemoteCommand
5
+ attr_accessor :options
6
+
7
+ def initialize(command, options={})
8
+ @command, @options = command, options
9
+ end
10
+
11
+ def execute
12
+ puts full_command
13
+ system full_command
14
+ raise "Error with #{full_command}" if 0 != $?
15
+ end
16
+
17
+ def full_command
18
+ cmd = "#{ssh_command} "
19
+ cmd << "\"su -l #{options[:su]} -c " if options[:su]
20
+ cmd << "'#{remote_command}'"
21
+ cmd << '"' if options[:su]
22
+ cmd
23
+ end
24
+
25
+ def ssh_command
26
+ shell_command = [ "ssh" ]
27
+ shell_command << "-i '#{options[:keypair]}'" if options[:keypair]
28
+ shell_command << "root@#{options[:host]}"
29
+
30
+ shell_command.join " "
31
+ end
32
+
33
+ def remote_command
34
+ shell_command = []
35
+ shell_command << "PATH=#{options[:path]}:${PATH}; export PATH;" if options[:path]
36
+ shell_command << "DISPLAY=#{options[:display]}; export DISPLAY;" if options[:display]
37
+ shell_command << "cd '#{options[:pwd]}';" if options[:pwd]
38
+ shell_command << @command
39
+
40
+ shell_command.join " "
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
47
+
@@ -0,0 +1,56 @@
1
+ module SeleniumGrid
2
+ module AWS
3
+
4
+ class Server
5
+ extend Ec2Client
6
+
7
+ attr_accessor :instance_id, :public_dns, :private_dns
8
+
9
+ def initialize(instance_id)
10
+ self.instance_id = instance_id
11
+ end
12
+
13
+ def self.boot(ami, options = {})
14
+ new launch(ami, options)
15
+ end
16
+
17
+ def self.boot_and_acquire_dns(ami, options)
18
+ server = boot(ami, options)
19
+ server.wait_for_dns
20
+ end
21
+
22
+ def wait_for_dns
23
+ puts "Fetching DNS Info..."
24
+ until dns_allocated?
25
+ sleep 2
26
+ putc "."
27
+ refresh_status
28
+ end
29
+ puts
30
+ self
31
+ end
32
+
33
+ def dns_allocated?
34
+ public_dns != nil && public_dns != "" &&
35
+ private_dns != nil && private_dns != ""
36
+ end
37
+
38
+ def refresh_status
39
+ info = self.class.describe instance_id
40
+ @public_dns = info[:public_dns]
41
+ @private_dns = info[:private_dns]
42
+ end
43
+
44
+ def shutdown
45
+ self.class.shutdown instance_id
46
+ end
47
+
48
+ def run(command, options)
49
+ command = RemoteCommand.new command, options.merge(:host => public_dns)
50
+ command.execute
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ Dir['**/*_test.rb'].each {|test_file| require test_file }
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ unit_tests do
4
+
5
+ test "hub is nil on a fresh cloud" do
6
+ assert_nil SeleniumGrid::AWS::Cloud.new.hub
7
+ end
8
+
9
+ test "hub return the latest assigned hub instance" do
10
+ cloud = SeleniumGrid::AWS::Cloud.new
11
+ cloud.hub = :old_hub
12
+ cloud.hub = :new_hub
13
+ assert_equal :new_hub, cloud.hub
14
+ end
15
+
16
+ test "remote_control_farms is empty on a fresh cloud" do
17
+ assert_equal [], SeleniumGrid::AWS::Cloud.new.farms
18
+ end
19
+
20
+ test "remote_control_farms returns all added farms" do
21
+ cloud = SeleniumGrid::AWS::Cloud.new
22
+ cloud.farms << :a_farm
23
+ cloud.farms << :another_farm
24
+ assert_equal [:a_farm, :another_farm], cloud.farms
25
+ end
26
+
27
+ end
@@ -0,0 +1,137 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ unit_tests do
4
+
5
+ test "run_instance launch a new AMI using ec2-run-instances script" do
6
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
7
+ client.expects(:ec2_shell).with("ec2-run-instances TheAMI -k TheKeyPair")
8
+ client.launch "TheAMI", :keypair => "TheKeyPair"
9
+ end
10
+
11
+ test "run_instance returns the instance id when launch is successful" do
12
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
13
+ client.stubs(:ec2_shell).returns(<<-EOS)
14
+ RESERVATION r-ee629587 069216575636 default
15
+ INSTANCE i-6fef1006 ami-d306e3ba pending grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
16
+ EOS
17
+ assert_equal "i-6fef1006", client.launch(:an_ami)
18
+ end
19
+
20
+ test "authorize launch ec2-authorize script for default group" do
21
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
22
+ client.expects(:ec2_shell).with("ec2-authorize default -p ThePort")
23
+ client.authorize_port "ThePort"
24
+ end
25
+
26
+ test "describe launch ec2-describe script for a particular AMI" do
27
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
28
+ client.expects(:ec2_shell).with("ec2-describe-instances TheAMI").returns("INSTANCE i-")
29
+ client.describe "TheAMI"
30
+ end
31
+
32
+ test "describe returns the instance id when running" do
33
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
34
+ client.stubs(:ec2_shell).returns(<<-EOS)
35
+ RESERVATION r-ee629587 069216575636 default
36
+ INSTANCE i-6fef1006 ami-d306e3ba ec2-67-202-19-143.compute-1.amazonaws.com domU-12-31-38-00-3D-E6.compute-1.internal running grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
37
+ EOS
38
+ assert_equal "i-6fef1006", client.describe(:an_ami)[:instance_id]
39
+ end
40
+
41
+ test "describe returns the ami when running" do
42
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
43
+ client.stubs(:ec2_shell).returns(<<-EOS)
44
+ RESERVATION r-ee629587 069216575636 default
45
+ INSTANCE i-6fef1006 ami-d306e3ba ec2-67-202-19-143.compute-1.amazonaws.com domU-12-31-38-00-3D-E6.compute-1.internal running grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
46
+ EOS
47
+ assert_equal "ami-d306e3ba", client.describe(:an_ami)[:ami]
48
+ end
49
+
50
+ test "describe returns the public_dns when running" do
51
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
52
+ client.stubs(:ec2_shell).returns(<<-EOS)
53
+ RESERVATION r-ee629587 069216575636 default
54
+ INSTANCE i-6fef1006 ami-d306e3ba ec2-67-202-19-143.compute-1.amazonaws.com domU-12-31-38-00-3D-E6.compute-1.internal running grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
55
+ EOS
56
+ assert_equal "ec2-67-202-19-143.compute-1.amazonaws.com",
57
+ client.describe(:an_ami)[:public_dns]
58
+ end
59
+
60
+ test "describe returns the private_dns when running" do
61
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
62
+ client.stubs(:ec2_shell).returns(<<-EOS)
63
+ RESERVATION r-ee629587 069216575636 default
64
+ INSTANCE i-6fef1006 ami-d306e3ba ec2-67-202-19-143.compute-1.amazonaws.com domU-12-31-38-00-3D-E6.compute-1.internal running grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
65
+ EOS
66
+ assert_equal "domU-12-31-38-00-3D-E6.compute-1.internal",
67
+ client.describe(:an_ami)[:private_dns]
68
+ end
69
+
70
+ test "describe returns the status when running" do
71
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
72
+ client.stubs(:ec2_shell).returns(<<-EOS)
73
+ RESERVATION r-ee629587 069216575636 default
74
+ INSTANCE i-6fef1006 ami-d306e3ba ec2-67-202-19-143.compute-1.amazonaws.com domU-12-31-38-00-3D-E6.compute-1.internal running grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
75
+ EOS
76
+ assert_equal "running", client.describe(:an_ami)[:status]
77
+ end
78
+
79
+ test "describe returns the instance id when terminated" do
80
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
81
+ client.stubs(:ec2_shell).returns(<<-EOS)
82
+ RESERVATION r-ee629587 069216575636 default
83
+ INSTANCE i-6fef1006 ami-d306e3ba terminated grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
84
+ EOS
85
+ assert_equal "i-6fef1006", client.describe(:an_ami)[:instance_id]
86
+ end
87
+
88
+ test "describe returns the status when pending" do
89
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
90
+ client.stubs(:ec2_shell).returns(<<-EOS)
91
+ RESERVATION r-40609729 069216575636 default
92
+ INSTANCE i-afee11c6 ami-6801e401 pending grid-keypair 0 m1.small 2008-02-17T22:33:38+0000
93
+ EOS
94
+ assert_equal "pending", client.describe(:an_ami)[:status]
95
+ end
96
+
97
+ test "describe returns a nil public dns the status when pending" do
98
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
99
+ client.stubs(:ec2_shell).returns(<<-EOS)
100
+ RESERVATION r-40609729 069216575636 default
101
+ INSTANCE i-afee11c6 ami-6801e401 pending grid-keypair 0 m1.small 2008-02-17T22:33:38+0000
102
+ EOS
103
+ assert_nil client.describe(:an_ami)[:public_dns]
104
+ end
105
+
106
+ test "describe returns a nil private dns the status when pending" do
107
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
108
+ client.stubs(:ec2_shell).returns(<<-EOS)
109
+ RESERVATION r-40609729 069216575636 default
110
+ INSTANCE i-afee11c6 ami-6801e401 pending grid-keypair 0 m1.small 2008-02-17T22:33:38+0000
111
+ EOS
112
+ assert_nil client.describe(:an_ami)[:private_dns]
113
+ end
114
+
115
+ test "describe returns the status when terminated" do
116
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
117
+ client.stubs(:ec2_shell).returns(<<-EOS)
118
+ RESERVATION r-ee629587 069216575636 default
119
+ INSTANCE i-6fef1006 ami-d306e3ba terminated grid-keypair 0 m1.small 2008-02-17T20:49:08+0000
120
+ EOS
121
+ assert_equal "terminated", client.describe(:an_ami)[:status]
122
+ end
123
+
124
+ test "shutdown terminates an instance" do
125
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
126
+ client.expects(:ec2_shell).with("ec2-terminate-instances The-Instance-ID")
127
+ client.shutdown("The-Instance-ID")
128
+ end
129
+
130
+ test "version returns EC2 version using defined keypair" do
131
+ client = Class.new.extend SeleniumGrid::AWS::Ec2Client
132
+ client.expects(:ec2_shell).with("ec2-version").returns(:ec2_version)
133
+ assert_equal :ec2_version, client.version
134
+ end
135
+
136
+ # ec2-version -K "${EC2_PRIVATE_KEY}"
137
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ unit_tests do
4
+
5
+ test "url return the public url where the hub can be contacted" do
6
+ hub = SeleniumGrid::AWS::Hub.new nil
7
+ hub.public_dns = "public.dns"
8
+ assert_equal "http://public.dns:4444", hub.url
9
+ end
10
+
11
+ test "private_url return the private url where the hub can be contacted" do
12
+ hub = SeleniumGrid::AWS::Hub.new nil
13
+ hub.private_dns = "private.dns"
14
+ assert_equal "http://private.dns:4444", hub.private_url
15
+ end
16
+
17
+ test "console_url return the public url of the hub console" do
18
+ hub = SeleniumGrid::AWS::Hub.new nil
19
+ hub.public_dns = "public.dns"
20
+ assert_equal "http://public.dns:4444/console", hub.console_url
21
+ end
22
+
23
+
24
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ unit_tests do
4
+
5
+ test "ssh_command builds ssh based command targetting the host" do
6
+ command = SeleniumGrid::AWS::RemoteCommand.new "ls", :host => "the.host"
7
+ assert_equal "ssh root@the.host", command.ssh_command
8
+ end
9
+
10
+ test "ssh_command use custom key when keypair options is provided" do
11
+ command = SeleniumGrid::AWS::RemoteCommand.new "ls",
12
+ :host => "the.host", :keypair => "/the/key.pair"
13
+ assert_equal "ssh -i '/the/key.pair' root@the.host", command.ssh_command
14
+ end
15
+
16
+ test "remote_command" do
17
+ command = SeleniumGrid::AWS::RemoteCommand.new "ls", :pwd => "/a/directory"
18
+ assert_equal "cd '/a/directory'; ls", command.remote_command
19
+ end
20
+
21
+ test "remote_command set path when path is provided as an option" do
22
+ command = SeleniumGrid::AWS::RemoteCommand.new "ls", :path => "/a/directory:and/another"
23
+ assert_equal "PATH=/a/directory:and/another:${PATH}; export PATH; ls", command.remote_command
24
+ end
25
+
26
+ test "remote_command set display when display is provided as an option" do
27
+ command = SeleniumGrid::AWS::RemoteCommand.new "ls", :display => ":0"
28
+ assert_equal "DISPLAY=:0; export DISPLAY; ls", command.remote_command
29
+ end
30
+
31
+ test "full_command execute the remote command using ssh_command" do
32
+ command = SeleniumGrid::AWS::RemoteCommand.new nil
33
+ command.stubs(:ssh_command).returns("the_ssh_command")
34
+ command.stubs(:remote_command).returns("the remote command")
35
+ assert_equal "the_ssh_command 'the remote command'", command.full_command
36
+ end
37
+
38
+ test "full_command wraps remote_command with 'su user -c' when su option is set" do
39
+ command = SeleniumGrid::AWS::RemoteCommand.new nil, :su => "a-user"
40
+ command.stubs(:ssh_command).returns("the_ssh_command")
41
+ command.stubs(:remote_command).returns("the remote command")
42
+ assert_equal "the_ssh_command \"su -l a-user -c 'the remote command'\"",
43
+ command.full_command
44
+ end
45
+
46
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ unit_tests do
4
+
5
+ test "refresh_status updates public dns" do
6
+ server = SeleniumGrid::AWS::Server.new :an_instance_id
7
+ SeleniumGrid::AWS::Server.expects(:describe).with(:an_instance_id).
8
+ returns(:public_dns => :new_public_dns)
9
+ server.refresh_status
10
+ assert_equal :new_public_dns, server.public_dns
11
+ end
12
+
13
+ test "refresh_status updates private dns" do
14
+ server = SeleniumGrid::AWS::Server.new :an_instance_id
15
+ SeleniumGrid::AWS::Server.expects(:describe).with(:an_instance_id).
16
+ returns(:private_dns => :new_private_dns)
17
+ server.refresh_status
18
+ assert_equal :new_private_dns, server.private_dns
19
+ end
20
+
21
+
22
+ end
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + "/../../lib/selenium_grid/aws/ec2"
2
+ require "rubygems"
3
+ require "dust"
4
+ require "mocha"
@@ -0,0 +1,16 @@
1
+ module FlickrExample
2
+
3
+ def run_flickr_scenario(options)
4
+ browser.open "/"
5
+ page.location.should match(%r{http://images.google.com/})
6
+ page.type "q", options[:search_string]
7
+ page.click "btnG", :wait_for => :page
8
+ page.click "link=Advanced Image Search", :wait_for => :page
9
+ page.click "rimgtype4"
10
+ page.click "sf"
11
+ page.select "imgc", "full color"
12
+ page.click "btnG", :wait_for => :page
13
+ page.text?(options[:search_string].split(/ /).first).should be_true
14
+ end
15
+
16
+ end
@@ -0,0 +1,13 @@
1
+ module ArrayExtension
2
+
3
+ def /(number_of_buckets)
4
+ buckets = (1..number_of_buckets).collect { [] }
5
+ while self.any? do
6
+ buckets.each do |bucket|
7
+ bucket << self.shift if self.any?
8
+ end
9
+ end
10
+ buckets
11
+ end
12
+
13
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/array_extension')
2
+ Array.send :include, ArrayExtension
3
+
4
+ class MultiProcessSpecRunner
5
+
6
+ def initialize(max_concurrent_processes = 10)
7
+ @max_concurrent_processes = max_concurrent_processes
8
+ end
9
+
10
+ def run(spec_files)
11
+ concurrent_processes = [ @max_concurrent_processes, spec_files.size ].min
12
+ spec_files_by_process = spec_files / concurrent_processes
13
+ concurrent_processes.times do |i|
14
+ cmd = "spec #{spec_files_by_process[i].join(' ')}"
15
+ puts "Launching #{cmd}"
16
+ exec(cmd) if fork == nil
17
+ end
18
+ success = true
19
+ concurrent_processes.times do |i|
20
+ pid, status = Process.wait2
21
+ puts "Test process ##{i} with pid #{pid} completed with #{status}"
22
+ success &&= status.exitstatus.zero?
23
+ end
24
+
25
+ raise "Build failed" unless success
26
+ end
27
+
28
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe "Paris" do
4
+ include FlickrExample
5
+
6
+ it "Has museums" do
7
+ run_flickr_scenario :search_string => "Louvre"
8
+ end
9
+
10
+ it "Has bridges" do
11
+ run_flickr_scenario :search_string => "Pont Neuf"
12
+ end
13
+
14
+ it "Has magnific cathedrals" do
15
+ run_flickr_scenario :search_string => "Notre Dame de Paris"
16
+ end
17
+
18
+ it "Has magnificent Castles" do
19
+ run_flickr_scenario :search_string => "Versailles"
20
+ end
21
+
22
+ it "Has a gorgeous river" do
23
+ run_flickr_scenario :search_string => "Seine by Night"
24
+ end
25
+
26
+ it "Has weird towers" do
27
+ run_flickr_scenario :search_string => "Tour Eiffel"
28
+ end
29
+
30
+ it "Has avenues" do
31
+ run_flickr_scenario :search_string => "Avenue des Champs Elysees"
32
+ end
33
+
34
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe "Perigord" do
4
+ include FlickrExample
5
+
6
+ it "Has magnific cro-magnon paintings" do
7
+ run_flickr_scenario :search_string => "lascaux hall of the bull"
8
+ end
9
+
10
+ it "Has magnific cities" do
11
+ run_flickr_scenario :search_string => "Sarlat"
12
+ end
13
+
14
+ it "Has magnific cathedrals" do
15
+ run_flickr_scenario :search_string => "Cathedral in Périgueux"
16
+ end
17
+
18
+ it "Has great wines" do
19
+ run_flickr_scenario :search_string => "Montbazillac"
20
+ end
21
+
22
+ end
@@ -0,0 +1,59 @@
1
+ $:.unshift
2
+
3
+ require "rubygems"
4
+ gem "rspec", "=1.1.8"
5
+ require 'spec/rake/spectask'
6
+
7
+ require "rake"
8
+
9
+ gem "selenium-client", "=1.2.7"
10
+ require "selenium/rake/tasks"
11
+ require "selenium/client"
12
+ require "selenium/rspec/spec_helper"
13
+
14
+ require File.expand_path(File.dirname(__FILE__) + "/flickr_example")
15
+
16
+ Spec::Runner.configure do |config|
17
+
18
+ config.before(:each) do
19
+ create_selenium_driver
20
+ start_new_browser_session
21
+ end
22
+
23
+ # The system capture need to happen BEFORE the closing the Selenium session
24
+ config.append_after(:each) do
25
+ @selenium_driver.close_current_browser_session
26
+ end
27
+
28
+ def start_new_browser_session
29
+ @selenium_driver.start_new_browser_session
30
+ @selenium_driver.set_context "Starting example '#{self.description}'"
31
+ end
32
+
33
+ def selenium_driver
34
+ @selenium_driver
35
+ end
36
+
37
+ def browser
38
+ @selenium_driver
39
+ end
40
+
41
+ def page
42
+ @selenium_driver
43
+ end
44
+
45
+ def create_selenium_driver
46
+ remote_control_server = ENV['SELENIUM_RC_HOST'] || "localhost"
47
+ port = ENV['SELENIUM_RC_PORT'] || 4444
48
+ browser = ENV['SELENIUM_RC_BROWSER'] || "*firefox"
49
+ timeout = ENV['SELENIUM_RC_TIMEOUT'] || 200
50
+ application_host = ENV['SELENIUM_APPLICATION_HOST'] || "images.google.com"
51
+ application_port = ENV['SELENIUM_APPLICATION_PORT'] || "80"
52
+
53
+ @selenium_driver = Selenium::Client::Driver.new(
54
+ remote_control_server, port, browser,
55
+ "http://#{application_host}:#{application_port}", timeout)
56
+ end
57
+
58
+ end
59
+
@@ -0,0 +1,9 @@
1
+ class File
2
+
3
+ def self.native_path(path)
4
+ expanded_path = File.expand_path(path)
5
+ expanded_path.gsub!('/', '\\') if PLATFORM['win32']
6
+ expanded_path
7
+ end
8
+
9
+ end
@@ -0,0 +1,28 @@
1
+ module Java
2
+
3
+ class Classpath
4
+ require 'pathname'
5
+
6
+ def initialize(root_dir)
7
+ @root = root_dir
8
+ @locations = []
9
+ self
10
+ end
11
+
12
+ def <<(paths)
13
+ @locations = (@locations << Dir[@root + '/' + paths]).flatten
14
+ self
15
+ end
16
+
17
+ def definition
18
+ @locations.map {|path| File.native_path(path)}.join(self.separator)
19
+
20
+ end
21
+
22
+ def separator
23
+ PLATFORM['win32'] ? ";" : ":"
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,31 @@
1
+ module Java
2
+
3
+ class VM
4
+
5
+ def run(classname, options)
6
+ command = [ "java" ]
7
+ command << "-cp \"#{options[:classpath]}\""
8
+ command << classname
9
+ command << jvm_properties(options[:properties])
10
+ command << options[:args].join(' ') if options[:args]
11
+ command << ">\"#{options[:log_file]}\" 2>&1" if options[:log_file]
12
+
13
+ if options[:background]
14
+ if PLATFORM['win32']
15
+ command.unshift("start")
16
+ else
17
+ command << "&"
18
+ end
19
+ end
20
+
21
+ sh command.join(' ')
22
+ end
23
+
24
+ def jvm_properties(property_hash)
25
+ return "" unless property_hash
26
+ property_hash.inject([]) {|memo, (name, value)| memo << "-D#{name}=#{value}" }.join(' ')
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,29 @@
1
+ module SGrid
2
+
3
+ class Hub
4
+
5
+ def initialize(options={})
6
+ @host = options[:host] || "localhost"
7
+ @port = (options[:port] || "4444").to_i
8
+ end
9
+
10
+ def start(options={})
11
+ root = File.expand_path(File.dirname(__FILE__) + "/../../..")
12
+ classpath = Java::Classpath.new(root)
13
+ classpath = classpath << "." << "lib/selenium-grid-hub-standalone-*.jar"
14
+ Java::VM.new.run "com.thoughtworks.selenium.grid.hub.HubServer",
15
+ options.merge(:classpath => classpath.definition)
16
+ end
17
+
18
+ def wait_until_up_and_running
19
+ TCPSocket.wait_for_service :host => @host, :port => @port
20
+ end
21
+
22
+ def shutdown
23
+ http = Net::HTTP.new(@host, @port)
24
+ http.post('/lifecycle-manager', "action=shutdown")
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,40 @@
1
+ module SGrid
2
+
3
+ class RemoteControl
4
+
5
+ def initialize(options={})
6
+ @host = options[:host] || "localhost"
7
+ @port = (options[:port] || "4444").to_i
8
+ @hub_url = options[:hub_url] || "http://localhost:4444"
9
+ @shutdown_command = options[:shutdown_command] || "shutDownSeleniumServer"
10
+ end
11
+
12
+ def start(options={})
13
+ # Selenium Server must be first in classpath
14
+ root = File.expand_path(File.dirname(__FILE__) + "/../../..")
15
+ classpath = Java::Classpath.new(root)
16
+ classpath = classpath << "." << "vendor/selenium-server-*.jar"
17
+ classpath = classpath << "lib/selenium-grid-remote-control-standalone-*.jar"
18
+ Java::VM.new.run "com.thoughtworks.selenium.grid.remotecontrol.SelfRegisteringRemoteControlLauncher",
19
+ options.merge(:classpath => classpath.definition,
20
+ :args => rc_args(options))
21
+ end
22
+
23
+ def shutdown
24
+ http = Net::HTTP.new(@host, @port)
25
+ http.post('/selenium-server/driver/', "cmd=#{@shutdown_command}")
26
+ end
27
+
28
+ def rc_args(options)
29
+ args = []
30
+ args << "-host" << @host
31
+ args << "-port" << @port
32
+ args << "-hubUrl" << @hub_url
33
+ args << %Q{-env "#{options[:environment] || ENV['ENVIRONMENT'] || '*firefox'}"}
34
+ args << (options[:selenium_args] || ENV['SELENIUM_ARGS'] || "")
35
+ args
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,24 @@
1
+ require 'timeout'
2
+ require 'socket'
3
+
4
+ class TCPSocket
5
+
6
+ def self.wait_for_service(options)
7
+ socket = nil
8
+ Timeout::timeout(options[:timeout] || 20) do
9
+ loop do
10
+ begin
11
+ socket = TCPSocket.new(options[:host], options[:port])
12
+ return
13
+ rescue Errno::ECONNREFUSED,
14
+ Errno::EBADF # Windows
15
+ puts ".\n"
16
+ sleep 2
17
+ end
18
+ end
19
+ end
20
+ ensure
21
+ socket.close unless socket.nil?
22
+ end
23
+
24
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Launch a collection of remote controls
4
+ #
5
+
6
+ def launch_on_unix(title, command)
7
+ terminal = ENV['TERM'] || "xterm"
8
+ system "#{terminal} -t '#{title}' -e '#{command}'"
9
+ end
10
+
11
+ def launch_in_terminal(title, command)
12
+ launch_on_unix(title, command)
13
+ end
14
+
15
+ first_port = ARGV[0] || 5555
16
+ last_port = ARGV[1] || 5555
17
+ base_directory = File.expand_path(File.dirname(__FILE__))
18
+ (first_port..last_port).each do |port|
19
+ launch_in_terminal "Remote Control #{port}", "ant -Dport=#{port} launch-remote-control"
20
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ module Statt
4
+ require "selenium"
5
+ require "selenium/server_manager"
6
+ require "selenium/selenium_server"
7
+
8
+ require "net/http"
9
+ require "yaml"
10
+ require 'selenium-grid/lib/ruby/tcp_socket_extensions'
11
+ require 'selenium-grid/lib/ruby/file_extensions'
12
+ require 'selenium-grid/lib/ruby/java/classpath'
13
+ require 'selenium-grid/lib/ruby/java/vm'
14
+ require 'selenium-grid/lib/ruby/s_grid/hub'
15
+ require 'selenium-grid/lib/ruby/s_grid/remote_control'
16
+
17
+ gem "selenium-client", ">=1.2.16"
18
+ require "selenium/client"
19
+ require 'nokogiri'
20
+
21
+ require 'statt/motor'
22
+ require 'statt/client'
23
+ end
@@ -0,0 +1,27 @@
1
+ require "selenium"
2
+ require "test/unit"
3
+ require "selenium/server_manager"
4
+ require "selenium/selenium_server"
5
+ require "selenium/client/driver"
6
+
7
+ module Statt
8
+ class Client
9
+ attr_reader :selenium_driver
10
+ def initialize
11
+ @selenium_driver = Selenium::Client::Driver.new \
12
+ :host => "localhost",
13
+ :port => 4444,
14
+ :browser => "*firefox",
15
+ :url => "http://www.google.com",
16
+ :timeout_in_second => 60
17
+ end
18
+
19
+ def test
20
+ @selenium_driver.start_new_browser_session
21
+ @selenium_driver.open "/"
22
+ @selenium_driver.type "q", "Selenium seleniumhq"
23
+ @selenium_driver.click "btnG", :wait_for => :page_to_load
24
+ @selenium_driver.close_current_browser_session
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+
2
+
3
+ module Statt
4
+ class Motor < Selenium::ServerManager
5
+
6
+ def initialize
7
+ @server = Selenium::SeleniumRCServer.new
8
+ end
9
+
10
+ def manager
11
+ self
12
+ end
13
+
14
+ def server
15
+ @server
16
+ end
17
+
18
+
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Client" do
4
+
5
+ it "should initialize a client to communicate with the grid hub" do
6
+ end
7
+
8
+ it "should receive an optional parameter of host and port to determine the location of the hub " do
9
+ end
10
+
11
+ it "should recieve an optional starting location though default to http://localhost:3000/" do
12
+ end
13
+
14
+ it "should provide an api to communicate with the selenium grid" do
15
+ end
16
+
17
+ it "should " do
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Motor" do
4
+ it "should connect with a pre-existing selenium grid hub to run the tests" do
5
+ end
6
+
7
+ it "should start a selenium grid hub if one is not specified" do
8
+ end
9
+
10
+ it "should shutdown a selenium grid hub if told to, and if the hub is local" do
11
+ end
12
+
13
+ end
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'statt'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+
8
+ Spec::Runner.configure do |config|
9
+
10
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Statt" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: statt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - davidtrogers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-21 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Testing web applications js and all
17
+ email: david.t.rogers@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/cloud.rb
27
+ - lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/ec2.rb
28
+ - lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/ec2_client.rb
29
+ - lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/hub.rb
30
+ - lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/remote_command.rb
31
+ - lib/selenium-grid/examples/ec2/lib/selenium_grid/aws/server.rb
32
+ - lib/selenium-grid/examples/ec2/test/unit/all_test.rb
33
+ - lib/selenium-grid/examples/ec2/test/unit/cloud_test.rb
34
+ - lib/selenium-grid/examples/ec2/test/unit/ec2_client_test.rb
35
+ - lib/selenium-grid/examples/ec2/test/unit/hub_test.rb
36
+ - lib/selenium-grid/examples/ec2/test/unit/remote_command_test.rb
37
+ - lib/selenium-grid/examples/ec2/test/unit/server_test.rb
38
+ - lib/selenium-grid/examples/ec2/test/unit/test_helper.rb
39
+ - lib/selenium-grid/examples/ruby/flickr_example.rb
40
+ - lib/selenium-grid/examples/ruby/lib/array_extension.rb
41
+ - lib/selenium-grid/examples/ruby/lib/multi_process_behaviour_runner.rb
42
+ - lib/selenium-grid/examples/ruby/paris_spec.rb
43
+ - lib/selenium-grid/examples/ruby/perigord_spec.rb
44
+ - lib/selenium-grid/examples/ruby/spec_helper.rb
45
+ - lib/selenium-grid/lib/ruby/file_extensions.rb
46
+ - lib/selenium-grid/lib/ruby/java/classpath.rb
47
+ - lib/selenium-grid/lib/ruby/java/vm.rb
48
+ - lib/selenium-grid/lib/ruby/s_grid/hub.rb
49
+ - lib/selenium-grid/lib/ruby/s_grid/remote_control.rb
50
+ - lib/selenium-grid/lib/ruby/tcp_socket_extensions.rb
51
+ - lib/selenium-grid/sample-scripts/launch-remote-controls.rb
52
+ - lib/statt.rb
53
+ - lib/statt/client.rb
54
+ - lib/statt/motor.rb
55
+ - LICENSE
56
+ - README.rdoc
57
+ has_rdoc: true
58
+ homepage: http://github.com/davidtrogers/statt
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --charset=UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Selenium Testing All The Time
85
+ test_files:
86
+ - spec/client_spec.rb
87
+ - spec/motor_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/statt_spec.rb