<?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>Virtuous Code &#187; database</title>
	<atom:link href="http://devblog.avdi.org/tag/database/feed/" rel="self" type="application/rss+xml" />
	<link>http://devblog.avdi.org</link>
	<description>&#34;The three virtues of a programmer: laziness, impatience, and hubris&#34; -- Larry Wall</description>
	<lastBuildDate>Fri, 17 May 2013 15:24:41 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Configuring database_cleaner with Rails, RSpec, Capybara, and Selenium</title>
		<link>http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/</link>
		<comments>http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/#comments</comments>
		<pubDate>Fri, 31 Aug 2012 04:00:00 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[capybara]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://devblog.avdi.org/?p=2620</guid>
		<description><![CDATA[How I avoid finding myself in database bizarro world while testing Rails apps. <a href="http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>If you write Rails code, or any Ruby code that interacts with a database, and you also write automated tests, chances are you have heard of or used the <a href="https://github.com/bmabey/database_cleaner">database_cleaner</a> gem. It&#8217;s a terrific gem that abstracts away the various ORM APIs for getting the DB into a &#8220;blank slate&#8221; state. </p>
<p> Periodically I start a new project using Rails, with RSpec, Capybara, and Selenium for acceptance testing, and a short way into it I find myself banging my head against bizarre inconsistencies with the test database. I&#8217;ll set up some records in the test DB, only to have the Selenium-driven browser-based tests act like those records never existed. Eventually, I&#8217;ll realize what I did wrong and curse my feeble brain for not remembering the last time I solved the same problem. </p>
<p> The problem is always the same: the tests are being wrapped in database transactions, so any code running outside the actual test process (like, say, a server process servicing a Selenium-driven browser request) <em>does not see</em> the database fixture I&#8217;ve so carefully assembled. </p>
<p> I just walked a <a href="http://devblog.avdi.org/pair-programming-services/">pairing</a> client through the same fix, so in the interests of remembering the steps, and hopefully preventing some other folks from tearing their hair out, here are the steps needed. </p>
<p> First of all, and this is very important, go into <code>spec/spec_helper.rb</code> and change this line: </p>
<pre class="src src-ruby">config.use_transactional_fixtures = <span class="org-variable-name">true</span>
</pre>
<p> To: </p>
<pre class="src src-ruby">config.use_transactional_fixtures = <span class="org-variable-name">false</span>
</pre>
<p> This will disable rspec-rails&#8217; implicit wrapping of tests in a database transaction. Without disabling this, none of the following configuration will matter. </p>
<p> Now configure <code>database_cleaner</code>. I usually create a separate file called <code>spec/support/database_cleaner.rb</code> for this. Inside, I put something like this: </p>
<pre class="src src-ruby"><span class="org-type">RSpec</span>.configure <span class="org-keyword">do</span> |config|

  config.before(<span class="org-constant">:suite</span>) <span class="org-keyword">do</span>
    <span class="org-type">DatabaseCleaner</span>.clean_with(<span class="org-constant">:truncation</span>)
  <span class="org-keyword">end</span>

  config.before(<span class="org-constant">:each</span>) <span class="org-keyword">do</span>
    <span class="org-type">DatabaseCleaner</span>.strategy = <span class="org-constant">:transaction</span>
  <span class="org-keyword">end</span>

  config.before(<span class="org-constant">:each</span>, <span class="org-constant">:js</span> =&gt; <span class="org-variable-name">true</span>) <span class="org-keyword">do</span>
    <span class="org-type">DatabaseCleaner</span>.strategy = <span class="org-constant">:truncation</span>
  <span class="org-keyword">end</span>

  config.before(<span class="org-constant">:each</span>) <span class="org-keyword">do</span>
    <span class="org-type">DatabaseCleaner</span>.start
  <span class="org-keyword">end</span>

  config.after(<span class="org-constant">:each</span>) <span class="org-keyword">do</span>
    <span class="org-type">DatabaseCleaner</span>.clean
  <span class="org-keyword">end</span>

<span class="org-keyword">end</span>
</pre>
<p> Let&#8217;s take that step by step. </p>
<pre class="src src-ruby">config.before(<span class="org-constant">:suite</span>) <span class="org-keyword">do</span>
  <span class="org-type">DatabaseCleaner</span>.clean_with(<span class="org-constant">:truncation</span>)
<span class="org-keyword">end</span>
</pre>
<p> This says that before the entire test suite runs, clear the test database out completely. This gets rid of any garbage left over from interrupted or poorly-written tests&mdash;a common source of surprising test behavior. </p>
<pre class="src src-ruby">config.before(<span class="org-constant">:each</span>) <span class="org-keyword">do</span>
  <span class="org-type">DatabaseCleaner</span>.strategy = <span class="org-constant">:transaction</span>
<span class="org-keyword">end</span>
</pre>
<p> This part sets the default database cleaning strategy to be transactions. Transactions are very fast, and for all the tests where they <em>do</em> work&mdash;that is, any test where the entire test runs in the RSpec process&mdash;they are preferable. </p>
<pre class="src src-ruby">config.before(<span class="org-constant">:each</span>, <span class="org-constant">:js</span> =&gt; <span class="org-variable-name">true</span>) <span class="org-keyword">do</span>
  <span class="org-type">DatabaseCleaner</span>.strategy = <span class="org-constant">:truncation</span>
<span class="org-keyword">end</span>
</pre>
<p> This line <em>only</em> runs before examples which have been flagged <code>:js =&gt; true</code>. By default, these are the only tests for which Capybara fires up a test server process and drives an actual browser window via the Selenium backend. For these types of tests, transactions won&#8217;t work, so this code overrides the setting and chooses the &#8220;truncation&#8221; strategy instead. </p>
<pre class="src src-ruby">config.before(<span class="org-constant">:each</span>) <span class="org-keyword">do</span>
  <span class="org-type">DatabaseCleaner</span>.start
<span class="org-keyword">end</span>

config.after(<span class="org-constant">:each</span>) <span class="org-keyword">do</span>
  <span class="org-type">DatabaseCleaner</span>.clean
<span class="org-keyword">end</span>
</pre>
<p> These lines hook up <code>database_cleaner</code> around the beginning and end of each test, telling it to execute whatever cleanup strategy we selected beforehand. </p>
<p> And that&#8217;s it! </p>
<p> Note that this is all for RSpec, and does not cover Cucumber configuration. </p>
<p> Hopefully this will help someone else out there avoid the frustrations I&#8217;ve run into! </p>
<p> EDIT: A few people have asked me why I don&#8217;t just force all threads to share the same ActiveRecord connection, as demonstrated <a href="https://gist.github.com/470808">in this Gist</a>. A few reasons: </p>
<ul>
<li>Using <code>database_cleaner</code> implies that I want ORM   neutrality. <code>database_cleaner</code> supports ActiveRecord, DataMapper,   MongoMapper, and others. The solution linked above only works for   ActiveRecord.  </li>
<li>It&#8217;s a monkey-patched kludge which will only work so long as AR   refrains from changing its connection-sharing internals. And frankly   I&#8217;m not sure I trust it to work across all Ruby VM and database   combinations (UPDATE: And indeed, I&#8217;ve now seen two different people   say there are race conditions with the current Postgres   adapter). I&#8217;d be more inclined to use it if ActiveRecord had a   published configuration option which was known to work in all   contexts.  </li>
<li>As I stressed above, I&#8217;m careful to set things up so that only the   tests that need them fall back to truncation. Since <code>:js =&gt; true</code>   tests generally don&#8217;t form the bulk of my suite (and since they are   unavoidably slow anyway, due to the overhead of driving a browser),   I&#8217;m not overly concerned about the added overhead. Perhaps if all of   my acceptance tests drove a live browser I&#8217;d be more worried about   it.  </li>
<li>In cases where database truncation <em>is</em> taking up a significant   amount of test time, you can usually speed things up with some   judicious control of which subset of tables get truncated for a   given test. This is something <code>database_cleaner</code> makes pretty   easy. Maybe that would make a good topic for a followup post.  </li>
<li>UPDATE: Oh yeah, and as <a href="https://twitter.com/donaldball/status/241548932415635456">@donaldball points out</a>, sharing a   transaction between test and test server means acceptance tests   don&#8217;t run quite the same as they would in production. Specifically,   they&#8217;ll never trigger <code>after_commit</code> hooks. </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>New maintainer needed for NullDB</title>
		<link>http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/</link>
		<comments>http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 17:45:18 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[nulldb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://devblog.avdi.org/?p=2237</guid>
		<description><![CDATA[NullDB, for those who don&#8217;t know, is a null backend for ActiveRecord. Unlike RSpec&#8217;s stub_object, rather than raise an exception on DB access, will NullDB DB interactions simply become no-ops. This is handy for things like testing after_save hooks in &#8230; <a href="http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="https://github.com/nulldb/nulldb">NullDB</a>, for those who don&#8217;t know, is a null backend for ActiveRecord. Unlike RSpec&#8217;s stub_object, rather than raise an exception on DB access, will NullDB DB interactions simply become no-ops. This is handy for things like testing after_save hooks in isolation.</p>
<p>Myron Marston has done a stellar job shepherding it through the Rails 3 transition, but he&#8217;s busy with <a href="https://github.com/myronmarston/vcr">other awesome projects</a> now and has asked me to look for a new maintainer. So: If you&#8217;re interested in helping keep NullDB up to date with the latest changes to ActiveRecord, please get in touch!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NullDB for DataMapper</title>
		<link>http://devblog.avdi.org/2009/10/27/nulldb-for-datamapper/</link>
		<comments>http://devblog.avdi.org/2009/10/27/nulldb-for-datamapper/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 14:00:29 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[nulldb]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=279</guid>
		<description><![CDATA[The first Ruby library I ever released, and still the one I get the most emails about, is NullDB. NullDB is an ActiveRecord database adapter which simply turns every database operation into a no-op. It is useful for speeding up &#8230; <a href="http://devblog.avdi.org/2009/10/27/nulldb-for-datamapper/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>The first Ruby library I ever released, and still the one I get the most emails about, is <a href="http://nulldb.rubyforge.org/">NullDB</a>. NullDB is an ActiveRecord database adapter which simply turns every database operation into a no-op. It is useful for speeding up tests which don&#8217;t rely on the database, as well as verifying that they are, in fact, independent of the database.</p>
<p>Lately I&#8217;ve been working with <a href="http://datamapper.org/">DataMapper</a> and I&#8217;d begun to wonder how difficult it would be to write a DataMapper version of NullDB. As it turns out, the answer is &#8220;trivially easy&#8221;. In fact, it probably doesn&#8217;t even warrant making a library out of it &#8211; all the tools needed are right in the DataMapper distribution.</p>
<p>The task of a DataMapper null adapter is simplified in comparison to the ActiveRecord version by dint of DataMapper&#8217;s differing architecture. Where ActiveRecord scans the DB schema to extrapolate tables and columns, DataMapper makes the model classes the sole canonical source of schema information. This means that all the mucking about with schema.rb files that the original NullDB had to do is unnecessary.</p>
<p>The simplest form of a null database adapter is one that simply raises an exception every time code tries to touch the database. This kind of null backend is useful when you want to ensure that the software under test is completely isolated from the database. Rails Views are one example of code which you might want to keep rigidly database-independent in this fashion.</p>
<p>Setting up this type of null database backend in DataMapper is trivial:</p>
<pre name="code" class="ruby">
  DataMapper.setup(:default, "abstract::")
</pre>
<p>This code uses the &#8220;abstract&#8221; adapter which comes with DataMapper. The Abstract adapter is primarily intended to provide a base class on which to build other adapters. But for our purposes it makes for a poor-man&#8217;s null database backend. Any attempt to write to or query from the database while this adapter is in effect will result in a NotImplementedError being raised:</p>
<pre name="code" class="ruby">
  p = Post.new(:title => "NullDB for DataMapper")
  p.save # => NotImplementedError
</pre>
<p>What if we want to incoporate this technique into a complete test suite which includes both database-dependent and database-free tests? We need a way to make the null database active only while selected tests are being run. Once again, DataMapper&#8217;s design makes it easy to achieve our ends. DataMapper incorporates the concept of a  &#8220;repository stack&#8221;. instead of only having a single database adapter active for a whole session, or having different models tied to different adapters, DataMapper keeps a stack of adapter sessions in a stack. New sessions can be pushed onto the stack, and then popped off when they are no longer needed.</p>
<p>Here&#8217;s an example of how to set up a single Test::Unit test case to use a null database backend, while leaving other tests unaffected:</p>
<pre name="code" class="ruby">
class FooTest < Test::Unit::TestCase
  def setup
    DataMapper.setup(:null, "abstract::")
    DataMapper::Repository.context.push(DataMapper.repository(:null))
  end

  def teardown
    DataMapper::Repository.context.pop
  end

  def test_bar
    # ...
  end
end
</pre>
<p>There's one kind of test that NullDB enables which the code we've looked at so far does not allow. That is, testing of after-save hooks. We can't test an after-save hook with the code above, because a call to <code>#save</code> will error out before it ever gets to the after-save callback.</p>
<p>While DataMapper does not include an actual null-object style backend which turns all database operations into no-ops, it includes something close which will permit us to test after-save hooks. DataMapper ships with an in-memory store, which implements the DataMapper API in terms of a simple in-memory collection of Ruby objects. Here's an example of triggering an after-save hook with an in-memory backend:</p>
<pre name="code" class="ruby">
class Foo
  include DataMapper::Resource

  property :id, Serial

  after :save do
    puts "Saved!"
  end
end

DataMapper.setup(:ephemeral, "in_memory::")

DataMapper.repository(:ephemeral) do
  f = Foo.new
  f.save
end
</pre>
<p>Running this script produces the output <tt>Saved!</tt>. This code also demonstrates the block-form of the the <code>DataMapper.repository</code> method, which pushes a session onto the repository stack, yields to the passed block, and then pops the session back off the stack.</p>
<p>So there you have it, a couple of quick and easy ways to approximate a null-database in DataMapper. I think it&#8217;s a testament to DataMapper&#8217;s design that it&#8217;s so easy to assemble the pieces it provides in ways that the writers may not have anticipated. I hope you find these techniques useful!</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2009/10/27/nulldb-for-datamapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
