Testing Your RhoConnect Application

RhoConnect provides a spec framework for behavior driven development of your application. When your application and source adapters are generated, you will see spec files generated in the top-level ‘spec’ folder of your application.

Example Spec

Here is a simple example model spec for the rhostore product adapter:

it "should process Product query" do
  test_query.size.should > 0
  query_errors.should == {}
end

This simple spec runs the query method of our product adapter model and verifies the result is greater than one object and has no errors.

The full code listing for this product_spec is available on github.

Running Specs

From your application’s root folder:

$ rhoconnect spec
[05:51:48 PM 2012-04-19] Rhoconnect Server v4.0.1 started...
Product
  it should behave like SpecHelper
    should process Product query (PENDING: No reason given)
    should process Product create (PENDING: No reason given)
    should process Product update (PENDING: No reason given)
    should process Product delete (PENDING: No reason given)
Pending:
  Product it should behave like SpecHelper should process Product query
  Product it should behave like SpecHelper should process Product create
  Product it should behave like SpecHelper should process Product update
  Product it should behave like SpecHelper should process Product delete

Finished in 0.05877 seconds
4 examples, 0 failures, 4 pending

This will also automatically generate an rcov report under ‘coverage’ if you have rcov installed (currently only Mac/Linux support rcov).

Test API

The RhoConnect Source Adapter Model Test API provides the following methods to perform spec tests.

  • setup_test_for – Executes the adapter’s query method and returns the master document.
  • test_query – Executes the adapter’s query method and returns the master document.
  • query_errors – Returns any errors stored in redis for the previous source adapter query.
  • test_create – Executes the adapter’s create method with a provided record and returns the object string from the create method.
  • create_errors – Returns the result of the adapter’s create method..
  • test_update – Execute the source adapter’s update method.
  • update_errors – Returns any errors stored in redis from the previous source adapter update.
  • test_delete – Execute the source adapter’s delete method.
  • delete_errors – Returns any errors stored in redis from the previous source adapter delete.
  • md – Returns the master document (:md) for the source adapter stored in redis.
  • cd – Returns the client document (:cd) for the source adapter + client under test.

Example of setup_test_for

This example initializes a source adapter model named Product under test for a user named testuser.

# 'testuser' will be used by rest of the specs
setup_test_for(Product,'testuser') 

Example of test_query

The test_query method executes the model’s query method and returns the master document (:md) stored in redis.

For example, if your source adapter query method was:

def query(params=nil)
  @result = { 
    "1" => { 
      "name"=>"Acme", 
      "industry"=>"Electronics"},
    "2" => { 
      "name"=>"Best", 
      "industry"=>"Software"
    }
  }
end

test_query would return:

{ 
  "1" => { 
    "name" => "Acme", 
    "industry"=>"Electronics"
  },
  "2" => { 
    "name" => "Best", 
    "industry" => "Software"
  }
}

Example of query_errors

Returns any errors stored in redis for the previous model’s query.

For example:

{ 
  "query-error" => {
      "message" => "error connecting to web service!"
  }
}

Example of test_create

The test_create method executes the model’s create method with a provided record and returns the object string from the create method. If the create method returns a string, then a link will be saved for the device next time it synchronizes.

For example, in your spec:

@product = {
  'name' => 'iPhone',
  'brand' => 'Apple',
  'price' => '$299.99',
  'quantity' => '5',
  'sku' => '1234'
}
new_product_id = test_create(@product)
create_errors.should == {}
md[new_product_id].should == @product

If you have set pass through to true, the create method will not return a string but instead a json hash of the object ids created. When testing the id will always be set to ‘temp_id’.

For example, in your spec:

@product = {
  'name' => 'iPhone',
  'brand' => 'Apple',
  'price' => '$299.99',
  'quantity' => '5',
  'sku' => '1234'
}
@s.pass_through = 'true'
new_product = test_create(@product)
new_product.should == {'processed' => ["temp-id"]}.to_json

Example of test_update

This example executes the model’s update method, calling the adapter’s update method for object_id ‘4’.

test_update({'4' => {'price' => '$199.99'}})
update_errors.should == {}
test_query
md[product_id]['price'].should == '$199.99'

To test the master document, you will need to run test_query as shown above.

If you have set pass through to true, the update method will return a json hash of the object id updated.

For example, in your spec:

record = {'4'=> { 'price' => '199.99' }}
@s.pass_through = 'true'
test_update(record).should == {'processed' => ["4"]}.to_json

Example of test_delete

This example executes the source model’s delete method, calling the adapter’s delete method for product ‘4’.

@product = {
  'name' => 'iPhone',
  'brand' => 'Apple',
  'price' => '$299.99',
  'quantity' => '5',
  'sku' => '1234'
}
test_delete('4' => @product)
delete_errors.should == {}
md.should == {}

The master document (:md) will be updated and can be verified as shown above.

If you have set pass through to true, the delete method will return a json hash of the object id deleted. You could have the following code in your spec.

@product = {
  'name' => 'iPhone',
  'brand' => 'Apple',
  'price' => '$299.99',
  'quantity' => '5',
  'sku' => '1234'
}
record = {'4'=> { 'price' => '199.99' }}
@s.pass_through = 'true'
test_update(record).should == {'processed' => ["4"]}.to_json

Example of md

The md method returns the master document (:md) for the source adapter model stored in redis. This is equivalent to the @result hash of hashes structure.

md.should == { 
  "1" => { 
    "name"=>"Acme", 
    "industry"=>"Electronics"
  },
  "2" => { 
    "name"=>"Best", 
    "industry"=>"Software"
  }
}

Example of cd

This example shows that the master document (:md) and client document (:cd) should be equal after the query is executed.

test_query.size.should > 0
md.should == cd
Back to Top