Testing Your RhoConnect Application === RhoConnect provides a [spec](http://rspec.info/) framework for [behavior driven development](http://en.wikipedia.org/wiki/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 spec for the [rhostore product adapter](http://github.com/rhomobile/store-server/blob/master/sources/product.rb): :::ruby 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 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](http://github.com/rhomobile/store-server/blob/master/spec/sources/product_spec.rb). ## Running Specs From your application's root folder: :::term $ rake rhoconnect:spec [05:51:48 PM 2011-04-19] Rhoconnect Server v3.0.0 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 For the most up-to-date Test API, please see the [rdocs](http://rdoc.info/projects/rhomobile/rhoconnect). ### `setup_test_for(adapter,user_id)` Initializes the source adapter under test for a given user, typically in a before(:each) block :::ruby # 'testuser' will be used by rest of the specs setup_test_for(Product,'testuser') ### `test_query` Executes the adapter's query method and returns the master document (:md) stored in redis. For example, if your source adapter query method was: :::ruby def query(params=nil) @result = { "1" => { "name"=>"Acme", "industry"=>"Electronics"}, "2" => { "name"=>"Best", "industry"=>"Software" } } end `test_query` would return: :::ruby { "1" => { "name" => "Acme", "industry"=>"Electronics" }, "2" => { "name" => "Best", "industry" => "Software" } } ### `query_errors` Returns any errors stored in redis for the previous source adapter query. For example: :::ruby { "query-error" => { "message" => "error connecting to web service!" } } ### `test_create(record)` Execute's the adapter'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. This link can be tested here. 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](http://docs.rhomobile.com/rhoconnect/source-adapters#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 ### `create_errors` This will return the result of the adapter's create method. The master document (:md) should also contain the new record. Returns any errors stored in redis from the previous source adapter create (same structure as query errors). ### `test_update(record)` Execute the source adapter's update method. Takes a record as hash of hashes (object_id => object) For example: :::ruby test_update({'4' => {'price' => '$199.99'}}) update_errors.should == {} test_query md[product_id]['price'].should == '$199.99' This will call the adapter's update method for object_id '4'. **NOTE: To test the master document, you will need to run `test_query` as shown above.** If you have set [pass through](http://docs.rhomobile.com/rhoconnect/source-adapters#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 ### `update_errors` Returns any errors stored in redis from the previous source adapter update (same structure as query errors). ### `test_delete(record)` Execute the source adapter's delete method. Takes a record as hash of hashes (object_id => object). For example: :::ruby @product = { 'name' => 'iPhone', 'brand' => 'Apple', 'price' => '$299.99', 'quantity' => '5', 'sku' => '1234' } test_delete('4' => @product) delete_errors.should == {} md.should == {} This will call the adapter's delete method for product '4'. **NOTE: The master document (:md) will be updated and can be verified as shown above.** If you have set [pass through](http://docs.rhomobile.com/rhoconnect/source-adapters#pass-through) to true, the delete method will return a json hash of the object id deleted. For example, in your spec: :::ruby @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 ### `delete_errors` Returns any errors stored in redis from the previous source adapter delete (same structure as query errors). ### `md` Returns the master document (:md) for the source adapter stored in redis. This is equivalent to the @result hash of hashes structure. For example: :::ruby md.should == { "1" => { "name"=>"Acme", "industry"=>"Electronics" }, "2" => { "name"=>"Best", "industry"=>"Software" } } ### `cd` Returns the client document (:cd) for the source adapter + client under test. The master document (:md) and client document (:cd) should be equal after the query is executed. For example: :::ruby test_query.size.should > 0 md.should == cd