Integration testing with TorqueBox
Pull request Compare This branch is 2 commits ahead, 15 commits behind torquebox:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Integration Testing for TorqueBox


TorqueSpec extends the RSpec testing framework to provide integration testing for applications designed to run on the TorqueBox Ruby application server. Before running your RSpec examples, TorqueSpec ensures that a TorqueBox server is running and enables you to verify expectations against real applications deployed on it.

Easy browser control/simulation is possible via the capybara or webrat gems, of course, but TorqueSpec also provides “in-container” testing, where your examples are actually run within the TorqueBox server itself.


Install the torquespec gem:

$ gem install torquespec

And then in your spec files (or indirectly via spec_helper.rb):

require 'torquespec'

Doing this will cause TorqueSpec to add a “before suite” hook that fires up a TorqueBox server, i.e. JBoss, prior to running your specs and an “after suite” hook to shut it down.

RSpec extensions

Aiming to be minimally intrusive, TorqueSpec makes two new methods available to your spec files: deploy and remote_describe.


Determines which app[s] are deployed prior to running a particular ExampleGroup, so typically called from a top-level describe block. The deployment and subsequent undeployment occur within “before all” and “after all” RSpec hooks, respectively.

The method accepts any number of arguments, each of which should represent a TorqueBox deployment descriptor, typically a YAML “here document”, a Hash, or a path to an existing file. It also accepts a block, the result of which should also be one or more deployment descriptors. Here’s an example using a single here doc:

describe "basic test with heredoc" do

  deploy <<-DD_END.gsub(/^ {4}/,'')
      root: #{File.dirname(__FILE__)}/../app
      env: development
      context: /basic

  it "should work" do
    visit "/basic"
    page.should have_content('it worked')
    page.find("#success")[:class].should == 'basic'


Here docs are especially nice because they support string substitution. Note that we’re setting the location of the app relative to the location of the spec file itself, e.g. __FILE__. And the little gsub(/^ {4},'') trick allows you to indent the YAML relative to the Ruby.


TorqueSpec supports “in container” testing via the remote_describe method. It behaves exactly like the RSpec describe method, but the resulting ExampleGroup will be run inside the TorqueBox server, which is remote relative to the local RSpec process.

If your spec calls remote_describe, TorqueSpec will deploy a small daemon with your application. This daemon will act as an additional RSpec runner to which the “local” runner will delegate the invocation of those ExampleGroups defined by remote_describe. This delegation occurs via DRb: the “remote” runner reports its results to the “local” one, allowing you to summarize the results of all your tests, both in-container and out, in a single report.

Because your specs are consumed by two separate RSpec processes, you must ensure that any gems other than TorqueSpec/RSpec are available to the process that needs them.

require 'torquespec'
require 'torquebox-core'

TorqueSpec.local {
  require 'capybara'

app = <<-END.gsub(/^ {4}/,'')
      root: #{File.dirname(__FILE__)}/../app

describe "local test" do

  it "should work" do
    visit "/"
    page.should have_content('it worked')

remote_describe "remote test" do
  include TorqueBox::Injectors

  it "should work" do
    some_service = inject( == 'SUCCESS'

The above spec shows two example groups, one local and one remote. There are a few things to note:

  • This spec will be processed by both the local test runner and the remote daemon.
  • The local example needs the visit() method and page objects from capybara so its require statemtent is guarded in a TorqueSpec.local block, which won’t be run remotely, since the capybara won’t be available in the daemon’s runtime. Similarly, put statements that should only run remotely in a TorqueSpec.remote block.
  • TorqueBox injection is supported in remote examples as long as TorqueBox::Injectors is included in their group.
  • Because the remote_describe block is evaluated locally (but not executed), we must require ‘torquebox-core’ to refer to TorqueBox::Injectors both locally and remotely, even though the injection will only be performed remotely.

Nesting Example Groups

The above example is not very efficient because the same application is being deployed twice: once for the local describe and again for the remote_describe. We can do better by taking advantage of RSpec’s support for nested groups:

describe "outside the container" do

  before(:each) do
    puts "runs both locally and remotely"

  deploy <<-END.gsub(/^ {4}/,'')
      root: #{File.dirname(__FILE__)}/../app

  it "should handle web requests" do
    visit "/"

  remote_describe "inside the container" do

    before(:each) do
      puts "runs only remotely"

    it "should handle injection" do
      inject( 'service-registry' ).should_not be_nil



Example groups may be arbitrarily nested, but remember that ALL subgroups of a remote_describe will be executed remotely by the TorqueSpec daemon.

Also note that before and after blocks should work as you expect, but the fact that the parent’s before block in the above example will run remotely might mean you’ll need to guard certain statements in either a TorqueSpec.local or TorqueSpec.remote block.


Configuration parameters are variables in the TorqueSpec namespace, e.g. TorqueSpec.max_heap.

knob_rootWhere TorqueSpec creates your deployment descriptors.torquespec
jboss_homeWhere JBoss is installed$JBOSS_HOME
max_heapThe maximum RAM allocated to the JBoss JVM1024 MB
jvm_argsArguments to the JVM running JBosssee below
drb_portThe in-container spec runner listens on this port for requests7772
lazyWhether to use a running JBoss and leave it running when donefalse

By default, TorqueSpec is initialized thusly:

TorqueSpec.configure do |config|
  config.drb_port = 7772
  config.knob_root = ".torquespec"
  config.jvm_args = "-Xms64m -Xmx1024m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -Dgem.path=default"

Include a similar block in your spec_helper.rb to customize any of these.


TorqueSpec has been extensively tested with RSpec 2, though RSpec 1 should be compatible as well. But really, why are you still using RSpec 1?