<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Carbon Emitter &#187; fixtures</title>
	<atom:link href="http://blog.carbonfive.com/tag/fixtures/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.carbonfive.com</link>
	<description>The blog of Carbon Five</description>
	<lastBuildDate>Thu, 19 Apr 2012 16:48:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>assert_changes and assert_no_changes in Ruby</title>
		<link>http://blog.carbonfive.com/2009/04/03/assert_changes-and-assert_no_changes-in-ruby/</link>
		<comments>http://blog.carbonfive.com/2009/04/03/assert_changes-and-assert_no_changes-in-ruby/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 17:26:51 +0000</pubDate>
		<dc:creator>Andy Peterson</dc:creator>
				<category><![CDATA[Process]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[fixtures]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=567</guid>
		<description><![CDATA[Update: This code and documentation is now available on github: http://github.com/ndp/assert_changes/tree/master The Problem On our work on gobalto.com, we spend time to have good fixture data for our tests&#8211; data that can represent all the important application states that our &#8230; <a href="http://blog.carbonfive.com/2009/04/03/assert_changes-and-assert_no_changes-in-ruby/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3><span style="color:#000080;">Update:</span><span style="color:#000080;"> This code and documentation is now available on github:<a href="http://github.com/ndp/assert_changes/tree/master" target="_blank"> http://github.com/ndp/assert_changes/tree/master</a></span></h3>
<h2>The Problem</h2>
<p>On our work on <a href="http://www.gobalto.com">gobalto.com</a>, we spend time to have good fixture data for our tests&#8211; data that can represent all the important application states that our tests require. As a result, our tests are very dependent on the data. It&#8217;s important that someone doesn&#8217;t inadvertantly change it in subtle ways. This has led us to write not only asserts at the end of tests, but pre-conditions as well. For example,</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">    ...
    inotech = companies(:inotech)
    assert inotech.services.public.include?(categories(:a))
    assert inotech.services.public.include?(categories(:b))
    assert inotech.services.public.include?(categories(:c))

    post :edit_services_dialog, :id=&amp;gt;inotech.id,
                                          :service_category_id=&amp;gt;categories(:a).id
    inotech.reload

    assert inotech.services.public.include?(categories(:a))
    assert !inotech.services.public.include?(categories(:b))
    assert !inotech.services.public.include?(categories(:c))</pre>
<p>Although the pre-conditions were introduced to guard against accidentally changing fixture data (or just to figure out what&#8217;s going on), we don&#8217;t necessarily delete them. They provide stronger tests. And in some ways, leaving in pre-conditions make the code more readable by providing documentation of your assumptions to the readers. The code above would be hard to follow without the clarifying pre-conditions. What do we expect to change and what stays the same?</p>
<p>Unfortunately all these asserts make the tests twice as long. And there&#8217;s a subtle readability problem: there&#8217;s no relationship between the corresponding pre- and post-conditions. In the example above, you have to scan carefully to see that the three assertions are repeated, but negated (b and c only). The reader must mentally put pieces together. And it&#8217;s not DRY. Using local variables doesn&#8217;t help much.</p>
<h2>The Solution</h2>
<p>I was inspired by a nice little test helper called assert_difference. It takes a string to evaluate and a block to execute. It&#8217;s useful for checking on state changes&#8211; especially database changes&#8211; during a test:</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">assert_difference('Company.count', -1) do
    Company.delete_one
end</pre>
<p>(Without this method, we rely on a count of all database records, or merely look for specific ones. The former approach leads to brittle tests, and the latter to incomplete assertions.)</p>
<p>A limitation of assert_difference is that it only deals with integers. What if it were generalized? Here goes:</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">    i = true
    assert_changes 'i' =&amp;gt; false do   # read as: i changes to false
      i = false
    end</pre>
<p><span id="more-567"></span>The string passed to assert changes is evaluated in the block context, both before and after the block is run. So this block asserts that i becomes false (and by deduction, starts out as true). It executes asserts on both ends, just like we want.</p>
<p>Of course sometimes you want to be explicit about a state change, so you can specify both the starting and ending values using an array:</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">    o.answer = 'yes'
    assert_changes 'o.answer' =&amp;gt; ['yes','no'] do
      o.answer = 'no'
    end</pre>
<p>To handle the original example, you can pass multiple pre/post conditions of arbitrary complexity and they are all evaluated before and after the block is executed:</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">      assert_changes 'post(:a).status' =&amp;gt; [:preview, :published],
                            'comment(:c).status' =&amp;gt; [:preview, :deleted] do
        ...
      end</pre>
<p>Finally, I added support for a :no_change symbol. Now I can re-write my original problem in a clearer form:</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">    assert_changes
        'inotech.services.public.include?(categories(:a))' =&amp;gt; [true, :no_change],
            'inotech.services.public.include?(categories(:b))'=&amp;gt;false,
            'inotech.services.public.include?(categories(:c))'=&amp;gt;false do
      post :edit_services_dialog, :id=&amp;gt;inotech.id, :service_category_id=&amp;gt;categories(:a).id
      inotech.reload
    end</pre>
<p>For completeness, I added assert_no_changes, with slightly extended parameter possibilities:</p>
<pre class="brush: ruby; light: true; title: ; wrap-lines: false; notranslate">    i,j = 'hello','hi'
    assert_no_changes 'i' do ...  # i (before) == i (after)
    assert_no_changes 'i'=&amp;gt;'hello' do ... # i == 'hello' before and after
    assert_no_changes ['i','j'] do ... # neither i or j change
    assert_no_changes 'i'=&amp;gt;'hello','j'=&amp;gt;'hi' do # or be explicit</pre>
<h3><span style="color:#000080;">Update:</span><span style="color:#000080;"> This code and documentation is now available on github:<a href="http://github.com/ndp/assert_changes/tree/master" target="_blank"> http://github.com/ndp/assert_changes/tree/master</a></span></h3>
<p>Thoughts? Comments?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2009/04/03/assert_changes-and-assert_no_changes-in-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

