Matt Wynne wrote:
> So we've got a pretty decent number of specs now, and despite my best
> efforts, AR is just forcing us down the path of having to use database
> interaction for some of the model specs.
>> It's starting to get tiring to run all the specs now, which is making
> me sad, and making me worry about how things are going to be in a few
> months from now.
>> I'd like to somehow be able to systematically mark the slow example
> groups as being 'impure' and thus be able to choose to mostly ignore
> them during my regular TDD cycle, just running them every so often as
> a regression.
>> I'm thinking something like this:
>> describe "when there are ten users in the database", :slow => true do
>> What do you think? How are other people solving this problem? Any tips
> / thoughts on how I could implement this?
>
Hey Matt,
In order to keep my object-level examples on the unit-test speed (less
than 0.1 sec) I have been using NullDB to disconnect my entire suite
from the DB. I do this by requiring nulldb and then setting the adapter
in my spec_helper.rb:
# Turn DB off by default for specs
ActiveRecord::Base.establish_connection(:adapter => :nulldb)
This helps immensely because you can still use your regular AR objects
and you can even call #save and #create and get unique ids back. There
are some caveats and gotchas associated with the style but I think it is
well worth it. The largest caveat is that you can not do SELECTs. In a
way this has been very good for the design of my current project because
it forces me to use stubbing and push my custom finders in they own
methods on different classes/objects. Once I have isolated the finders
in their own methods then I turn on the regular db adapter to write
examples against for it. The fact that it is isolated though allows me
to test with a small dataset which generally is quite faster than the
other datasets that would of been needed in my examples that I stubbed
results for.
To turn my real database on for individual examples this is the code I use:
unless Object.const_defined?(:Functional)
share_as :Functional do
before :all do
ActiveRecord::Base.establish_connection(:test)
end
after :all do
ActiveRecord::Base.establish_connection(:adapter => :nulldb)
end
end
end
Then in the example I say:
describe "when there are ten users in the database" do
include Functional
....
end
I have actually also implemented what you have suggested so I can also say:
describe "when there are ten users in the database", :functional => true do
...
end
I was going to use that implementation to have the runner only run the
type of examples I want to at a given moment. However, I think I'm
going organize my examples by directories because that is already
supported in rspec. So, as Pat already mentioned, it would look
something like:
spec/
functional/
models/
object-level/
controllers/
models/
I should also say that in some of my cases I have not been doing any functional examples. That is because I have been using Stories/Fearures to drive the entire process so I just let them test my SQL against a real DB when I'm not doing anything out of regular AR.
HTH,
Ben