I totally agree.&nbsp; This sort of comment/guidance/opinion should be findable from (or included on) the <a href="http://rspec.info">rspec.info</a> page on models..<br><br>Pat - thanks a bunch for taking the time!<br><br>Tim.<br>
<br><div><span class="gmail_quote">On 03/04/2008, <b class="gmail_sendername">David Chelimsky</b> &lt;<a href="mailto:dchelimsky@gmail.com">dchelimsky@gmail.com</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On Wed, Apr 2, 2008 at 10:40 PM, Zach Dennis &lt;<a href="mailto:zach.dennis@gmail.com">zach.dennis@gmail.com</a>&gt; wrote:<br> &gt; Pat,<br> &gt;<br> &gt;&nbsp;&nbsp;That was a wonderfully thought out reply and at first read your<br>
 &gt;&nbsp;&nbsp;reasoning makes a lot of sense.<br> <br> <br>+1<br> <br><br> &gt; Thank you for taking the time to write<br> &gt;&nbsp;&nbsp;it.<br> <br> <br>+1 more<br> <br> Cheers,<br> <br>David<br> <br><br> &gt; I am going to let it sink in over the next few days,<br>
 &gt;<br> &gt;&nbsp;&nbsp;Zach<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;&nbsp;&nbsp;On Wed, Apr 2, 2008 at 8:11 PM, Pat Maddox &lt;<a href="mailto:pergesu@gmail.com">pergesu@gmail.com</a>&gt; wrote:<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt; On Tue, Apr 1, 2008 at 4:20 PM, Zach Dennis &lt;<a href="mailto:zach.dennis@gmail.com">zach.dennis@gmail.com</a>&gt; wrote:<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt; On Tue, Apr 1, 2008 at 6:38 PM, Pat Maddox &lt;<a href="mailto:pergesu@gmail.com">pergesu@gmail.com</a>&gt; wrote:<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt; On Tue, Apr 1, 2008 at 3:09 PM, David Chelimsky &lt;<a href="mailto:dchelimsky@gmail.com">dchelimsky@gmail.com</a>&gt; wrote:<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Example:<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;describe SomeModel do<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it_has_many :widgets, :destroy =&gt; :null, :class_name =&gt; &quot;BaseWidget&quot;<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it_has_one :fuzzbucket<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it_belongs_to :another_model<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;end<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;I see more and more structures appearing like this. I have very mixed<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;feelings about them. This is about structure, not behaviour. Even if<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;the underlying code is actually approaching this in a more behavioural<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;way, it&#39;s still expressing structure at the high level.<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;I don&#39;t have mixed feelings about this.&nbsp;&nbsp;I think this type of spec is<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;terrible.&nbsp;&nbsp;It completely duplicates the implementation.&nbsp;&nbsp;It&#39;s not even<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;testing anything.<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;This is not a value judgment against you though, Zach.&nbsp;&nbsp;I think when<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;people do stuff like this they genuinely have good intentions.&nbsp;&nbsp;It&#39;s<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;just that it seems to be quite difficult to test highly declarative<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;stuff like AR associations.<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Now that I&#39;ve given my rather harsh opinion, I have to get back to<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;work :)&nbsp;&nbsp;I&#39;ll try follow up later with something more helpful like<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;thoughts on how to write better specs.<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;I don&#39;t like the fact that it tests the structure of the association<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;(as opposed to testing the behavior), but I do like that it tests the<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;conceptual relationship between models. I find value in this. Even<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;though it is declarative it is very clear and meaningful to the next<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;guy looking at the code, and if someone changes something incidentally<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;they are quickly pointed to the fact that they broke a conceptual<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;relationship between two models.<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Please do respond with more thoughts, as this is a topic I&#39;d like to<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;get hammered out as it will provide value to every developer on this<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;list,<br>
 &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;I&#39;ve put some more thought into this and have a bit of time to reply.<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;So here goes.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;The first thing I&#39;m going to do is demonstrate why I feel this is a<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;bad spec.&nbsp;&nbsp;Please understand that this is not a criticism of anyone in<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;particular.&nbsp;&nbsp;I&#39;m merely using this as an example of specs that don&#39;t<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;add any value.<br> &gt;&nbsp;&nbsp;&gt;<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Take a look at the spec again:<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;describe SomeModel do<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it_has_many :widgets, :destroy =&gt; :null, :class_name =&gt; &quot;BaseWidget&quot;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it_has_one :fuzzbucket<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it_belongs_to :another_model<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;end<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Change &#39;describe&#39; to &#39;class&#39; and remove &#39;do&#39; from the first line.<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Then remove the &#39;it_&#39; from the next three lines.&nbsp;&nbsp;At this point you<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;have the exact implementation of the class.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;I don&#39;t know about you, but that bothers the hell out of me.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;The concrete benefits of object-level specification are, in my mind, that it<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; - helps you design your code well<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; - leaves behind regression tests<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; - provides executable examples of how to use code<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Often when we write specs we have to balance those goals...for<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;example, one major criticism of using mocks is that tests that use<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;mocks don&#39;t act as effective regression tests.&nbsp;&nbsp;That&#39;s a valid<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;criticism in certain contexts, but you&#39;ll find that most people who<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;make such criticisms are being myopic - they either don&#39;t understand<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;or don&#39;t share the other goals, and so write the technique off all<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;together.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Besides the fact that the given association helpers duplicate the<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;implementation to an i-t-underscore, what else is wrong with them?&nbsp;&nbsp;I<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;would argue that they provide 0 value in all three categories.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;They don&#39;t help drive the design.&nbsp;&nbsp;You either need widgets or you<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;don&#39;t.&nbsp;&nbsp;If you decide you do, you add a declaration to the<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;implementation.&nbsp;&nbsp;Done.&nbsp;&nbsp;There was never any question about how to<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;design it.&nbsp;&nbsp;Rails made that decision for you.<br>
 &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;They have no value as regression tests.&nbsp;&nbsp;How likely is it that any of<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;that code will break?&nbsp;&nbsp;Not likely at all.&nbsp;&nbsp;It&#39;s not like anyone&#39;s ever<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;going to go in there and change the behavior, because there is no<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;behavior, other than that which is abstracted away by Rails (thus<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;already thoroughly tested).&nbsp;&nbsp;If you make any change to the<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;implementation then the specs will fail...so they&#39;re brittle without<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;providing any value.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;The lack of documentation value should be obvious.&nbsp;&nbsp;The specs don&#39;t<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;show you how to use the objects together.&nbsp;&nbsp;You have to know how Rails<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;associations work.&nbsp;&nbsp;And you get absolutely no information from the<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;spec that you don&#39;t get from the implementation itself.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Hopefully that clarifies why I don&#39;t feel that specs like these are<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;valuable.&nbsp;&nbsp;I also hope that this helps others develop heuristics for<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;when to write/delete/ignore tests.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;With that out of the way, how would I specify this SomeModel class?<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Well, if the class is as given and there&#39;s no business logic, then I<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;would only write a couple specs for SomeModel directly.&nbsp;&nbsp;These would<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;be specs for the widgets association.<br>
 &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;describe SomeModel, &quot;widgets&quot; do<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; before(:each) do<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp; @model = SomeModel.create!<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp; BaseWidget.create! :some_model_id =&gt; @<a href="http://model.id">model.id</a><br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; end<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it &quot;should find BaseWidgets&quot; do<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp; @model.should have(1).widget<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; end<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; it &quot;should nullify keys when deleting the widgets&quot; do<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp; lambda { @model.widgets.destroy_all }.should_not change(BaseWidget, :count)<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp; @model.should have(0).widgets<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp; end<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;end<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;The reason I would do this is because there&#39;s a greater chance that<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;some of this stuff could break.&nbsp;&nbsp;None of the other associations will.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Looking back at this, I&#39;m not sure that I would write the second<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;example.&nbsp;&nbsp;The reason I might not write it is that I don&#39;t think I have<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;enough information.&nbsp;&nbsp;The foreign keys get nulled out when I call<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;#destroy_all, but that&#39;s something that I know from the has_many<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;declaration, and that I know works.&nbsp;&nbsp;My real question at this point is<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;WHY I want the keys nulled out instead of just deleting the records.<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Do I have some requirement in the system that these associations<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;should be broken, but the child records should stick around?&nbsp;&nbsp;If so, I<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;should have another spec that demonstrates that behavior.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;These associations *should* be tested, but they should be tested<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;indirectly from _somewhere else_.&nbsp;&nbsp;They&#39;re not important enough to<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;deserve tests at such a low granularity.&nbsp;&nbsp;They should be tested via an<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;acceptance test where a view iterates through them, or some test which<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;calls a DB aggregate method on the proxy.&nbsp;&nbsp;They don&#39;t have any<br>
 &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;interesting behavior on their own, and we are concerned primarily with<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;behavior.<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Does that help?<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;Pat<br> &gt;&nbsp;&nbsp;&gt;<br> &gt;<br> &gt;<br>
 &gt;<br> &gt;<br> &gt; --<br> &gt;&nbsp;&nbsp;Zach Dennis<br> &gt;&nbsp;&nbsp;<a href="http://www.continuousthinking.com">http://www.continuousthinking.com</a><br> &gt;&nbsp;&nbsp;_______________________________________________<br> &gt;<br> &gt;<br> &gt; rspec-devel mailing list<br>
 &gt;&nbsp;&nbsp;<a href="mailto:rspec-devel@rubyforge.org">rspec-devel@rubyforge.org</a><br> &gt;&nbsp;&nbsp;<a href="http://rubyforge.org/mailman/listinfo/rspec-devel">http://rubyforge.org/mailman/listinfo/rspec-devel</a><br> &gt;<br> _______________________________________________<br>
 rspec-devel mailing list<br> <a href="mailto:rspec-devel@rubyforge.org">rspec-devel@rubyforge.org</a><br> <a href="http://rubyforge.org/mailman/listinfo/rspec-devel">http://rubyforge.org/mailman/listinfo/rspec-devel</a><br>
 </blockquote></div><br>