Hi I''ve spec''d a class and they pass. Now I''d like to assure that any subclass of this class also passes the same specs. Any suggestions for a clever way to handle this? I''d prefer to keep the existing specs as is (eg instead of moving everything into shared behaviors, or doing something to all the ''describe'' lines) thanks linoj
On Jan 22, 2008 10:49 PM, Jonathan Linowes <jonathan at parkerhill.com> wrote:> Hi > > I''ve spec''d a class and they pass. > > Now I''d like to assure that any subclass of this class also passes > the same specs. > Any suggestions for a clever way to handle this? > I''d prefer to keep the existing specs as is (eg instead of moving > everything into shared behaviors, or doing something to all the > ''describe'' lines)How about: [Subclass1, Subclass2, BaseClass].each do |klass| describe klass do ... end end> > thanks > > linoj > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > rubyforge.org/mailman/listinfo/rspec-users >
cool thx :) On Jan 23, 2008, at 12:02 AM, David Chelimsky wrote:> On Jan 22, 2008 10:49 PM, Jonathan Linowes > <jonathan at parkerhill.com> wrote: >> Hi >> >> I''ve spec''d a class and they pass. >> >> Now I''d like to assure that any subclass of this class also passes >> the same specs. >> Any suggestions for a clever way to handle this? >> I''d prefer to keep the existing specs as is (eg instead of moving >> everything into shared behaviors, or doing something to all the >> ''describe'' lines) > > How about: > > [Subclass1, Subclass2, BaseClass].each do |klass| > describe klass do > ... > end > end > >> >> thanks >> >> linoj >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> rubyforge.org/mailman/listinfo/rspec-users >> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > rubyforge.org/mailman/listinfo/rspec-users
On Jan 23, 2008, at 12:02 AM, David Chelimsky wrote:> On Jan 22, 2008 10:49 PM, Jonathan Linowes > <jonathan at parkerhill.com> wrote: >> Hi >> >> I''ve spec''d a class and they pass. >> >> Now I''d like to assure that any subclass of this class also passes >> the same specs. >> Any suggestions for a clever way to handle this? >> I''d prefer to keep the existing specs as is (eg instead of moving >> everything into shared behaviors, or doing something to all the >> ''describe'' lines) > > How about: > > [Subclass1, Subclass2, BaseClass].each do |klass| > describe klass do > ... > end > endThat''s sort of funny, being that I posted this solution on Courtney''s blog yesterday. Is this what you actually use in this sort of situations? Are there other (better, or worse) alternatives? Scott
On Jan 23, 2008 12:04 AM, Scott Taylor <mailing_lists at railsnewbie.com> wrote:> > On Jan 23, 2008, at 12:02 AM, David Chelimsky wrote: > > > On Jan 22, 2008 10:49 PM, Jonathan Linowes > > <jonathan at parkerhill.com> wrote: > >> Hi > >> > >> I''ve spec''d a class and they pass. > >> > >> Now I''d like to assure that any subclass of this class also passes > >> the same specs. > >> Any suggestions for a clever way to handle this? > >> I''d prefer to keep the existing specs as is (eg instead of moving > >> everything into shared behaviors, or doing something to all the > >> ''describe'' lines) > > > > How about: > > > > [Subclass1, Subclass2, BaseClass].each do |klass| > > describe klass do > > ... > > end > > end > > That''s sort of funny, being that I posted this solution on Courtney''s > blog yesterday.I saw that. I''ve also done this before :)> Is this what you actually use in this sort of situations? Are there > other (better, or worse) alternatives?I usually stick w/ shared example groups, but I sometimes use an iterator like this. Not sure why. I''ll think about it. Cheers, David> > Scott > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > rubyforge.org/mailman/listinfo/rspec-users >
On Jan 22, 2008 10:26 PM, David Chelimsky <dchelimsky at gmail.com> wrote:> On Jan 23, 2008 12:04 AM, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > On Jan 23, 2008, at 12:02 AM, David Chelimsky wrote: > > > > > On Jan 22, 2008 10:49 PM, Jonathan Linowes > > > <jonathan at parkerhill.com> wrote: > > >> Hi > > >> > > >> I''ve spec''d a class and they pass. > > >> > > >> Now I''d like to assure that any subclass of this class also passes > > >> the same specs. > > >> Any suggestions for a clever way to handle this? > > >> I''d prefer to keep the existing specs as is (eg instead of moving > > >> everything into shared behaviors, or doing something to all the > > >> ''describe'' lines) > > > > > > How about: > > > > > > [Subclass1, Subclass2, BaseClass].each do |klass| > > > describe klass do > > > ... > > > end > > > end > > > > That''s sort of funny, being that I posted this solution on Courtney''s > > blog yesterday. > > I saw that. I''ve also done this before :) > > > Is this what you actually use in this sort of situations? Are there > > other (better, or worse) alternatives? > > I usually stick w/ shared example groups, but I sometimes use an > iterator like this. Not sure why. I''ll think about it.I think using an iterator here is weird, and muddles the intent of the specs. Think of what it means to define a class and a subclass. class Foo ... some behavior ... end class Bar < Foo ... all of Foo''s behavior ... ... some specialized behavior ... end You don''t define all the behavior in Bar - you get a bunch of it from Foo for free, and then specialize whatever you need. Your specs should be similar in spirit. shared_examples_for("the foo role") do it "should have some behavior" ... end describe Bar do it_should_behave_like "the foo role" it "should have some specialized behavior" ... end That is far more clear to me. The downside is that you also end up with On Jan 22, 2008 10:26 PM, David Chelimsky <dchelimsky at gmail.com> wrote:> On Jan 23, 2008 12:04 AM, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > On Jan 23, 2008, at 12:02 AM, David Chelimsky wrote: > > > > > On Jan 22, 2008 10:49 PM, Jonathan Linowes > > > <jonathan at parkerhill.com> wrote: > > >> Hi > > >> > > >> I''ve spec''d a class and they pass. > > >> > > >> Now I''d like to assure that any subclass of this class also passes > > >> the same specs. > > >> Any suggestions for a clever way to handle this? > > >> I''d prefer to keep the existing specs as is (eg instead of moving > > >> everything into shared behaviors, or doing something to all the > > >> ''describe'' lines) > > > > > > How about: > > > > > > [Subclass1, Subclass2, BaseClass].each do |klass| > > > describe klass do > > > ... > > > end > > > end > > > > That''s sort of funny, being that I posted this solution on Courtney''s > > blog yesterday. > > I saw that. I''ve also done this before :) > > > Is this what you actually use in this sort of situations? Are there > > other (better, or worse) alternatives? > > I usually stick w/ shared example groups, but I sometimes use an > iterator like this. Not sure why. I''ll think about it.I think using an iterator here is weird, and muddles the intent of the specs. Think of what it means to define a class and a subclass. class Foo ... some behavior ... end class Bar < Foo ... all of Foo''s behavior ... ... some specialized behavior ... end You don''t define all the behavior in Bar - you get a bunch of it from Foo for free, and then specialize whatever you need. Your specs should be similar in spirit. shared_examples_for("the foo role") do it "should have some behavior" ... end The downside is you end up with describe Foo do it_should_behave_like "the foo role" end to specify the behavior, which feels pretty weak to me. Though I assume you feel somewhat similarly, so I''d be interested to know when you use an iterator for full example groups. Actually one example I remember is when I wrote a macro that added a bunch of methods to a class...I wrote the initial example group for just one attribute name. Then when I extracted the macro, I just iterated through a bunch of names over the example group. So it can be useful. Although a whole class feels too coarse grained for that approach, to me. I do use iterators a bunch for stuff like [:name, :email, :phone, :address].each do |field| it "should require a #{field}" do u = build_user(field => nil) u.should_not be_valid u.should have(1).error_on(field) end end Also, since I''m close to the subject, here''s a little tip. I''ve seen people write specs like: it "should require valid attributes" do [:name, :email, :phone, :address].each do |field| u = build_user(field => nil) u.should_not be_valid u.should have(1).error_on(field) end end but that sucks, because if the example fails, you don''t have any clue why. Cause it''ll just say that user is invalid, but doesn''t tell you which field is blank. That was a bit of a tangent. It''s late, I''m loopy :) Pat
On Jan 24, 2008, at 4:36 AM, Pat Maddox wrote:> > On Jan 22, 2008 10:26 PM, David Chelimsky <dchelimsky at gmail.com> > wrote: >> On Jan 23, 2008 12:04 AM, Scott Taylor >> <mailing_lists at railsnewbie.com> wrote: >>> >>> On Jan 23, 2008, at 12:02 AM, David Chelimsky wrote: >>> >>>> On Jan 22, 2008 10:49 PM, Jonathan Linowes >>>> <jonathan at parkerhill.com> wrote: >>>>> Hi >>>>> >>>>> I''ve spec''d a class and they pass. >>>>> >>>>> Now I''d like to assure that any subclass of this class also passes >>>>> the same specs. >>>>> Any suggestions for a clever way to handle this? >>>>> I''d prefer to keep the existing specs as is (eg instead of moving >>>>> everything into shared behaviors, or doing something to all the >>>>> ''describe'' lines) >>>> >>>> How about: >>>> >>>> [Subclass1, Subclass2, BaseClass].each do |klass| >>>> describe klass do >>>> ... >>>> end >>>> end >>> >>> That''s sort of funny, being that I posted this solution on >>> Courtney''s >>> blog yesterday. >> >> I saw that. I''ve also done this before :) >> >>> Is this what you actually use in this sort of situations? Are there >>> other (better, or worse) alternatives? >> >> I usually stick w/ shared example groups, but I sometimes use an >> iterator like this. Not sure why. I''ll think about it. > > I think using an iterator here is weird, and muddles the intent of > the specs. > > Think of what it means to define a class and a subclass. > > class Foo > ... some behavior ... > end > > class Bar < Foo > ... all of Foo''s behavior ... > ... some specialized behavior ... > end > > You don''t define all the behavior in Bar - you get a bunch of it from > Foo for free, and then specialize whatever you need. Your specs > should be similar in spirit.In a normal setting, I''d agree with you. In the case where I used it, there was STI involved, and the subclasses had almost no unique behaviour (except one or two methods which were over-ridden).> > shared_examples_for("the foo role") do > it "should have some behavior" > ... > end > > The downside is you end up with > > describe Foo do > it_should_behave_like "the foo role" > end > > to specify the behavior, which feels pretty weak to me.The trouble with the shared specs is that you have to do the same setup multiple times, in various specs.> > Though I assume you feel somewhat similarly, so I''d be interested to > know when you use an iterator for full example groups. > > Actually one example I remember is when I wrote a macro that added a > bunch of methods to a class...I wrote the initial example group for > just one attribute name. Then when I extracted the macro, I just > iterated through a bunch of names over the example group. So it can > be useful. Although a whole class feels too coarse grained for that > approach, to me. > > I do use iterators a bunch for stuff like > > [:name, :email, :phone, :address].each do |field| > it "should require a #{field}" do > u = build_user(field => nil) > u.should_not be_valid > u.should have(1).error_on(field) > end > end > > Also, since I''m close to the subject, here''s a little tip. I''ve seen > people write specs like: > > it "should require valid attributes" do > [:name, :email, :phone, :address].each do |field| > u = build_user(field => nil) > u.should_not be_valid > u.should have(1).error_on(field) > end > end > > but that sucks, because if the example fails, you don''t have any clue > why. Cause it''ll just say that user is invalid, but doesn''t tell you > which field is blank.Yeah, I agree. It''s also violating the one test per test case rule. If you had ordered the tests in the opposite manner, it wouldn''t be a problem. I usually still use valid?, even though it''s less informative, since I let FixtureReplacement take care of making it a valid record in the first place: it "should not be valid with a firstname" do new_user(:firstname => nil).should_not be_valid end it "should be valid with valid attributes" do new_user.should be_valid end Scott