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.
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.
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).
The RhoConnect Source Adapter Model Test API provides the following methods to perform spec tests.
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')
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" } }
Returns any errors stored in redis for the previous model’s query.
For example:
{ "query-error" => { "message" => "error connecting to web service!" } }
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: :::ruby @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: :::ruby @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
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: :::ruby record = {‘4’=> { ‘price’ => ‘199.99’ }} @s.pass_through = ‘true’ test_update(record).should == {‘processed’ => [“4”]}.to_json
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
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" } }
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