<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>The Dev Blog: Testing: DRYing the Asserting of Array Similarity</title>
    <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Putting Family Management on Rails!</description>
    <item>
      <title>Testing: DRYing the Asserting of Array Similarity</title>
      <description>&lt;p&gt;After one too many instances of:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;ph&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;contacts&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:john&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;phones&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;collect&lt;/span&gt;&lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;p&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;number&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ph&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;
&lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;[].&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;12345&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;56789&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;67890&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;ph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I decided it's time to DRY up array similarity checking. Using &lt;strong&gt;assert_equal&lt;/strong&gt; on arrays is a so-so solution, given that you don't always know if the order in the array is the same. Returning  an array from a &lt;strong&gt;has_many&lt;/strong&gt; collection has a non-deterministic order by default. So asserting that what we get from a collection is a bit painfull, and require the code above to make absolutely sure we got what we wanted.&lt;/p&gt;

&lt;p&gt;To make my life easier and DRYer, I added the following function to the &lt;strong&gt;test/test_helper.rb&lt;/strong&gt; file:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;assert_array_similarity&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;actual&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;full_message&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;build_message&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&amp;lt;?&amp;gt; expected but was&lt;span class="escape"&gt;\n&lt;/span&gt;&amp;lt;?&amp;gt;.&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;actual&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_block&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;full_message&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt;  &lt;span class="ident"&gt;actual&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;expected&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;actual&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;[])&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And now testing for array similarity is simply:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;assert_array_similarity&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;12345&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;56789&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;67890&lt;/span&gt;&lt;span class="punct"&gt;'],&lt;/span&gt; &lt;span class="ident"&gt;contacts&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:john&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;phones&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;collect&lt;/span&gt;&lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;p&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;number&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not bad, 1 line instead of 3 and better error reporting to boot.&lt;/p&gt;</description>
      <pubDate>Tue, 13 Feb 2007 06:21:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:1aad69f7-4179-47c2-9e59-dfb613871241</guid>
      <author>guy.naor@famundo.com (Guy Naor)</author>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity</link>
      <category>Rails</category>
      <category>Ruby</category>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Guy Naor</title>
      <description>&lt;p&gt;Joshua,&lt;/p&gt;

&lt;p&gt;Maybe I need a better name :-), but the operation is something I do all the time, and I'm sure other do as well, and DRYing it is very helpful.&lt;/p&gt;

&lt;p&gt;Got I deas for a better name?&lt;/p&gt;</description>
      <pubDate>Fri, 16 Feb 2007 07:58:42 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:495035cc-7a1b-4bca-957d-814060975362</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-39</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Joshua E Cook</title>
      <description>&lt;p&gt;Yeah, I disclaimed my approach by assuming that the elements would be unique.  However, if you &lt;em&gt;do&lt;/em&gt; intend for the elements to be unique within the collection, and there is a possibility of a bug causing doubled items, then I think it is appropriate to test for uniqueness separately.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ary = [1,1,2,3,4,5]
assert_equal ary, ary.uniq
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I realize you want to reduce the amount of code you're writing, but you also say you want to write precise tests.  I think that if you care about uniqueness, you should test for uniqueness.&lt;/p&gt;

&lt;p&gt;Something about &lt;code&gt;assert_array_similarity&lt;/code&gt; just has a bad smell about it to me.  Think about it this way:  sample a random group of programmers and ask them what "array similarity" means.  Then ask them what it means for a collection's items to be unique, and what it means for sets to be equal.  I assert you'll get many more consensus answers for the latter questions.&lt;/p&gt;</description>
      <pubDate>Fri, 16 Feb 2007 05:47:44 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:81d4486c-829d-4afd-887b-c05c958f318d</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-38</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Guy Naor</title>
      <description>&lt;p&gt;Joshua,&lt;/p&gt;

&lt;p&gt;Sets are fine, but it adds more code and more typing. I'm trying to save on those :-), and simplify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; Actually there's a much bigger problem with the set transformation in testing. One of the things I want to check is that the arrays contain exactly the same items. WOn't work with sets if the array have non-unique items.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;assert_array_similarity [1,2,3,4,5], [1,1,2,3,4,5]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Will fail. But this will pass:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;asset_equal  [1,2,3,4,5].to_set, [1,1,2,3,4,5].to_set
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which means that the set test is only good for same size arrays, or if you don't care aboutthe possibility of multiple items in the result.&lt;/p&gt;

&lt;p&gt;For testing I'm always for doing as exact a test as possible. What if because of some bug you get doubled items? The set with to_set won't find this bug.&lt;/p&gt;</description>
      <pubDate>Thu, 15 Feb 2007 14:24:09 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:8e227158-1bd5-4f9d-bc24-94ae27d504d4</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-35</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Joshua E Cook</title>
      <description>&lt;p&gt;I think you're approaching this problem incorrectly by comparing Arrays.  Assuming the uniqueness of elements within a collection, when the order of a collection's elements is not defined, the appropriate data structure is a Set, not an Array.&lt;/p&gt;

&lt;p&gt;I think something like this is more expressive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'set'
assert_equal contacts(:john).phones.map(&amp;amp;:number).to_set,
             ['12345','56789','67890'].to_set
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Thu, 15 Feb 2007 14:05:39 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ff5cacd3-0d98-41d8-ab3e-091eb26c0292</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-34</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Guy Naor</title>
      <description>&lt;p&gt;Duncan,&lt;/p&gt;

&lt;p&gt;Yeah, I could change it to empty and it would look a bit nicer. And the map is also a good shorthand.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;</description>
      <pubDate>Thu, 15 Feb 2007 12:50:09 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:34a9f05a-215f-4658-a6d0-8707e664e454</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-33</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Duncan Beevers</title>
      <description>&lt;p&gt;If the array you're examining is full of ActiveRecord models, (as ActiveRecord find calls often are) then you'd need to define a &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; method for the class in order for &lt;code&gt;sort!&lt;/code&gt; to work.&lt;/p&gt;

&lt;p&gt;Not that that's really a problem, but if sorting instances of itself isn't a primary function of your model, supporting sort! introduces unnecessary complexity.&lt;/p&gt;

&lt;p&gt;Handy little assertion for a reasonably common operation.&lt;/p&gt;

&lt;p&gt;I think &lt;code&gt;(expected - actual).empty?&lt;/code&gt; looks a little nicer.&lt;/p&gt;

&lt;p&gt;Also, you can clean up the actual assertion using something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;code&gt;assert&amp;#095;array&amp;#095;similarity ['12345', '56789', '67890'], contacts(:john).phones.map(&amp;:number)&lt;/code&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Thu, 15 Feb 2007 11:23:58 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3038be03-ecfe-4519-898c-e7060ba989fa</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-32</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Guy Naor</title>
      <description>&lt;p&gt;There's no problem with comparing with sort!, only problem is that once again it's less DRY. More things to write, and a lot less expressive.&lt;/p&gt;</description>
      <pubDate>Thu, 15 Feb 2007 06:12:01 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fb5236a4-d95b-4d5e-b98b-a4fa24a91814</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-31</link>
    </item>
    <item>
      <title>"Testing: DRYing the Asserting of Array Similarity" by Guillaume Theoret</title>
      <description>&lt;p&gt;I may be looking at this problem wrong, but if the only problem is the nondeterministic results why don't just just build an array of phone numbers manually, build an array of phone numbers from the db, call sort! on both and compare that?&lt;/p&gt;

&lt;p&gt;Disclaimer: I've never tried to assert contents of an array so the above might be completely wrong.&lt;/p&gt;</description>
      <pubDate>Wed, 14 Feb 2007 23:16:55 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:15b50e1a-2a62-4775-8c68-aa4f0f7b52b4</guid>
      <link>http://devblog.famundo.com/articles/2007/02/13/testing-drying-the-asserting-of-array-similarity#comment-30</link>
    </item>
  </channel>
</rss>
