views:

815

answers:

7

I have 357 tests (534 assertions) for my app (using Shoulda). The whole test suite runs in around 80 seconds. Is this time OK? I'm just curious, since this is one of my first apps where I write tests extensively. No fancy stuff in my app.

Btw.: I tried to use in memory sqlite3 database, but the results were surprisingly worse (around 83 seconds). Any clues here?

I'm using Macbook with 2GB of RAM and 2GHz Intel Core Duo processor as my development machine.

+1  A: 

It really depends on what your tests are doing. Test code can be written efficiently or not in exactly the same way as any other code can.

One obvious optimisation in many cases is to write your test code in such a way that everything (or as much as possible) is done in memory, as opposed to many read/writes to the database. However, you may have to change your application code to have the right interfaces to achieve this.

DanSingerman
As I mentioned in my question, I tried to use in memory database, unfortunately with no success. :(
Milan Novota
Even if the db is in memory, there will probably be an overhead reading and writing to it.
DanSingerman
How big is the db? - if putting more stuff in memory slows it down, it may be that the system is paging.
Pete Kirkham
+2  A: 

I don't feel this question is rails specific, so I'll chime in.

The main thing about testing is that it should be fast enough for you to run them a lot (as in, all the time). Also, you may wish to split your tests into a few different sets, specifically things like 'long running tests' and 'unit tests'.

One last option to consider, if your database setup is time consuming, would be to create your domain by restoring from a backup, rather than doing a whole bunch of inserts.

Good luck!

Travis
+1  A: 

Large test suites can take some time to run.

I generally use "autospec -f" when developing, this only runs the specs that have changed since the last run - makes it much more efficient to keep your tests running.

Of course, if you are really serious, you will run a Continuous Integration setup like Cruise Control - this will automate your build process and run in the background, checking out your latest building and running the suite.

Toby Hede
I've been using autotest for quite a long time now and set up a CI server just couple of days ago. I'm very happy with that.
Milan Novota
+1  A: 

If you're looking to speed up the runtime of your test suite, then I'd use a test server such as this one from Roman Le Négrate.

Mr. Matt
That seems pretty interesting. How does it compare to autotest?
Milan Novota
Autotest just reruns the tests on each invocation, loading your rails environment each time (AFAIK). A test server loads your environment on startup, then reruns the tests without needing to reinitialize.
Mr. Matt
+2  A: 

You should try this method http://wiki.github.com/dchelimsky/rspec/spork-autospec-pure-bdd-joy using spork to spin up a couple of processes that stay running and batch out your tests. I found it to be pretty quick.

Danny Hawkins
Hey Danny! Does this work with Test::Unit/Shoulda?
Milan Novota
Hey Milan, as far as I'm aware the only guidance I can find is on rspec and spork, I don't see any reason why you couldn't adopt the same approach
Danny Hawkins
A: 

As opposite to inmemory SQLLite you can put MySQL database on RAMDISK (on windows) or on tmpfs on linux. Thus MySQL has a very efficient buffering, so putting database in memory does not help a lot until you updating a lot of data really often.

More significant is the way of test isolation and data preparation for each test.

You can use transactional fixtures. That means that each test will be wrapped into transaction and thus next test will start at the initial point.

This is faster than clean up database before each test.

There are situations when you want to use both transactions and explicit data erasing, here is a good article about: http://www.3hv.co.uk/blog/2009/05/08/switching-off-transactions-for-a-single-spec-when-using-rspec/

Grimmo
A: 

You can experiment with preloading fixtures, but it will be harder to maintain, and, IMHO, not worth it's speed improvements (20% maximum I think, but it depends)

It's known that SQLite is slower than mysql/pgsql, excepting very small, tiny DBs.

As someone already said, you can put mysql (or other DB) datafiles on some kind of RAMDisk (I use tmpfs on linux).

PS: we have 1319 Rspec examples now, and it runs for 230 seconds on C2D-3Ghz-4GRam, and I think it's fine. So, yours is fine too.

zed_0xff