Rémi Gagnon
2008-Oct-28 14:52 UTC
[rspec-users] spec''ing the :conditions argument of a find
Let''s see, I want to spec the :conditions args to make sure the right args is passed to the query. Product.find(:all, :conditions => ["inte_no = ? and vaat_id_type_statut_pcpa = ?", inte_no, 7], :limit => 2, :order => "trns_dt_appl_prod desc") Product.should_receive(:find).with(:conditions => ''vaat_id_type_statut_pcpa == 7) I''m pretty sure this is not the right synthax. Any suggestions? R?mi -- Posted via http://www.ruby-forum.com/.
Nick Hoffman
2008-Oct-30 15:06 UTC
[rspec-users] spec''ing the :conditions argument of a find
On 2008-10-28, at 10:52, R?mi Gagnon wrote:> Let''s see, I want to spec the :conditions args to make sure the right > args is passed to the query. > > Product.find(:all, > :conditions => ["inte_no = ? and vaat_id_type_statut_pcpa = ?", > inte_no, 7], > :limit => 2, > :order => "trns_dt_appl_prod desc") > > > Product.should_receive(:find).with(:conditions => > ''vaat_id_type_statut_pcpa == 7) > > I''m pretty sure this is not the right synthax. > > Any suggestions? > > R?miHi R?mi. You have two options here: 1) Pass each argument to #with that #find receives; 2) Use #any_args to not specify some arguments that #find receives. I''d do something like this: find_conditions = [] find_conditions << "inte_no = ? and vaat_id_type_statut_pcpa = ?" find_conditions << inte_no find_conditions << 7 Product.should_receive(:find).with(:all, :conditions => find_conditions, :limit => 2, :order => ''trns_dt_appl_prod desc'' )
Pat Maddox
2008-Oct-30 15:33 UTC
[rspec-users] spec''ing the :conditions argument of a find
R?mi Gagnon <lists at ruby-forum.com> writes:> Let''s see, I want to spec the :conditions args to make sure the right > args is passed to the query. > > Product.find(:all, > :conditions => ["inte_no = ? and vaat_id_type_statut_pcpa = ?", > inte_no, 7], > :limit => 2, > :order => "trns_dt_appl_prod desc") > > > Product.should_receive(:find).with(:conditions => > ''vaat_id_type_statut_pcpa == 7) > > I''m pretty sure this is not the right synthax. > > Any suggestions? > > R?miewww......brittle, ugly, and not encapsulated. Why don''t you create a method to wrap this find? Product.find_thingy(1, 2). Then mocking becomes trivial and clean: Product.should_receive(:find_thingy).with(1,2) Pat
Rémi Gagnon
2008-Oct-30 15:41 UTC
[rspec-users] spec''ing the :conditions argument of a find
I do agree, That''s what we''re gonna do. it was just an example. But what if we want to test find_thingy(in model spec) to make sure the :conditions is set properly? R Pat Maddox wrote:> R?mi Gagnon <lists at ruby-forum.com> writes: > >> Product.should_receive(:find).with(:conditions => >> ''vaat_id_type_statut_pcpa == 7) >> >> I''m pretty sure this is not the right synthax. >> >> Any suggestions? >> >> R?mi > > ewww......brittle, ugly, and not encapsulated. Why don''t you create a > method to wrap this find? Product.find_thingy(1, 2). Then mocking > becomes trivial and clean: > Product.should_receive(:find_thingy).with(1,2) > > Pat-- Posted via http://www.ruby-forum.com/.
Zach Dennis
2008-Oct-30 15:58 UTC
[rspec-users] spec''ing the :conditions argument of a find
On Thu, Oct 30, 2008 at 11:41 AM, R?mi Gagnon <lists at ruby-forum.com> wrote:> I do agree, That''s what we''re gonna do. it was just an example. > But what if we want to test find_thingy(in model spec) to make sure the > :conditions is set properly?You are probably more interested in the fact that find_thingy works rather then it sets a bunch of conditions. Perhaps something like the below would work for you: it "can find things by blank and blank" do thing1 = Thing.create! :nte_no => 1, vaat_id_type_statut_pcpa => 2 thing2 = Thing.create! :nte_no => 2, vaat_id_type_statut_pcpa => 3 Thing.find_by_thingy(1,2).should == thing1 Thing.find_by_thingy(2,3).should == thing2 end If you have a way of generating "things" that are valid, then I''d use that mechanism and pass in the attributes you are specifically going to be testing against (so they stand out in the example that that''s what matters in the example). I know the above example breaks the one assertion per test guideline people strive to adhere to, but I think it is ok. If there are more examples that should be used to make sure find_thingy works then I''d break out a separate describe block and have multiple ''it'' examples, -- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20081030/94a6849f/attachment-0001.html>
Matt Wynne
2008-Oct-30 16:41 UTC
[rspec-users] spec''ing the :conditions argument of a find
On 30 Oct 2008, at 15:58, Zach Dennis wrote:> I know the above example breaks the one assertion per test guideline > people strive to adhere to, but I think it is ok. If there are more > examples that should be used to make sure find_thingy works then I''d > break out a separate describe block and have multiple ''it'' examples,It also goes to the database, which will make it a slow unit test. I personally do pretty much the same thing myself mostly when working with ActiveRecord, but it doesn''t mean I''m comfortable with it. (And it also doesn''t mean our unit test suite is anything other than shamefully slow) I did experiment with a QueryApapter for this purpose which has worked out quite well for us. You end up with code like this in the Controller: products = Product.find(:all, Product::QueryAdapter.new(params).adapt) You then have a QueryAdapter class to test which is solely responsible for mapping web query params into database query params - so that''s where you put the logic to build your conditions, your limit etc, and return them as a hash from QueryAdapter#adapt. The family of QueryAdapters then become the one place where I''m coupled to ActiveRecord''s find method arguments, which is nice, rather than having it sprinkled all over the controller code. HTH, Matt
Zach Dennis
2008-Oct-30 17:00 UTC
[rspec-users] spec''ing the :conditions argument of a find
On Thu, Oct 30, 2008 at 12:41 PM, Matt Wynne <matt at mattwynne.net> wrote:> On 30 Oct 2008, at 15:58, Zach Dennis wrote: > >> I know the above example breaks the one assertion per test guideline >> people strive to adhere to, but I think it is ok. If there are more >> examples that should be used to make sure find_thingy works then I''d break >> out a separate describe block and have multiple ''it'' examples, >> > > It also goes to the database, which will make it a slow unit test. I > personally do pretty much the same thing myself mostly when working with > ActiveRecord, but it doesn''t mean I''m comfortable with it. (And it also > doesn''t mean our unit test suite is anything other than shamefully slow)It will make it a *slower* unit test. I am yet to be convinced that when working with ActiveRecord, it is worthwhile to not hit the database when you trying to verify that custom queries are working correctly. I have yet to see model examples which were so slow I didn''t want to run them. I get more confidence and value out of knowing custom queries work at the model example level, rather than waiting for an acceptance test to trigger their failure. I do get value out of not hitting the database for things that I don''t need to hit it for, but custom finds aren''t one of those things IMO. It''s also easier to track down the failure and fix it at the model example level, rather than having to truck through acceptance test backtraces, log files, etc to find that you had a typo in your custom finder. For the record, my definition of custom apples to handcrafted SQL as well as handcrafted conditions, scopes, joins, etc that are used when creating find methods which encapsulate this logic (such as find_thingy 1, 2) -- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20081030/b8e37a96/attachment.html>
Pat Maddox
2008-Oct-30 20:11 UTC
[rspec-users] spec''ing the :conditions argument of a find
Matt Wynne <matt at mattwynne.net> writes:> On 30 Oct 2008, at 15:58, Zach Dennis wrote: >> I know the above example breaks the one assertion per test guideline >> people strive to adhere to, but I think it is ok. If there are more >> examples that should be used to make sure find_thingy works then I''d >> break out a separate describe block and have multiple ''it'' examples, > > It also goes to the database, which will make it a slow unit test. I > personally do pretty much the same thing myself mostly when working > with ActiveRecord, but it doesn''t mean I''m comfortable with it. (And > it also doesn''t mean our unit test suite is anything other than > shamefully slow) > > I did experiment with a QueryApapter for this purpose which has worked > out quite well for us. You end up with code like this in the > Controller:Scott is working on a SQL parser which would let you write tests that "hit" the db but keep everything in memory and fast. Might be worth checking out for you. Pat
Matt Wynne
2008-Oct-31 07:49 UTC
[rspec-users] spec''ing the :conditions argument of a find
On 30 Oct 2008, at 20:11, Pat Maddox wrote:> Matt Wynne <matt at mattwynne.net> writes: > >> On 30 Oct 2008, at 15:58, Zach Dennis wrote: >>> I know the above example breaks the one assertion per test guideline >>> people strive to adhere to, but I think it is ok. If there are more >>> examples that should be used to make sure find_thingy works then I''d >>> break out a separate describe block and have multiple ''it'' examples, >> >> It also goes to the database, which will make it a slow unit test. I >> personally do pretty much the same thing myself mostly when working >> with ActiveRecord, but it doesn''t mean I''m comfortable with it. (And >> it also doesn''t mean our unit test suite is anything other than >> shamefully slow) >> >> I did experiment with a QueryApapter for this purpose which has >> worked >> out quite well for us. You end up with code like this in the >> Controller: > > Scott is working on a SQL parser which would let you write tests that > "hit" the db but keep everything in memory and fast. Might be worth > checking out for you.Sounds interesting. I''d still like to see us have a proper ORM for ruby that lets us play with POROs 90% of the time, and just have a separate suite of tests for the database-object mappings that we run when necessary. cheers, Matt
Ashley Moran
2008-Oct-31 08:24 UTC
[rspec-users] spec''ing the :conditions argument of a find
On Oct 31, 2008, at 7:49 am, Matt Wynne wrote:>>> It also goes to the database, which will make it a slow unit test. I >>> personally do pretty much the same thing myself mostly when working >>> with ActiveRecord, but it doesn''t mean I''m comfortable with it. (And >>> it also doesn''t mean our unit test suite is anything other than >>> shamefully slow) > > <snip> > > Sounds interesting. I''d still like to see us have a proper ORM for > ruby that lets us play with POROs 90% of the time, and just have a > separate suite of tests for the database-object mappings that we run > when necessary.I''m using DataMapper in a (non-web) project I have on now, and for part of the spec suite where I am concerned with persistence as a black-box, I create an in-memory SQLite database: # story_spec.rb describe "Class", Story do # ... describe ".unposted" do include InMemoryDatabase before(:each) do setup_in_memory_database @twitter_client = mock(TwitterAgent::Client, :post_story => true) @story_1 = Story.create(:title => "Story title 1", :published_at => DateTime.new(2008, 9, 28)) @story_2 = Story.create(:title => "Story title 2", :published_at => DateTime.new(2008, 9, 29)) @story_3 = Story.create(:title => "Story title 3", :published_at => DateTime.new(2008, 9, 27)) end it "should find all stories (in ascending published date) when none have been posted" do Story.unposted.should == [ @story_3, @story_1, @story_2 ] end it "should find only unpublished stories (in ascending published date)" do @story_1.post_to_twitter!(@twitter_client) Story.unposted.should == [ @story_3, @story_2 ] end end end # spec_helper.rb module InMemoryDatabase def setup_in_memory_database DataMapper.setup(:default, "sqlite3::memory:") Database::Migrator.new.reset_database! end end Aside from being unable to use DB-lever constraints, that gives me enough confidence in the persistence. Other specs that don''t need persistence simply omit the "setup_in_memory_database" call. It''s important not to lose sight of the fact that, even though ActiveRecord mixes business logic and persistence, *they are still separate concerns*. Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/