Jamie D
2008-Apr-15 01:58 UTC
[rspec-users] rspec test for converting a hash to a URL string
Hi all, I''ve written an expectation for a method that converts a hash into a url string of name/value pairs. The problem is that the hash is not traversed in the same order as it is defined so I can not work out how to test for the correct returned string. The operation of the code does not require and specific order so I am not going to add a specific order to my method. # test def mappings_data { :shell => true, :ftp => 10, :sql => 11, :email => 12, :subdomains => 13, :parkeddomains => 14, :addondomains => 15, :transfer => 16 } end it "should map arguments to a url" do @whm.map_args_to_url(mappings_data).should eql("?shell=true&ftp=10&sql=11&email=12&subdomains=13&parkeddomains=14&addondomains=15&transfer=16") end # implementation def map_args_to_url(args={}) ''?'' + args.map { |k,v| "%s=%s" % [URI.encode(k.to_s), URI.encode(v.to_s)] }.join(''&'') unless args.blank? end # string that is returned "?parkeddomains=14&shell=true&email=12&addondomains=15&ftp=10&subdomains=13&transfer=16&sql=11"
Pat Maddox
2008-Apr-15 02:33 UTC
[rspec-users] rspec test for converting a hash to a URL string
On Mon, Apr 14, 2008 at 6:58 PM, Jamie D <jam5t3r.lists at gmail.com> wrote:> Hi all, I''ve written an expectation for a method that converts a hash > into a url string of name/value pairs. The problem is that the hash is > not traversed in the same order as it is defined so I can not work out > how to test for the correct returned string. The operation of the code > does not require and specific order so I am not going to add a > specific order to my method. > > > # test > def mappings_data > { > :shell => true, > :ftp => 10, > :sql => 11, > :email => 12, > :subdomains => 13, > :parkeddomains => 14, > :addondomains => 15, > :transfer => 16 > } > end > > it "should map arguments to a url" do > @whm.map_args_to_url(mappings_data).should > eql("?shell=true&ftp=10&sql=11&email=12&subdomains=13&parkeddomains=14&addondomains=15&transfer=16") > end > > # implementation > def map_args_to_url(args={}) > ''?'' + args.map { |k,v| "%s=%s" % [URI.encode(k.to_s), > URI.encode(v.to_s)] }.join(''&'') unless args.blank? > end > > # string that is returned > "?parkeddomains=14&shell=true&email=12&addondomains=15&ftp=10&subdomains=13&transfer=16&sql=11" > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >You can use the CGI library to parse the query string, and verify that the hashes are equal. params = {:foo => true, :bar => 12} params_as_strings = {} params.each_key {|key| params_as_strings[key.to_s] = params[key].to_s } query_string = map_args_to_url params CGI.parse(query_string.delete("?")).should == params_as_strings (completely untested, so you''ll have to mess with it I''m sure) That''s a bit ugly and verbose, so it may be a good candidate for a custom matcher query_string.should equal_query_string("?foo=true&bar=12") The matcher would call CGI.parse on the actual and expected strings and verify that they are equal. Another thing that jumps out at me is that there may be a chance to build a QueryParams abstraction. So instead of the above expectation, you might do query_params.should == QueryParams.new(:foo => true, :bar => 12) (you would still have to write a spec verifying the QueryParams#to_s hash->string conversion of course) If all you''re doing at this point is building that string, then a QueryParams object is probably overkill. But I would be ready to move to it as soon as I started to do any more logic with the query string, such as asserting that it contains a certain key-value pair. Like I said at the beginning, this is probably a good situation for a custom expectation matcher to hide some of the messy details. Just keep in mind that the thresholds for creating a custom matcher and creating a new object are not that far apart, and creating a new object is generally way more valuable. (that was almost certainly a lot longer than you wanted, sorry. I''ve just been sick the last couple days and needed to scratch my list-writing itch :) Pat