Scott Taylor
2007-Mar-24 07:08 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
I''ve notice that a project like Rubinius has both a spec & a test directory. Rspec has only a spec directory. Obviously I support BDD, but isn''t there also a place for state based/verification testing? I sometimes sense that I *do* want to practice Test Driven Development. That is, I want some assurance that my production code will run as intended. But I also want some verification of a bug right after I have implemented it. How can one truly get away from state based testing to some degree? Spec''s often seem too "high level" to assure the "testing" of the code. I know that Test::Unit code will always be brittle. What happens when the code is refactored? It is sure to break. Does this suggest that Test::Unit code should be written right after development is done, covering the internals of the project? Maybe BDD specs should be written first, using TDD with Test::Unit for verification (as throw-away code)? Or do mock objects solve all of these problems? The real question is, do you spec''ers think there is any place for a testing framework next to a spec''ing framework? Best, Scott Taylor
David Chelimsky
2007-Mar-24 12:19 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:> > I''ve notice that a project like Rubinius has both a spec & a test > directory. Rspec has only a spec directory. Obviously I support > BDD, but isn''t there also a place for state based/verification > testing?BDD is not a tool. BDD is a way of thinking about TDD. BDD *is* TDD, with focus (not exclusivity) on behaviour. This is what I believe to be the initial intent of TDD. This doesn''t mean that all state testing is bad. In fact, most of the expectations in rspec are state-based: actual.should == value, etc. I think you''re confusing Interaction testing with BDD. Interaction testing is a very important part of BDD, but it is not the sole purview of BDD. Mocks have been around for a long time. I can''t really think of anything that you can do with rspec that you can''t do w/ test/unit and mocha. RSpec just tries to make it easier to focus on behaviour by using less "testy" words.> I sometimes sense that I *do* want to practice Test Driven > Development. That is, I want some assurance that my production code > will run as intended. But I also want some verification of a bug > right after I have implemented it.Many people fix bugs using TDD. When the bug is reported, just start by writing a failing test that exposes the bug. Keep in mind that when doing TDD, the nature of the tests change very quickly. When you write the failing test, your goal is expose a missing or incorrect behaviour, and use the resulting test to drive your design. As soon as that test is passing, it changes in nature, becoming both documentation and a regression test.> > How can one truly get away from state based testing to some degree?You can''t. At least not in my experience.> Spec''s often seem too "high level" to assure the "testing" of the code.Again, this has to do w/ approach. You can write low level specs just as you can write high-level tests. The trick is balance, keeping the focus on behaviour rather than the internal structure of code.> I know that Test::Unit code will always be brittle. What happens > when the code is refactored? It is sure to break. > Does this suggest that Test::Unit code should be written right after > development is done, covering the internals of the project?Again, this is a matter of approach, not tooling. Assuming that you *must* test something internal, there''s no reason that you can''t do it with rspec. But if you are testing internals, I''d reflect on that and ask yourself why it is important to do so. Ask yourself how the behaviour is going to be different if the internals change. I''ll bet that most (not all) of the time, you''ll be able to find ways to express your "testing" concerns in terms of behaviour. If you can do that without having to get too far away from the code to do so, you''re better off because you''ll have better documentation and less brittle tests. We should really be talking about specific examples, because there are some principles here that are either not being recognized or dying to get out. Feel free to post some.> Maybe > BDD specs should be written first, using TDD with Test::Unit for > verification (as throw-away code)? Or do mock objects solve all of > these problems? > > The real question is, do you spec''ers think there is any place for a > testing framework next to a spec''ing framework?Heretical though this may seem: RSPEC IS A TESTING FRAMEWORK. There, I said it. Scott - I don''t mean to pick on you here. In fact, I thank you for posting this because a lot has been said during the early phases of BDD''s evolution that is confusing and obviously misleading. And, in fact, much of this has been said by me as I''ve been exploring what the meaning of BDD is ... to me. I hope that you''ll keep posting questions like this as they can only help us all to clarify things. Cheers, David> > Best, > > Scott Taylor > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
David Chelimsky
2007-Mar-24 13:08 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/24/07, David Chelimsky <dchelimsky at gmail.com> wrote:> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > I''ve notice that a project like Rubinius has both a spec & a test > > directory. Rspec has only a spec directory. Obviously I support > > BDD, but isn''t there also a place for state based/verification > > testing? > > BDD is not a tool. BDD is a way of thinking about TDD. BDD *is* TDD, > with focus (not exclusivity) on behaviour. This is what I believe to > be the initial intent of TDD. This doesn''t mean that all state testing > is bad. In fact, most of the expectations in rspec are state-based: > actual.should == value, etc. > > I think you''re confusing Interaction testing with BDD. Interaction > testing is a very important part of BDD, but it is not the sole > purview of BDD. Mocks have been around for a long time. I can''t really > think of anything that you can do with rspec that you can''t do w/ > test/unit and mocha. RSpec just tries to make it easier to focus on > behaviour by using less "testy" words. > > > I sometimes sense that I *do* want to practice Test Driven > > Development. That is, I want some assurance that my production code > > will run as intended. But I also want some verification of a bug > > right after I have implemented it. > > Many people fix bugs using TDD. When the bug is reported, just start > by writing a failing test that exposes the bug. > > Keep in mind that when doing TDD, the nature of the tests change very > quickly. When you write the failing test, your goal is expose a > missing or incorrect behaviour, and use the resulting test to drive > your design. As soon as that test is passing, it changes in nature, > becoming both documentation and a regression test. > > > > > How can one truly get away from state based testing to some degree? > > You can''t. At least not in my experience. > > > Spec''s often seem too "high level" to assure the "testing" of the code. > > Again, this has to do w/ approach. You can write low level specs just > as you can write high-level tests. The trick is balance, keeping the > focus on behaviour rather than the internal structure of code. > > > I know that Test::Unit code will always be brittle. What happens > > when the code is refactored? It is sure to break. > > Does this suggest that Test::Unit code should be written right after > > development is done, covering the internals of the project? > > Again, this is a matter of approach, not tooling. Assuming that you > *must* test something internal, there''s no reason that you can''t do it > with rspec. But if you are testing internals, I''d reflect on that and > ask yourself why it is important to do so. Ask yourself how the > behaviour is going to be different if the internals change. I''ll bet > that most (not all) of the time, you''ll be able to find ways to > express your "testing" concerns in terms of behaviour. If you can do > that without having to get too far away from the code to do so, you''re > better off because you''ll have better documentation and less brittle > tests. > > We should really be talking about specific examples, because there are > some principles here that are either not being recognized or dying to > get out. Feel free to post some. > > > Maybe > > BDD specs should be written first, using TDD with Test::Unit for > > verification (as throw-away code)? Or do mock objects solve all of > > these problems? > > > > The real question is, do you spec''ers think there is any place for a > > testing framework next to a spec''ing framework? > > Heretical though this may seem: RSPEC IS A TESTING FRAMEWORK. There, I said it. > > Scott - I don''t mean to pick on you here. In fact, I thank you for > posting this because a lot has been said during the early phases of > BDD''s evolution that is confusing and obviously misleading. And, in > fact, much of this has been said by me as I''ve been exploring what the > meaning of BDD is ... to me. > > I hope that you''ll keep posting questions like this as they can only > help us all to clarify things.I should also add that I''m talking about BDD as applied to isolation testing (what many call unit testing :) ). BDD has really evolved into an agile practice that comprises TDD, Acceptance Test Driven Planning and other concepts that are geared towards increasing communication and understanding within the context of a software project. If this is new to you, check out http://dannorth.net/introducing-bdd/.> > Cheers, > David > > > > > Best, > > > > Scott Taylor > > > > > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > >
aslak hellesoy
2007-Mar-24 13:11 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:> > I''ve notice that a project like Rubinius has both a spec & a test > directory. Rspec has only a spec directory. Obviously I support > BDD, but isn''t there also a place for state based/verificationAnyone is free to write their code who they want. RSpec doesn''t mandate any particular style, it just encourages it.> testing? I sometimes sense that I *do* want to practice Test Driven > Development.Ok. BDD is just a kind of TDD with a stronger focus on "tell don''t ask", mocking and intent.> That is, I want some assurance that my production code > will run as intended. But I also want some verification of a bug > right after I have implemented it. > > How can one truly get away from state based testing to some degree?Use mocking to drive out interaction between objects. Strive for a "tell don''t ask" design (look it up).> Spec''s often seem too "high level" to assure the "testing" of the code. >What do you mean?> I know that Test::Unit code will always be brittle. What happens > when the code is refactored? It is sure to break. >Huh? What is it about Test::Unit that makes it inherently brittle? I have no idea what you are talking about here.> Does this suggest that Test::Unit code should be written right after > development is done, covering the internals of the project?If you''re doing TDD, no - you write tests before the code. If you''re "just using Test::Unit" you can write it when you want.> Maybe > BDD specs should be written first, using TDD with Test::Unit forBDD *is* TDD, with some extra philosophical baggage. You write specs before the code in both BDD and TDD.> verification (as throw-away code)? Or do mock objects solve all of > these problems? >What problems?> The real question is, do you spec''ers think there is any place for a > testing framework next to a spec''ing framework? >To solve what problem? Aslak> Best, > > Scott Taylor > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Scott Taylor
2007-Mar-25 05:44 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
Sorry if this was rather incoherent. I guess the simplest questions that I have are these: 1. Should you test protected and private methods in your specs? 2. Should you ever test that a certain instance variable gets set in a method, or only that methods return their correct values? This question can be generalized to: Should you ever test/spec *parts* of a method? 3. If you already have a code base (with no specs/tests) is there any advantage over using Rspec to Test::Unit for verification testing? Some of these questions may be seemingly off topic from the original post, but I''m sure they are connected somehow subconsciously for me. I''d be interested in hearing your answers. Just another point to make:>>> I know that Test::Unit code will always be brittle. What happens >>> when the code is refactored? It is sure to break. >>> >> >> Huh? What is it about Test::Unit that makes it inherently brittle? >> I have no idea what you are talking about here.I was watching Dave Astel''s Google Tech Talk, and one of the main problems he saw with testing was that classes had a one to one correspondence with tests, removing the ability to refactor. Best, Scott
Pat Maddox
2007-Mar-25 06:25 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:> 1. Should you test protected and private methods in your specs?No. You''re specifying the behavior of an object as seen by the outside world. Of course protected and private methods aren''t available to the world, so why would you need to test them? When you''re doing state-based testing, just call a method and then verify that it returns the expected value or leaves your object in an expected state.> 2. Should you ever test that a certain instance variable gets set in > a method, or only that methods return their correct values? This > question can be generalized to: Should you ever test/spec *parts* of > a method?Same thinking behind my answer to (1) applies here.> 3. If you already have a code base (with no specs/tests) is there > any advantage over using Rspec to Test::Unit for verification testing?Sure. my_object.foo.should == 3 vs assert_equal 3, my_object.foo my_object.should_not be_nil vs assert !my_object.nil? my_object.should have(2).errors vs assert_equal 2, my_object.errors.size Ultimately it comes down to personal preference. If you''re doing things the right way, you''re going to do basically the same thing in RSpec or Test::Unit, just with a different syntax. However if you''re like me, RSpec makes it easier to do things the right way (or at least get close :) Pat
Scott Taylor
2007-Mar-25 06:37 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On Mar 25, 2007, at 2:25 AM, Pat Maddox wrote:> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: >> 1. Should you test protected and private methods in your specs? > > No. You''re specifying the behavior of an object as seen by the > outside world. Of course protected and private methods aren''t > available to the world, so why would you need to test them? When > you''re doing state-based testing, just call a method and then verify > that it returns the expected value or leaves your object in an > expected state. >How about if your writing code that is *only* meant to be reused? E.g., you are writing some class which is only meant to be derived from (ruby metaprogramming - Spec''ing rails would be a good example)? Best, Scott
Pat Maddox
2007-Mar-25 06:39 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
I actually wrote something in our company wiki tonight that touches on this. I''m going to be lazy and just copy and paste it here (it''s late). Anyway to summarize my thinking on the state-based vs interaction-based testing, it''s... Some of your code''s job is to tell a story some of your code''s job is to get stuff done The first part is pretty easy. You just write your mock expecations and go. There''s not a whole lot of state-based testing. The second part is more of a mix of the two, depending on what an object or method should do. When a method has to interact with other objects, obviously interaction-based testing is looking like a good option. If you''re interested in a method''s return value, or whether it changes the object''s state, you have to do some state-based testing. Here''s the wiki excerpt I wrote up. Hope you find it helpful. Pat ========================================== We should have good enough domain model code that our controllers tell an easy to read story. (PM: yes I''m aware I sorta suck at that). They really shouldn''t have any business logic, that''s all done in the models. The controller just coordinates it all and exposes data to the user. With that in mind, the vast majority of your controller specs should be behavioral expectations. We just want to know that the right method was called on the right object. Really the only state-based verification you''d do is to ensure that certain instance variables are correctly set for the view. I''ll show an example for requesting /video_formats/1.xml, which is the XML representation of the VideoFormat with ID=1. We are interested in verifying three things: * The proper video format is selected from the db * We call that video format''s #to_xml method * The result of #to_xml is rendered as the page output context "Requesting /video_formats/1.xml using GET" do controller_name :video_formats setup do @mock_format = mock("format") @mock_format.stub!(:to_xml).and_return "XML" VideoFormat.stub!(:find).and_return @mock_format end def do_get @request.env["HTTP_ACCEPT"] = "application/xml" get :show, :id => "1" end specify "should be successful" do do_get response.should_be_success end specify "should find the VideoFormat" do VideoFormat.should_receive(:find).with("1").and_return @mock_format do_get end specify "should render the format as XML" do @mock_format.should_receive(:to_xml).and_return "XML" do_get response.body.should_eql "XML" end end The specification clearly communicates what should happen when we request /video_formats/1.xml. In general I like to keep only one expectation per specification, but in the last one ("should render the format as XML") it makes sense to combine the two expectations since they''re closely related. Now I''m going to show an example of a spec that is a good idea and an important spec, but probably in the wrong place. context "Requesting real /video_formats/1.xml using GET" do controller_name :video_formats setup do @format = VideoFormat.new @format.save VideoFormat.stub!(:find).and_return @format end def do_get @request.env["HTTP_ACCEPT"] = "application/xml" get :show, :id => "1" end specify "use real video format xml and make sure id is set" do response = do_get response.should_be_success data = response.body # check the feed to make sure the format id is in there, we need it for the databurst addAsset call h = Hash.from_xml data format = h[''video_format''] assert format.has_key?(''id'') end end The problem with this spec is that it''s not verifying the behavior of the VideoFormatsController#show action, but rather verifying the behavior of a VideoFormat object itself. Because we know from the previous spec that #show renders the VideoFormat''s XML representation as a response, by finding the <id> property in the XML we implicitly know that a VideoFormat renders its id attribute. A better approach would be to move this into the VideoFormat model spec. That way the knowledge of a VideoFormat''s behavior is located in one place, and our controller specification can drop its dependence on the database and go back to simply telling the action''s story. context "A saved VideoFormat in general" do setup do @format = VideoFormat.create end specify "should include the ID in its XML" do Hash.from_xml(@format.to_xml)["video_format"]["id"].should_not be_nil end end Now we''ve explicitly stated that a VideoFormat should include <id> when it renders itself as XML. We can remove the second controller specification, because we''ve now verified that (a) /video_formats/1.xml calls the VideoFormat''s #to_xml method, and (b) calling #to_xml on a VideoFormat includes the id property.
Pat Maddox
2007-Mar-25 06:40 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:> > On Mar 25, 2007, at 2:25 AM, Pat Maddox wrote: > > > On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > >> 1. Should you test protected and private methods in your specs? > > > > No. You''re specifying the behavior of an object as seen by the > > outside world. Of course protected and private methods aren''t > > available to the world, so why would you need to test them? When > > you''re doing state-based testing, just call a method and then verify > > that it returns the expected value or leaves your object in an > > expected state. > > > > > How about if your writing code that is *only* meant to be reused? > E.g., you are writing some class which is only meant to be derived > from (ruby metaprogramming - Spec''ing rails would be a good example)? > > Best, > > Scott > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >I''m not sure what you mean, to tell you the truth. Would you mind showing an example of some code that you want to spec but aren''t sure how? Pat
Scott Taylor
2007-Mar-25 07:08 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On Mar 25, 2007, at 2:40 AM, Pat Maddox wrote:> On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: >> >> On Mar 25, 2007, at 2:25 AM, Pat Maddox wrote: >> >>> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: >>>> 1. Should you test protected and private methods in your specs? >>> >>> No. You''re specifying the behavior of an object as seen by the >>> outside world. Of course protected and private methods aren''t >>> available to the world, so why would you need to test them? When >>> you''re doing state-based testing, just call a method and then verify >>> that it returns the expected value or leaves your object in an >>> expected state. >>> >> >> >> How about if your writing code that is *only* meant to be reused? >> E.g., you are writing some class which is only meant to be derived >> from (ruby metaprogramming - Spec''ing rails would be a good example)? >> > > I''m not sure what you mean, to tell you the truth. Would you mind > showing an example of some code that you want to spec but aren''t sure > how?I had in mind a rails generic crud controller. The basic gist of it is would be one class which had a series of private class methods. These methods could be called in any class which derived from this class, which would then set certain instance variables and instance methods for use in the class. A good example is a typical rails controller, or class: class Person < ActiveRecord::Base has_many :posts end If you say something like: @person = Person.find(:first_name => "Scott", :last_name => "Taylor) @person.posts The first line will find the first person in the database that matches "Scott Taylor." The second will find all posts associated with Scott Taylor. What do you think the ActiveRecord::Base class is going to look like? It''s going to have a private class method named "has_many" which excepts a string or symbol as a parameter. This will then create an instance method in the derived class. In this example, that instance method would "posts". (For simplicity sake I''ve left out or changed some details of all the other things rails does). ActiveRecord::Base will never be used on its own, only as a class which is derived from. So how would ActiveRecord::Base be spec''ed out for this example? I haven''t posted my code example because what I was trying to achieve was implemented by someone else already, and I decided to abandon the attempt. I''ve noticed that they have a spec directory in their project, so I''ll have to check out how they''ve spec''ed out their class. Regards, Scott
Pat Maddox
2007-Mar-25 07:17 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:> > On Mar 25, 2007, at 2:40 AM, Pat Maddox wrote: > > > On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > >> > >> On Mar 25, 2007, at 2:25 AM, Pat Maddox wrote: > >> > >>> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > >>>> 1. Should you test protected and private methods in your specs? > >>> > >>> No. You''re specifying the behavior of an object as seen by the > >>> outside world. Of course protected and private methods aren''t > >>> available to the world, so why would you need to test them? When > >>> you''re doing state-based testing, just call a method and then verify > >>> that it returns the expected value or leaves your object in an > >>> expected state. > >>> > >> > >> > >> How about if your writing code that is *only* meant to be reused? > >> E.g., you are writing some class which is only meant to be derived > >> from (ruby metaprogramming - Spec''ing rails would be a good example)? > >> > > > > I''m not sure what you mean, to tell you the truth. Would you mind > > showing an example of some code that you want to spec but aren''t sure > > how? > > I had in mind a rails generic crud controller. The basic gist of it > is would be one class which had a series of private class methods. > These methods could be called in any class which derived from this > class, which would then set certain instance variables and instance > methods for use in the class. > > A good example is a typical rails controller, or class: > > class Person < ActiveRecord::Base > has_many :posts > end > > If you say something like: > > @person = Person.find(:first_name => "Scott", :last_name => "Taylor) > > @person.posts > > The first line will find the first person in the database that > matches "Scott Taylor." The second will find all posts associated > with Scott Taylor. > > What do you think the ActiveRecord::Base class is going to look > like? It''s going to have a private class method named "has_many" > which excepts a string or symbol as a parameter. This will then > create an instance method in the derived class. In this example, > that instance method would "posts". (For simplicity sake I''ve left > out or changed some details of all the other things rails does). > > ActiveRecord::Base will never be used on its own, only as a class > which is derived from. > > So how would ActiveRecord::Base be spec''ed out for this example?I''m not sure how the Rails codebase is tested, but I think I''d do base = ActiveRecord::Base.new base.send :has_many, :posts and verify from there. I''m interested to see what David and Aslak think. Pat
aslak hellesoy
2007-Mar-25 10:06 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote:> On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > On Mar 25, 2007, at 2:40 AM, Pat Maddox wrote: > > > > > On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > >> > > >> On Mar 25, 2007, at 2:25 AM, Pat Maddox wrote: > > >> > > >>> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > >>>> 1. Should you test protected and private methods in your specs? > > >>> > > >>> No. You''re specifying the behavior of an object as seen by the > > >>> outside world. Of course protected and private methods aren''t > > >>> available to the world, so why would you need to test them? When > > >>> you''re doing state-based testing, just call a method and then verify > > >>> that it returns the expected value or leaves your object in an > > >>> expected state. > > >>> > > >> > > >> > > >> How about if your writing code that is *only* meant to be reused? > > >> E.g., you are writing some class which is only meant to be derived > > >> from (ruby metaprogramming - Spec''ing rails would be a good example)? > > >> > > > > > > I''m not sure what you mean, to tell you the truth. Would you mind > > > showing an example of some code that you want to spec but aren''t sure > > > how? > > > > I had in mind a rails generic crud controller. The basic gist of it > > is would be one class which had a series of private class methods. > > These methods could be called in any class which derived from this > > class, which would then set certain instance variables and instance > > methods for use in the class. > > > > A good example is a typical rails controller, or class: > > > > class Person < ActiveRecord::Base > > has_many :posts > > end > > > > If you say something like: > > > > @person = Person.find(:first_name => "Scott", :last_name => "Taylor) > > > > @person.posts > > > > The first line will find the first person in the database that > > matches "Scott Taylor." The second will find all posts associated > > with Scott Taylor. > > > > What do you think the ActiveRecord::Base class is going to look > > like? It''s going to have a private class method named "has_many" > > which excepts a string or symbol as a parameter. This will then > > create an instance method in the derived class. In this example, > > that instance method would "posts". (For simplicity sake I''ve left > > out or changed some details of all the other things rails does). > > > > ActiveRecord::Base will never be used on its own, only as a class > > which is derived from. > > > > So how would ActiveRecord::Base be spec''ed out for this example? > > I''m not sure how the Rails codebase is tested, but I think I''d do > > base = ActiveRecord::Base.new > base.send :has_many, :posts > > and verify from there. I''m interested to see what David and Aslak think. >The (controller) specs generated by the rspec_resource generator are good examples on how to test a controller. I would just use them as-is. Aslak> Pat > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Pat Maddox
2007-Mar-25 10:18 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:> On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote: > > On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > > > On Mar 25, 2007, at 2:40 AM, Pat Maddox wrote: > > > > > > > On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > >> > > > >> On Mar 25, 2007, at 2:25 AM, Pat Maddox wrote: > > > >> > > > >>> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > >>>> 1. Should you test protected and private methods in your specs? > > > >>> > > > >>> No. You''re specifying the behavior of an object as seen by the > > > >>> outside world. Of course protected and private methods aren''t > > > >>> available to the world, so why would you need to test them? When > > > >>> you''re doing state-based testing, just call a method and then verify > > > >>> that it returns the expected value or leaves your object in an > > > >>> expected state. > > > >>> > > > >> > > > >> > > > >> How about if your writing code that is *only* meant to be reused? > > > >> E.g., you are writing some class which is only meant to be derived > > > >> from (ruby metaprogramming - Spec''ing rails would be a good example)? > > > >> > > > > > > > > I''m not sure what you mean, to tell you the truth. Would you mind > > > > showing an example of some code that you want to spec but aren''t sure > > > > how? > > > > > > I had in mind a rails generic crud controller. The basic gist of it > > > is would be one class which had a series of private class methods. > > > These methods could be called in any class which derived from this > > > class, which would then set certain instance variables and instance > > > methods for use in the class. > > > > > > A good example is a typical rails controller, or class: > > > > > > class Person < ActiveRecord::Base > > > has_many :posts > > > end > > > > > > If you say something like: > > > > > > @person = Person.find(:first_name => "Scott", :last_name => "Taylor) > > > > > > @person.posts > > > > > > The first line will find the first person in the database that > > > matches "Scott Taylor." The second will find all posts associated > > > with Scott Taylor. > > > > > > What do you think the ActiveRecord::Base class is going to look > > > like? It''s going to have a private class method named "has_many" > > > which excepts a string or symbol as a parameter. This will then > > > create an instance method in the derived class. In this example, > > > that instance method would "posts". (For simplicity sake I''ve left > > > out or changed some details of all the other things rails does). > > > > > > ActiveRecord::Base will never be used on its own, only as a class > > > which is derived from. > > > > > > So how would ActiveRecord::Base be spec''ed out for this example? > > > > I''m not sure how the Rails codebase is tested, but I think I''d do > > > > base = ActiveRecord::Base.new > > base.send :has_many, :posts > > > > and verify from there. I''m interested to see what David and Aslak think. > > > > The (controller) specs generated by the rspec_resource generator are > good examples on how to test a controller. I would just use them > as-is.That''s not what he means, if I understand correctly. Assume Rails doesn''t exist, and you''re building it from the ground up. How would you spec ActiveRecord::Base? At least that''s what I thought the question is. Pat
David Chelimsky
2007-Mar-25 10:42 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote:> On 3/25/07, aslak hellesoy <aslak.hellesoy at gmail.com> wrote: > > On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote: > > > On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > >> How about if your writing code that is *only* meant to be reused? > > > > >> E.g., you are writing some class which is only meant to be derived > > > > >> from (ruby metaprogramming - Spec''ing rails would be a good example)? > > > > >> > > > > > > > > > > I''m not sure what you mean, to tell you the truth. Would you mind > > > > > showing an example of some code that you want to spec but aren''t sure > > > > > how? > > > > > > > > I had in mind a rails generic crud controller. The basic gist of it > > > > is would be one class which had a series of private class methods. > > > > These methods could be called in any class which derived from this > > > > class, which would then set certain instance variables and instance > > > > methods for use in the class. > > > > > > > > A good example is a typical rails controller, or class: > > > > > > > > class Person < ActiveRecord::Base > > > > has_many :posts > > > > end > > > > > > > > If you say something like: > > > > > > > > @person = Person.find(:first_name => "Scott", :last_name => "Taylor) > > > > > > > > @person.posts > > > > > > > > The first line will find the first person in the database that > > > > matches "Scott Taylor." The second will find all posts associated > > > > with Scott Taylor. > > > > > > > > What do you think the ActiveRecord::Base class is going to look > > > > like? It''s going to have a private class method named "has_many" > > > > which excepts a string or symbol as a parameter. This will then > > > > create an instance method in the derived class. In this example, > > > > that instance method would "posts". (For simplicity sake I''ve left > > > > out or changed some details of all the other things rails does). > > > > > > > > ActiveRecord::Base will never be used on its own, only as a class > > > > which is derived from. > > > > > > > > So how would ActiveRecord::Base be spec''ed out for this example? > > > > > > I''m not sure how the Rails codebase is tested, but I think I''d do > > > > > > base = ActiveRecord::Base.new > > > base.send :has_many, :posts > > > > > > and verify from there. I''m interested to see what David and Aslak think. > > > > > > > The (controller) specs generated by the rspec_resource generator are > > good examples on how to test a controller. I would just use them > > as-is. > > That''s not what he means, if I understand correctly. > > Assume Rails doesn''t exist, and you''re building it from the ground up. > How would you spec ActiveRecord::Base? > > At least that''s what I thought the question is.I think you''re right. Typically I''d do something like this: describe FooSubclass do setup {@foo_sub = FooSubclass.new) it "should do bar" do ... end end class FooSubclass < Foo .. end To me, this is a little better than just describing the Foo class because the Foo class is never intended to be instantiated directly. If there are any interactions between the two (like initialization of the sub setting values in super, or super implementing #inherited(klass) ), they get well documented in the resulting descriptions. David
David Chelimsky
2007-Mar-25 10:59 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote:> On 3/24/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > 1. Should you test protected and private methods in your specs? > > No. You''re specifying the behavior of an object as seen by the > outside world. Of course protected and private methods aren''t > available to the world, so why would you need to test them? When > you''re doing state-based testing, just call a method and then verify > that it returns the expected value or leaves your object in an > expected state.+1. Well said.> > > 2. Should you ever test that a certain instance variable gets set in > > a method, or only that methods return their correct values? This > > question can be generalized to: Should you ever test/spec *parts* of > > a method? > > Same thinking behind my answer to (1) applies here.+1 again.> > > 3. If you already have a code base (with no specs/tests) is there > > any advantage over using Rspec to Test::Unit for verification testing? > > Sure. > > my_object.foo.should == 3 > vs > assert_equal 3, my_object.foo > > my_object.should_not be_nil > vs > assert !my_object.nil? > > my_object.should have(2).errors > vs > assert_equal 2, my_object.errors.sizeI think Scott''s question was the reverse of what you''re answering - I read "does Test::Unit hold any advantage over RSpec for post-code verification testing" Even when I''m doing TDD, once I''m convinced that I''ve satisfied the behavioural requirements (typically by passing Acceptance Tests), I''ll review the tests from the perspective of documentation. Can another developer read these tests and understand how to use the objects being described? If not, I''ll refactor the tests, which may mean adding new ones. Perhaps there''s even a corner case that I haven''t covered that I perceive covering would add some value. In this case, I''ll often add a new test method to cover that, just for the documentation value. If it passes right away, I''ll usually go into the code and tweak something to make it fail, and then tweak it back. This provides a sanity check that the test is actually interacting with the parts of the system it claims to, which is the main reason for starting with failing tests when you are in TDD mode.> > Ultimately it comes down to personal preference. If you''re doing > things the right way, you''re going to do basically the same thing in > RSpec or Test::Unit, just with a different syntax. However if you''re > like me, RSpec makes it easier to do things the right way (or at least > get close :)I''m really glad to see that you''re having that experience. This is the whole point of BDD. If you look at the things that Dave Astels and Dan North have written about since the earliest days of BDD, it is about making it easier to learn and then practice TDD as we believe it to be intended by evolving language and frameworks that focus on observable behaviour. Cheers, David> > Pat > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Pat Maddox
2007-Mar-25 11:34 UTC
[rspec-users] State Based vs. Behaviour Based Spec/Testing
On 3/25/07, David Chelimsky <dchelimsky at gmail.com> wrote:> On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote: > > On 3/25/07, aslak hellesoy <aslak.hellesoy at gmail.com> wrote: > > > On 3/25/07, Pat Maddox <pergesu at gmail.com> wrote: > > > > On 3/25/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote: > > > > > >> How about if your writing code that is *only* meant to be reused? > > > > > >> E.g., you are writing some class which is only meant to be derived > > > > > >> from (ruby metaprogramming - Spec''ing rails would be a good example)? > > > > > >> > > > > > > > > > > > > I''m not sure what you mean, to tell you the truth. Would you mind > > > > > > showing an example of some code that you want to spec but aren''t sure > > > > > > how? > > > > > > > > > > I had in mind a rails generic crud controller. The basic gist of it > > > > > is would be one class which had a series of private class methods. > > > > > These methods could be called in any class which derived from this > > > > > class, which would then set certain instance variables and instance > > > > > methods for use in the class. > > > > > > > > > > A good example is a typical rails controller, or class: > > > > > > > > > > class Person < ActiveRecord::Base > > > > > has_many :posts > > > > > end > > > > > > > > > > If you say something like: > > > > > > > > > > @person = Person.find(:first_name => "Scott", :last_name => "Taylor) > > > > > > > > > > @person.posts > > > > > > > > > > The first line will find the first person in the database that > > > > > matches "Scott Taylor." The second will find all posts associated > > > > > with Scott Taylor. > > > > > > > > > > What do you think the ActiveRecord::Base class is going to look > > > > > like? It''s going to have a private class method named "has_many" > > > > > which excepts a string or symbol as a parameter. This will then > > > > > create an instance method in the derived class. In this example, > > > > > that instance method would "posts". (For simplicity sake I''ve left > > > > > out or changed some details of all the other things rails does). > > > > > > > > > > ActiveRecord::Base will never be used on its own, only as a class > > > > > which is derived from. > > > > > > > > > > So how would ActiveRecord::Base be spec''ed out for this example? > > > > > > > > I''m not sure how the Rails codebase is tested, but I think I''d do > > > > > > > > base = ActiveRecord::Base.new > > > > base.send :has_many, :posts > > > > > > > > and verify from there. I''m interested to see what David and Aslak think. > > > > > > > > > > The (controller) specs generated by the rspec_resource generator are > > > good examples on how to test a controller. I would just use them > > > as-is. > > > > That''s not what he means, if I understand correctly. > > > > Assume Rails doesn''t exist, and you''re building it from the ground up. > > How would you spec ActiveRecord::Base? > > > > At least that''s what I thought the question is. > > I think you''re right. > > Typically I''d do something like this: > > describe FooSubclass do > setup {@foo_sub = FooSubclass.new) > it "should do bar" do > ... > end > end > > class FooSubclass < Foo > .. > end > > To me, this is a little better than just describing the Foo class > because the Foo class is never intended to be instantiated directly. > If there are any interactions between the two (like initialization of > the sub setting values in super, or super implementing > #inherited(klass) ), they get well documented in the resulting > descriptions. > > David > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >Yeah I was thinking that as well. I think it has the added benefit of clearly expressing the intent and usage of the class under test. It''s only meant to be subclassed, and should be spec''ed that way. Pat