Piotr Wlodarek
2008-Jul-15 09:17 UTC
[rspec-users] How to write specification for the *base* class API?
For the base class, it seems reasonable to specify public API with RSpec. However, since we deal with a base class, methods are often empty (put there just to show the API). The spec cannot be run against the base class. In consequence, the spec must be duplicated in every derived class, which seems to be far from DRY. How to deal with it? What is THE RSpec way to specify APIs when we face inheritance? -- Posted via http://www.ruby-forum.com/.
David Chelimsky
2008-Jul-15 12:23 UTC
[rspec-users] How to write specification for the *base* class API?
On Tue, Jul 15, 2008 at 4:17 AM, Piotr Wlodarek <lists at ruby-forum.com> wrote:> For the base class, it seems reasonable to specify public API with > RSpec. > > However, since we deal with a base class, methods are often empty (put > there just to show the API). > > The spec cannot be run against the base class. In consequence, the spec > must be duplicated in every derived class, which seems to be far from > DRY. > > How to deal with it? What is THE RSpec way to specify APIs when we face > inheritance?This is more a theoretical TDD/BDD question than an RSpec question. There are a few schools of thought about this, so I''d recommend checking out the testdrivendevelopment list at yahoo as well - but I''ll give you my two cents :) Any subclass can override any method in the base class, so it is not sufficient to have examples of just the base class, nor is it very helpful to have examples for empty methods just for show if the intent is that the base class will never get initialized directly. If you''re deriving objects from the base class, write examples for the derived classes. If all derived classes are intended to pass the same examples with the same input/output expectations, then you can write shared examples and run them against instances of all the derived classes, thus satisfying your quest for DRY. HTH, David
Pat Maddox
2008-Jul-15 12:47 UTC
[rspec-users] How to write specification for the *base* class API?
On Tue, Jul 15, 2008 at 5:17 AM, Piotr Wlodarek <lists at ruby-forum.com> wrote:> For the base class, it seems reasonable to specify public API with > RSpec. > > However, since we deal with a base class, methods are often empty (put > there just to show the API).What''s the point of that? This isn''t Java.> The spec cannot be run against the base class. In consequence, the spec > must be duplicated in every derived class, which seems to be far from > DRY.Presumably the derived classes have different implementations, so you would need to spec them out differently. If the implementations are the same, shared behaviors are often useful. Pat
Bart Zonneveld
2008-Jul-15 12:58 UTC
[rspec-users] How to write specification for the *base* class API?
On 15-jul-2008, at 14:47, Pat Maddox wrote:> On Tue, Jul 15, 2008 at 5:17 AM, Piotr Wlodarek <lists at ruby- > forum.com> wrote: >> For the base class, it seems reasonable to specify public API with >> RSpec. >> >> However, since we deal with a base class, methods are often empty >> (put >> there just to show the API). > > What''s the point of that? This isn''t Java.Exactly. In all of my projects, I only have an inheritance tree of at most 3 levels deep. AR::Base -> Generic -> Specific model. If there are more than three levels, something might not be okay with the design of your app. Of course your mileage may vary, but I think a lot of developers will agree on this subject.>> The spec cannot be run against the base class. In consequence, the >> spec >> must be duplicated in every derived class, which seems to be far from >> DRY. > > Presumably the derived classes have different implementations, so you > would need to spec them out differently. > > If the implementations are the same, shared behaviors are often > useful.
Piotr Wlodarek
2008-Jul-15 13:22 UTC
[rspec-users] How to write specification for the *base* class API?
>> However, since we deal with a base class, methods are often empty >> (put there just to show the API).> What''s the point of that? This isn''t Java.Documentation for developers of derived classes.> Exactly. In all of my projects, I only have an inheritance tree of > at most 3 levels deep.It''s not AR. I have 2 levels: Site1Scraper < BaseScraper. There will be many SiteXScrapers implemented by several people. ++++>From your answers I conclude it''s not possible (or at least notrecommended) to document abstract interface with RSpec. -- Posted via http://www.ruby-forum.com/.
Zach Dennis
2008-Jul-15 13:24 UTC
[rspec-users] How to write specification for the *base* class API?
On Tue, Jul 15, 2008 at 8:47 AM, Pat Maddox <pergesu at gmail.com> wrote:> On Tue, Jul 15, 2008 at 5:17 AM, Piotr Wlodarek <lists at ruby-forum.com> > wrote: > > For the base class, it seems reasonable to specify public API with > > RSpec. > > > > However, since we deal with a base class, methods are often empty (put > > there just to show the API). > > What''s the point of that? This isn''t Java. > >Readability I would assume. Rspec does this in the base_formatter.rb and Rails does this in some places as well I have noticed. -- Zach Dennis http://www.continuousthinking.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20080715/ab3a48d7/attachment.html>
David Chelimsky
2008-Jul-15 13:51 UTC
[rspec-users] How to write specification for the *base* class API?
On Jul 15, 2008, at 8:22 AM, Piotr Wlodarek <lists at ruby-forum.com> wrote:>>> However, since we deal with a base class, methods are often empty >>> (put there just to show the API). > >> What''s the point of that? This isn''t Java. > > Documentation for developers of derived classes. > > >> Exactly. In all of my projects, I only have an inheritance tree of >> at most 3 levels deep. > > It''s not AR. I have 2 levels: Site1Scraper < BaseScraper. > > There will be many SiteXScrapers implemented by several people. > > ++++ > >> From your answers I conclude it''s not possible (or at least not > recommended) to document abstract interface with RSpec.If everyone gave up that easily we''d never improve anything ;) Not sure how you get to "not possible." Pat suggested shared examples, which would be a perfectly good solution for part of the problem. I think the question is what are you trying to acheive here and whether Rspec (or any testing framework) is the right place for that goal.
Piotr Wlodarek
2008-Jul-15 14:10 UTC
[rspec-users] How to write specification for the *base* class API?
David Chelimsky wrote:> On Jul 15, 2008, at 8:22 AM, Piotr Wlodarek <lists at ruby-forum.com> > wrote: > >> >> It''s not AR. I have 2 levels: Site1Scraper < BaseScraper. >> >> There will be many SiteXScrapers implemented by several people. >> >> ++++ >> >>> From your answers I conclude it''s not possible (or at least not >> recommended) to document abstract interface with RSpec. > > If everyone gave up that easily we''d never improve anything ;) > > Not sure how you get to "not possible." Pat suggested shared examples, > which would be a perfectly good solution for part of the problem. > > I think the question is what are you trying to acheive here and > whether Rspec (or any testing framework) is the right place for that > goal.I try to document public API of important base class. Shared examples, as you said, solve part of the problem. Since I try to develop this project in a BDD style, and specifications are said to be - among other things - a documentation tool, it seems reasonable to take advantage of it. Alternative is mixed documentation of rdoc + specs. In a perfect world I would expect to have only one documentation tool: specs. -- Posted via http://www.ruby-forum.com/.
Bart Zonneveld
2008-Jul-15 14:16 UTC
[rspec-users] How to write specification for the *base* class API?
On 15-jul-2008, at 15:22, Piotr Wlodarek wrote:>>> However, since we deal with a base class, methods are often empty >>> (put there just to show the API). > >> What''s the point of that? This isn''t Java. > > Documentation for developers of derived classes. > > >> Exactly. In all of my projects, I only have an inheritance tree of >> at most 3 levels deep. > > It''s not AR. I have 2 levels: Site1Scraper < BaseScraper.Ok, but if a method is only in a BaseScraper for documentational purposes, eg, an empty body, should it be defined on that model at all? If it''s only going to be used on a Site1Scraper, leave it to that class to define and have it tested there. As far as I know there''s no useful implementation of an interface or an abstract class in ruby, but I could be wrong.> There will be many SiteXScrapers implemented by several people. > > ++++ > >> From your answers I conclude it''s not possible (or at least not > recommended) to document abstract interface with RSpec.
Pat Maddox
2008-Jul-15 14:24 UTC
[rspec-users] How to write specification for the *base* class API?
On Tue, Jul 15, 2008 at 10:10 AM, Piotr Wlodarek <lists at ruby-forum.com> wrote:> David Chelimsky wrote: >> On Jul 15, 2008, at 8:22 AM, Piotr Wlodarek <lists at ruby-forum.com> >> wrote: >> >>> >>> It''s not AR. I have 2 levels: Site1Scraper < BaseScraper. >>> >>> There will be many SiteXScrapers implemented by several people. >>> >>> ++++ >>> >>>> From your answers I conclude it''s not possible (or at least not >>> recommended) to document abstract interface with RSpec. >> >> If everyone gave up that easily we''d never improve anything ;) >> >> Not sure how you get to "not possible." Pat suggested shared examples, >> which would be a perfectly good solution for part of the problem. >> >> I think the question is what are you trying to acheive here and >> whether Rspec (or any testing framework) is the right place for that >> goal. > > I try to document public API of important base class. > > Shared examples, as you said, solve part of the problem. > > Since I try to develop this project in a BDD style, and specifications > are said to be - among other things - a documentation tool, it seems > reasonable to take advantage of it. Alternative is mixed documentation > of rdoc + specs. > > In a perfect world I would expect to have only one documentation tool: > specs.I think in this case you could provide contract tests. These would be shared behaviors that developers can mix in to their own specs. Consider something basic for an account: describe "account", :shared => true do it "should increase in balance after a deposit" do start_balance = account.balance account.deposit 100 account.balance.should > start_balance end it "should decrease in balance after a withdrawal" do start_balance = account.balance account.withdraw 100 account.balance.should < start_balance end end This defines the contract of an Account abstraction... you can imagine different account types that might implement it in a way that the actual dollar values differ. For example, fees may be applied to one kind of account but not another. Anyone who implements your API can include that shared example group and verify their code against the contract you''ve defined. Pat
Piotr Wlodarek
2008-Jul-16 05:14 UTC
[rspec-users] How to write specification for the *base* class API?
Pat Maddox wrote:> On Tue, Jul 15, 2008 at 10:10 AM, Piotr Wlodarek <lists at ruby-forum.com> > wrote: >>>> >>> goal. >> In a perfect world I would expect to have only one documentation tool: >> specs. > > I think in this case you could provide contract tests. These would be > shared behaviors that developers can mix in to their own specs. > Consider something basic for an account:Thanks for the example. It carifies the issue. I will try it. ++++ BTW, do you think it''s worthwile to replace most of rdoc and other documentation with specs? RSpec itself comes with nice RDoc, so perhaps I want too much? -- Posted via http://www.ruby-forum.com/.
Ashley Moran
2008-Jul-16 20:47 UTC
[rspec-users] How to write specification for the *base* class API?
On Jul 15, 2008, at 3:24 pm, Pat Maddox wrote:> This defines the contract of an Account abstraction... you can imagine > different account types that might implement it in a way that the > actual dollar values differ. For example, fees may be applied to one > kind of account but not another. > > Anyone who implements your API can include that shared example group > and verify their code against the contract you''ve defined.Hi Pat This sounds like a brilliant idea - I''ve wanted so often to be able to mix in specs for AR::Base for example. BUT - would it encourage programming by inheritance, rather than message passing? Often it feels unnatural to subclass *someone else''s* library class and use it in *my* application. Subclassing a library class to pass back into the library doesn''t bother me. For some reason it feels normal to subclass a controller class but not an ORM class. Perhaps because a controller is just a strategy for handling requests, and not something you instantiate and manipulate yourself, whereas an AR model class has business logic (handled by the app) and persistence (handled by the framework) rolled into one? WDYT? Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/
Pat Maddox
2008-Jul-17 18:27 UTC
[rspec-users] How to write specification for the *base* class API?
On Wed, Jul 16, 2008 at 4:47 PM, Ashley Moran <ashley.moran at patchspace.co.uk> wrote:> > On Jul 15, 2008, at 3:24 pm, Pat Maddox wrote: > >> This defines the contract of an Account abstraction... you can imagine >> different account types that might implement it in a way that the >> actual dollar values differ. For example, fees may be applied to one >> kind of account but not another. >> >> Anyone who implements your API can include that shared example group >> and verify their code against the contract you''ve defined. > > > Hi Pat > > This sounds like a brilliant idea - I''ve wanted so often to be able to mix > in specs for AR::Base for example. BUT - would it encourage programming by > inheritance, rather than message passing? Often it feels unnatural to > subclass *someone else''s* library class and use it in *my* application. > Subclassing a library class to pass back into the library doesn''t bother > me. For some reason it feels normal to subclass a controller class but not > an ORM class. Perhaps because a controller is just a strategy for handling > requests, and not something you instantiate and manipulate yourself, whereas > an AR model class has business logic (handled by the app) and persistence > (handled by the framework) rolled into one? > > WDYT? > > AshleyWell, I don''t think people would fall into the trap of misusing inheritance if you don''t give them classes to inherit from :) The original post was about writing specs for base classes that have empty methods. The reason that he wanted to write these empty methods was to provide documentation for later programmers. If, however, you provided a set of specs that defined the expected contract, people could write whatever code they want and know that it should work within the framework - no inheritance required. And if the framework developer did want to provide existing behavior, he can do so by writing modules that people can mix into their own stuff. Now, this is speculation on my part, as I''ve never actually done this. But I like the idea of taking DBC ideas and flipping them on their head, defining contracts from the client-side in the form of specs. Pat