torquespec 0.3.2 → 0.3.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/.gitignore CHANGED
@@ -2,4 +2,5 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
- .torquespec/*
5
+ .torquespec/*
6
+ /README.html
@@ -0,0 +1,171 @@
1
+ #+TITLE: Integration Testing for TorqueBox
2
+ #+AUTHOR: Jim Crossley
3
+ #+EMAIL: jcrossley@redhat.com
4
+ #+LANGUAGE: en
5
+ #+OPTIONS: H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
6
+ #+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc
7
+ #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
8
+ #+EXPORT_SELECT_TAGS: export
9
+ #+EXPORT_EXCLUDE_TAGS: noexport
10
+
11
+ * TorqueSpec
12
+
13
+ TorqueSpec extends the [[http://relishapp.com/rspec][RSpec testing framework]] to provide
14
+ integration testing for applications designed to run on the
15
+ [[http://torquebox.org/][TorqueBox Ruby application server]]. Before running your RSpec
16
+ examples, TorqueSpec ensures that a TorqueBox server is running and
17
+ enables you to verify expectations against real applications
18
+ deployed on it.
19
+
20
+ Easy browser control/simulation is possible via the [[https://github.com/jnicklas/capybara][capybara]] or
21
+ [[https://github.com/brynary/webrat][webrat]] gems, of course, but TorqueSpec also provides "in-container"
22
+ testing, where your examples are actually run within the TorqueBox
23
+ server itself.
24
+
25
+ ** Installation
26
+
27
+ Install the torquespec gem:
28
+
29
+ : $ gem install torquespec
30
+
31
+ And then in your spec files (or indirectly via =spec_helper.rb=):
32
+
33
+ : require 'torquespec'
34
+
35
+ Doing this will cause TorqueSpec to add a "before suite" hook that
36
+ fires up a TorqueBox server, i.e. JBoss, prior to running your
37
+ specs and an "after suite" hook to shut it down.
38
+
39
+ ** RSpec extensions
40
+
41
+ Aiming to be minimally intrusive, TorqueSpec makes two new methods
42
+ available to your spec files: =deploy= and =remote_describe=.
43
+
44
+ *** deploy()
45
+
46
+ Determines which app[s] are deployed prior to running a particular
47
+ =ExampleGroup=, so typically called from a top-level =describe=
48
+ block. The deployment and subsequent undeployment occur within
49
+ "before all" and "after all" RSpec hooks, respectively.
50
+
51
+ The method accepts any number of arguments, each of which should
52
+ represent a [[http://torquebox.org/2x/builds/html-docs/deployment-descriptors.html][TorqueBox deployment descriptor]], typically a YAML
53
+ "here document", a Hash, or a path to an existing file. It also
54
+ accepts a block, the result of which should also be one or more
55
+ deployment descriptors. Here's an example using a single here
56
+ doc:
57
+
58
+ : describe "basic test with heredoc" do
59
+ :
60
+ : deploy <<-DD_END.gsub(/^ {4}/,'')
61
+ : application:
62
+ : root: #{File.dirname(__FILE__)}/../app
63
+ : env: development
64
+ : web:
65
+ : context: /basic
66
+ : DD_END
67
+ :
68
+ : it "should work" do
69
+ : visit "/basic"
70
+ : page.should have_content('it worked')
71
+ : page.find("#success")[:class].should == 'basic'
72
+ : end
73
+ :
74
+ : end
75
+
76
+ Here docs are especially nice because they support string
77
+ substitution. Note that we're setting the location of the app
78
+ relative to the location of the spec file itself,
79
+ e.g. =__FILE__=. And the little =gsub(/^ {4},'')= trick allows
80
+ you to indent the YAML relative to the Ruby.
81
+
82
+ *** remote_describe()
83
+
84
+ TorqueSpec supports "in container" testing via the
85
+ =remote_describe= method. It behaves exactly like the RSpec
86
+ =describe= method, but the resulting =ExampleGroup= will be run
87
+ inside the TorqueBox server.
88
+
89
+ If your spec calls =remote_describe=, TorqueSpec will deploy a
90
+ small daemon with your application. This daemon will act as an
91
+ additional RSpec runner to which the "local" runner will delegate
92
+ the invocation of those =ExampleGroups= defined by
93
+ =remote_describe=. This delegation occurs via DRb: the "remote"
94
+ runner reports its results to the "local" one, allowing you to
95
+ summarize the results of all your tests, both in-container and
96
+ out, in a single report.
97
+
98
+ Because your specs are consumed by two separate RSpec processes,
99
+ you must ensure that any gems other than TorqueSpec/RSpec are
100
+ available to the process that needs them.
101
+
102
+ : require 'torquespec'
103
+ :
104
+ : TorqueSpec.local {
105
+ : require 'capybara'
106
+ : }
107
+ :
108
+ : app = <<-END.gsub(/^ {4}/,'')
109
+ : application:
110
+ : root: #{File.dirname(__FILE__)}/../app
111
+ : END
112
+ :
113
+ : describe "local test" do
114
+ : deploy(app)
115
+ :
116
+ : it "should work" do
117
+ : visit "/"
118
+ : page.should have_content('it worked')
119
+ : end
120
+ : end
121
+ :
122
+ : remote_describe "remote test" do
123
+ : deploy(app)
124
+ :
125
+ : it "should work" do
126
+ : some_service = inject(com.foo.SomeService)
127
+ : some_service.run.should == 'SUCCESS'
128
+ : end
129
+ : end
130
+
131
+ The above spec shows two example groups, one local and one remote.
132
+ But this spec will be processed by both the local test runner and
133
+ the remote daemon. The local one uses =capybara= so its require
134
+ is guarded in a =TorqueSpec.local= block, which won't be run
135
+ remotely. There's a complementary =TorqueSpec.remote= method
136
+ available, too.
137
+
138
+ Note also that the remote example is injecting a service that
139
+ wouldn't be available in the local runtime, only in the remote
140
+ TorqueBox server. Hence, the convenience, if not potential
141
+ confusion, of in-container testing. :)
142
+
143
+ ** Configuration
144
+
145
+ Configuration parameters are variables in the TorqueSpec namespace, e.g. =TorqueSpec.max_heap=.
146
+
147
+ | Parameter | Description | Default |
148
+ |--------------+----------------------------------------------------------------+---------------|
149
+ | ~knob_root~ | Where TorqueSpec creates your deployment descriptors | .torquespec |
150
+ | ~jboss_home~ | Where JBoss is installed | ~$JBOSS_HOME~ |
151
+ | ~max_heap~ | The maximum RAM allocated to the JBoss JVM | 1024 MB |
152
+ | ~jvm_args~ | Arguments to the JVM running JBoss | /see below/ |
153
+ | ~drb_port~ | The in-container spec runner listens on this port for requests | 7772 |
154
+ | ~lazy~ | Whether to use a running JBoss and leave it running when done | false |
155
+
156
+ By default, TorqueSpec is initialized thusly:
157
+
158
+ : TorqueSpec.configure do |config|
159
+ : config.drb_port = 7772
160
+ : config.knob_root = ".torquespec"
161
+ : config.jvm_args = "-Xms64m -Xmx1024m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -Dgem.path=default"
162
+ : end
163
+
164
+ Include a similar block in your =spec_helper.rb= to customize any of these.
165
+
166
+ ** Dependencies
167
+
168
+ TorqueSpec has been extensively tested with RSpec 2, though RSpec 1
169
+ should be compatible as well. But really, why are you still using
170
+ RSpec 1?
171
+
@@ -13,12 +13,15 @@ TorqueSpec::Configurator.configure do |config|
13
13
  config.extend(TorqueSpec)
14
14
  end
15
15
 
16
- if ENV['TORQUEBOX_APP_NAME']
16
+ TorqueSpec.remote {
17
17
  module TorqueSpec
18
18
  def deploy(*descriptors)
19
19
  end
20
20
  end
21
- else
21
+ }
22
+
23
+ TorqueSpec.local {
24
+
22
25
  require 'torquespec/server'
23
26
 
24
27
  TorqueSpec::Configurator.configure do |config|
@@ -43,7 +46,7 @@ else
43
46
  Thread.current[:app_server].stop
44
47
  end
45
48
  end
46
- end
49
+ }
47
50
 
48
51
  require 'torquespec/daemon'
49
52
 
@@ -51,7 +54,7 @@ module TorqueSpec
51
54
  module ObjectExtensions
52
55
  def remote_describe(*args, &example_group_block)
53
56
  group = describe(*args, &example_group_block)
54
- ENV['TORQUEBOX_APP_NAME'] ? group : group.extend( TorqueSpec::Daemon::Client )
57
+ TorqueSpec.remote? ? group : group.extend( TorqueSpec::Daemon::Client )
55
58
  end
56
59
  end
57
60
  end
@@ -6,7 +6,7 @@ module TorqueSpec
6
6
  class Daemon
7
7
 
8
8
  def initialize(opts={})
9
- puts "JC: create daemon opts=#{opts.inspect}"
9
+ puts "daemon: create opts=#{opts.inspect}"
10
10
  dir = opts['pwd'].to_s
11
11
  raise "The 'pwd' option must contain a valid directory name" if dir.empty? || !File.exist?(dir)
12
12
  Dir.chdir( dir ) do
@@ -25,24 +25,17 @@ module TorqueSpec
25
25
  end
26
26
 
27
27
  def start
28
- puts "JC: start daemon"
28
+ puts "daemon: start"
29
29
  DRb.start_service("druby://127.0.0.1:#{TorqueSpec.drb_port}", self)
30
- 10.times do
31
- if DRb.current_server
32
- break
33
- else
34
- sleep(0.1)
35
- end
36
- end
37
30
  end
38
31
 
39
32
  def stop
40
- puts "JC: stop daemon"
33
+ puts "daemon: stop"
41
34
  DRb.stop_service
42
35
  end
43
36
 
44
37
  def run(name, reporter)
45
- puts "JC: run #{name}"
38
+ puts "daemon: run #{name}"
46
39
  example_group = @world.example_groups.find { |g| g.name == name }
47
40
  example_group.run( reporter )
48
41
  end
@@ -65,15 +58,21 @@ module TorqueSpec
65
58
  def run_remotely(reporter)
66
59
  DRb.start_service("druby://127.0.0.1:0")
67
60
  daemon = DRbObject.new_with_uri("druby://127.0.0.1:#{TorqueSpec.drb_port}")
61
+ attempts = 10
68
62
  begin
69
63
  daemon.run( name, reporter )
64
+ rescue DRb::DRbConnError
65
+ # Overcome DRb.start_service() race condition
66
+ raise unless (attempts-=1) > 0
67
+ sleep(0.2)
68
+ retry
70
69
  ensure
71
70
  DRb.stop_service
72
71
  end
73
72
  end
74
73
 
75
74
  def deploy_paths
76
- [ DeploymentDescriptor.new({}, display_name, true).path ]
75
+ [ DeploymentDescriptor.new( {}, display_name, true ).path ]
77
76
  end
78
77
 
79
78
  end
@@ -7,7 +7,7 @@ module TorqueSpec
7
7
  metaclass = class << self; self; end
8
8
  metaclass.send(:define_method, :deploy_paths) do
9
9
  return @deploy_paths if @deploy_paths
10
- descriptors << block.call if block
10
+ descriptors += [block.call].flatten if block
11
11
  i = descriptors.size > 1 ? 0 : nil
12
12
  @deploy_paths = descriptors.map do |descriptor|
13
13
  DeploymentDescriptor.new(descriptor,
@@ -29,6 +29,15 @@ module TorqueSpec
29
29
  def as7?
30
30
  File.exist?( File.join( jboss_home, "bin/standalone.sh" ) )
31
31
  end
32
+ def jboss_home
33
+ @jboss_home ||= ENV['JBOSS_HOME'] || jboss_home_from_server_gem
34
+ end
35
+ def jboss_home_from_server_gem
36
+ require 'torquebox-server'
37
+ TorqueBox::Server.jboss_home
38
+ rescue Exception
39
+ $stderr.puts "WARN: Unable to determine JBoss install location; set either TorqueSpec.jboss_home or ENV['JBOSS_HOME']"
40
+ end
32
41
  end
33
42
 
34
43
  # A somewhat hackish way of exposing client-side gems to the server-side daemon
@@ -70,7 +79,6 @@ end
70
79
  TorqueSpec.configure do |config|
71
80
  config.drb_port = 7772
72
81
  config.knob_root = ".torquespec"
73
- config.jboss_home = ENV['JBOSS_HOME']
74
82
  config.jvm_args = "-Xms64m -Xmx1024m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -Dgem.path=default"
75
83
  end
76
84
 
@@ -1,3 +1,3 @@
1
1
  module TorqueSpec
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
@@ -15,10 +15,10 @@ end
15
15
 
16
16
  describe "simple directory deployment" do
17
17
 
18
- deploy <<-END.gsub(/^ {4}/,'')
18
+ deploy <<-DD_END.gsub(/^ {4}/,'')
19
19
  application:
20
20
  root: #{File.dirname(__FILE__)}/../apps/simple
21
- END
21
+ DD_END
22
22
 
23
23
  it "should greet the world" do
24
24
  response = open("http://localhost:8080") {|f| f.read}
metadata CHANGED
@@ -1,52 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: torquespec
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 3
9
- - 2
10
- version: 0.3.2
4
+ prerelease:
5
+ version: 0.3.3
11
6
  platform: ruby
12
7
  authors:
13
- - Jim Crossley
14
- - Bob McWhirter
8
+ - Jim Crossley
9
+ - Bob McWhirter
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
13
 
19
- date: 2011-06-11 00:00:00 -04:00
14
+ date: 2011-06-14 00:00:00 -04:00
20
15
  default_executable:
21
16
  dependencies:
22
- - !ruby/object:Gem::Dependency
23
- name: rspec
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 3
31
- segments:
32
- - 0
33
- version: "0"
34
- type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: json
38
- prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
48
- type: :runtime
49
- version_requirements: *id002
17
+ - !ruby/object:Gem::Dependency
18
+ name: rspec
19
+ prerelease: false
20
+ requirement: &id001 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: "0"
26
+ type: :runtime
27
+ version_requirements: *id001
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ prerelease: false
31
+ requirement: &id002 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: "0"
37
+ type: :runtime
38
+ version_requirements: *id002
50
39
  description: Write integration tests around the deployment of your app to a real JBoss app server
51
40
  email: team@projectodd.org
52
41
  executables: []
@@ -56,29 +45,29 @@ extensions: []
56
45
  extra_rdoc_files: []
57
46
 
58
47
  files:
59
- - .gitignore
60
- - Gemfile
61
- - README.md
62
- - Rakefile
63
- - apps/empty/torquebox.yml
64
- - apps/node-info.war
65
- - apps/simple.knob
66
- - apps/simple/config.ru
67
- - lib/rspec/core/torquespec-extensions.rb
68
- - lib/torque_spec/daemon.rb
69
- - lib/torquespec.rb
70
- - lib/torquespec/as6.rb
71
- - lib/torquespec/as7.rb
72
- - lib/torquespec/daemon.rb
73
- - lib/torquespec/deployment_descriptor.rb
74
- - lib/torquespec/server.rb
75
- - lib/torquespec/torquespec.rb
76
- - lib/torquespec/version.rb
77
- - spec/empty_spec.rb
78
- - spec/guard_spec.rb
79
- - spec/hello_world_spec.rb
80
- - spec/remote_spec.rb
81
- - torquespec.gemspec
48
+ - .gitignore
49
+ - Gemfile
50
+ - README.org
51
+ - Rakefile
52
+ - apps/empty/torquebox.yml
53
+ - apps/node-info.war
54
+ - apps/simple.knob
55
+ - apps/simple/config.ru
56
+ - lib/rspec/core/torquespec-extensions.rb
57
+ - lib/torque_spec/daemon.rb
58
+ - lib/torquespec.rb
59
+ - lib/torquespec/as6.rb
60
+ - lib/torquespec/as7.rb
61
+ - lib/torquespec/daemon.rb
62
+ - lib/torquespec/deployment_descriptor.rb
63
+ - lib/torquespec/server.rb
64
+ - lib/torquespec/torquespec.rb
65
+ - lib/torquespec/version.rb
66
+ - spec/empty_spec.rb
67
+ - spec/guard_spec.rb
68
+ - spec/hello_world_spec.rb
69
+ - spec/remote_spec.rb
70
+ - torquespec.gemspec
82
71
  has_rdoc: true
83
72
  homepage: http://github.com/torquebox/torquespec
84
73
  licenses: []
@@ -87,34 +76,28 @@ post_install_message:
87
76
  rdoc_options: []
88
77
 
89
78
  require_paths:
90
- - lib
79
+ - lib
91
80
  required_ruby_version: !ruby/object:Gem::Requirement
92
81
  none: false
93
82
  requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- hash: 3
97
- segments:
98
- - 0
99
- version: "0"
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
100
86
  required_rubygems_version: !ruby/object:Gem::Requirement
101
87
  none: false
102
88
  requirements:
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- hash: 3
106
- segments:
107
- - 0
108
- version: "0"
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
109
92
  requirements: []
110
93
 
111
94
  rubyforge_project: torquespec
112
- rubygems_version: 1.3.7
95
+ rubygems_version: 1.5.1
113
96
  signing_key:
114
97
  specification_version: 3
115
98
  summary: Deploy TorqueBox knobs to a running JBoss instance
116
99
  test_files:
117
- - spec/empty_spec.rb
118
- - spec/guard_spec.rb
119
- - spec/hello_world_spec.rb
120
- - spec/remote_spec.rb
100
+ - spec/empty_spec.rb
101
+ - spec/guard_spec.rb
102
+ - spec/hello_world_spec.rb
103
+ - spec/remote_spec.rb
data/README.md DELETED
@@ -1,8 +0,0 @@
1
- # TorqueSpec #
2
-
3
- TorqueSpec helps you build integration tests for your TorqueBox
4
- applications. It encapsulates the control of a JBoss AS instance, and
5
- makes it easy to deploy your apps before running your RSpec examples
6
- and undeploy them afterwards.
7
-
8
- More docs coming soon.