Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

error in after(:each) block causes per-test transaction to not get rolled back (was: Nested transactions causing Postgres woe) #58

Closed
wjessop opened this Issue · 28 comments

6 participants

@wjessop

I'm using rspec-rails 2.0.0.beta.8 with a rails 3 beta app (just upgraded from rails 2.3.5) and postgres. I have a bunch of rspec tests that were previously working with rspec 1.3/rails 2.3.5. However upgrading to this latest rspec seems to cause issues because it is trying to open nested transactions which postgres doesn't support, this the console output from the test run:

WARNING: there is already a transaction in progress
WARNING: there is already a transaction in progress

I have configured rspec-rails to use_transactional_examples:

Rspec.configure do |config|
# …
config.use_transactional_examples = true
end

setting this to false gets rid of the nested transaction error, but in both cases I get:

"Validation failed: Email has already been taken, Login has already been taken"

Is this a bug, or a deliberate change, or just something i am doing wrong?

@mooman

you can nest transactions in PG, it'll just complain and not do anything.

I have the same issue. for me, i think it's the ORM im using (Sequel). seems like transactional support in rspec might just work with AR at the moment.

@wjessop

PG does complain about the error, but it does also break per feature transactions.

@mooman

maybe "Around hooks" for rspec (https://rspec.lighthouseapp.com/projects/16211-cucumber/tickets/605) can help wtih ORM that only does transactions inside a block? in fact, it would be useful for any other general cases where a block is needed too...

@wjessop

I think this should maybe be an "rspec-1 compat" issue, as these same tests are working fine on rails 2.3.5, rspec 1.3. Unless I'm missing some new configuration option?

@dchelimsky
Owner

Is this still a problem on beta.11?

@wjessop

Still getting the same with .11 and .12 (sorry for the lag, was away for a week)

@hosh

I've been using rspec-rails beta.12 with AR3.beta4, postgresql and I run into these issues I have config.use_transactional_examples true set in my spec_helper, but the examples are clearly not rolling back.

I had run into a similar issue while running rspec-rails beta.7. There were no warnings but the rspec was clearly not running the examples in transactions.

@dchelimsky
Owner

What makes you say "clearly not rolling back". There is a cucumber feature that shows this is working as expected, and all rspec is doing is tapping into rails' transaction management. Would you be willing to try to recreate the problem using a rails unit or functional test?

@wjessop

I can tell it's not rolling back for me because If I create a single user in one of my tests I get a duplicate user validation issue next test. If I take the same tests and run them on a rails 2.3.5/rspec 1.3 app they work just fine so maybe I'm missing some syntax changes?

What do you mean "Would you be willing to try to recreate the problem using a rails unit or functional test?" exactly?

@dchelimsky
Owner

I want to find out if this is an rspec problem or a rails problem. If you can create the same test(s) using rails' builtin testing framework and it all works, then we know we have an rspec problem. Otherwise we can push a ticket to rails.

@hosh

On my end, I ended up adding this snippet to my rspec https://gist.github.com/749ee589ccbd278c28b2

Using the before/after to explicitly do the db transactions, I get 6 stores created via Machinist.

Not having the explicit db transaction, I get 27 stores created via Machinist.

I have tried this with both config.use_transactional_examples true and config.use_transactional_examples false and get the same results

@sriedel

I have seen similar issues with mysql; they only happen occasionally with beta11 but constantly with beta12 (downgrading to beta11 without touching any code reverted to the original behaviour). If this is the same issue, it's either been introduced or aggravated recently.

@sriedel

A small update: It seems that when a test fails with an sql error (e.g. missing foreign key), the transaction isn't being cleaned up and test data is left in the database. This seems to be a separate issue, so I'll move to a separate ticket.

@dchelimsky
Owner

FYI - rspec is not really doing anything here - it just delegates off to active record - if you're using another ORM you should use database cleaner instead.

@dchelimsky
Owner

Maybe rspec-rails should just rely on database cleaner instead of AR - thoughts?

@hosh

What is database cleaner, is that a gem?

@dchelimsky
Owner

Yes. http://github.com/bmabey/database_cleaner. Cucumber uses it. Very reliable and offers two modes: transaction and truncation. Use transaction for in-memory testing and truncation for in-browser testing (since the app runs in a separate process from the tests).

@dchelimsky
Owner

Hey all - I finally got postgres set up, created an app using rails 3 beta 4, rspec rails 2 beta 12 and I can not reproduce this error or problem at all - transactions are rolling back correctly.

I'm closing for now but if someone can provide me with an example app (with all gems vendored) and I can run it and see the failure, I'll reopen.

@hosh

Have you tried running the spec from spec cli instead of rake spec? Since cli spec doesn't do the db purge, the specs run into problems when they depend on a clean database.

@dchelimsky
Owner

Rails transaction management (which rspec delegates to) assumes you're starting a run with the database in the condition you want it in.

@hosh

That's fine, but it doesn't clean it up properly at the end of the run, so it starts accumulating records.

@dchelimsky
Owner

If every example is running in transactions, there is nothing to clean up.

@hosh

Right, and the problem is that they are not all running in transactions. So every rake spec I run, it keeps adding more and more records.

Anyways, when I have time to pull away from this project for my employers, I'll set something up so you can see it for yourself, maybe narrow down where the problem is. My bet is that either AR or Rspec isn't covering some corner case that comes up when you're using PostgreSQL for a serious app. I've been running into this issue all day this morning and it's getting increasingly annoying.

@wjessop

OK, I think I've isolated it to an error in the after(:each) block causing the current test's transaction to not get rolled back. I created a demo app here:

http://github.com/wjessop/testfail

The interesting file is tentacle_spec.rb. If you run rake spec directly after cloning and migrating then the first test will fail because of a validation error (expected). However the second test fails because a user already exists in the database, we are still in the same transaction hence the error: WARNING: there is already a transaction in progress.

If you uncomment the begin/rescue stuff in the after(:each) block then the error is trapped and the transactions are handled as expected.

Interestingly if you re-comment the begin/rescue and comment out the Tentacle.create!(@valid_attributes) lines in each test and re-run the specs you get the real error (divided by 0) so a failing test masks an error in the after(:each) block.

This could be considered a regression from 1.2 as these specs worked there, though maybe more aggressive failing of the test suite in this situation would be appropriate?

@dchelimsky
Owner

@wjessop - that makes perfect sense! Thank you for tracking this down. I've opened a new issue for this in rspec-core: http://github.com/rspec/rspec-core/issues#issue/60

Cheers,
David

@tispratik

I am seeing this error ("there is no transaction in progress") with rspec-core '2.6.4'. I guess its not fixed yet. Do we need to use database_cleaner with rspec?

@tispratik

Sorry, my bad, i had not cleaned up the old data left over by the previous version of the gem.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.