I added a unit test manually to test a library I'm building. I have some fixtures which are tested in their corresponding models without any issues.
The test case inherits from ActiveSupport::TestCase which runs fixtures :all.
require 'test_helper'
require 'mylib'
class MyLibTest < ActiveSupport::TestCase
#user = User.find(1)
test "Setup" do
assert_equal(#user.id, 1)
end
end
Even though user = User.find(1) works fine in every test that is actually for a model, this test raises an exception: /Library/Ruby/Gems/1.8/gems/activerecord-3.0.0.beta4/lib/active_record/relation/finder_methods.rb:287:in 'find_one': Couldn't find User with ID=1 (ActiveRecord::RecordNotFound)
I have tried moving fixtures :all into the MyLibTest-class (suggested in another post) but with no difference.
How can I make my test work?
EDIT
I found out what was wrong, and it wasn't at all related to the fixtures. I wanted to use the same User object in several test cases so I added #user = User.find inside the class, but not inside a testcase. When I realized this and tried putting it in a test case, everything worked. Awkward :)
I can't be too sure exactly whats up without seeing how your Fixtures file is set up, but try these:
Try moving "fixtures :all" to test_helper.rb.
In the fixtures files, are you setting "id:" on each record? If not, the id is actually not going to be simply incremental - it is created based on the name of the fixture. Try using "User.first" instead of User.find(1). If you need the id to be 1, then set "id: 1" on the fixture.
Hope this helps.
Related
I've been in Factory land for the past few years and have decided to come back to fixtures but am running into a problem.
In my test_helper.rb I have
class ActiveSupport::TestCase
fixtures :all
end
Then in an individual test case I might be doing something like users(:one) however the data for users(:two) and the data for other tables that I am not calling on seems to be present in the test database.
So, is this the expected behavior? I have a hard to believing it is, seems strange from an isolated testing perspective.
This happens because you load all the fixtures at once from fixtures :all statement. A rule of thumb in tests is to load only the required data for a given test (not all). This also could slow down your test running time.
If you want to load only the selected fixtures you could do
fixtures :<fixture name>
Ex:
fixtures :users
Read more about fixtures.
One more thing, do you have a particular reason to comeback to fixtures. Factories are the way to go; they allow you do organize your test data cleanly.
Read more about factories.
I want my rspec tests to load my YAML fixtures, and I want them to be loaded inside the transaction, so that they disappear after each test.
describe "the thing I'm testing"
fixtures :sandwiches, :condiments
before(:each) do
# stuff
end
it "makes sandwiches"
# making sandwiches
end
end
When the call to fixtures is there (in the describe block, but not in the before block), it loads my sandwiches and condiments, but outside of the transaction, and thus committed. Well, it looks that way; what's certain is that my fixtures are still in the db after the test finishes.
I thought perhaps I could put the call to fixtures in the before block, inside the transaction, but then I get
NoMethodError: undefined method `fixtures' for
<RSpec::Core::ExampleGroup::Nested_1:0x007fd1f11f7578>
So I guess I could use DatabaseCleaner, or something similar, but...can't I get what I want without that?
fixtures is a Rails method (not RSpec) that, afaik, doesn't actually load the fixtures - just registers them for loading later.
It is a class method, so it has to run in the class (the ExampleGroup returned by describe) and not the instance in which before, it, etc are evaluated.
Do you have config.use_transactional_fixtures = true in spec_helper.rb?
I'd like to init the data base once everytime i run tests, rather than every test.
I know with Rspec there is before(:all), but I haven't been able to get that working. I was wondering if rails had something similar.
Firstly: there used to be a before(:all) equivalent in Test::Unit but it was removed (don't know why).
Secondly: there are very good reasons not to do what you are trying to do - tests are meant to be run independently of one another, not rely on state that's in the db. This way you can guarantee that it's testing exactly what you are expecting it to test.
If you have one test that changes the state of the db, and you move it and it runs after another test which expects it to be another state - you run into problems. Thus, all test must be independent.
Thus: the db is rolled back to its pristine state and re-seeded every time.
If you really want some state that the db is always in - then set it up in the fixtures... and just realise that the db will be re-loaded for each test.
If you are having trouble with load-times... then consider figuring out some other way around the problem - eg don't use huge numbers of fixtures, instead use Factories to only create the data that you need for each individual test.
If there's some other reason... let us know - we may have a solution for it.
Edit: if you really need it, I actually wrote a monkey patch for this a long while back:
"faking startup and shutdown"
All things to run before everything just go in the top of the class
require 'test_helper'
class ObjectTest < ActiveSupport::TestCase
call_rake("db:bootstrap RAILS_ENV=test")
#set up our user for doing all our tests (this person is very busy)
#user = Factory(:user)
#account = Factory(:account)
#user.account = #account
#user.save
# make sure our user and account got created
puts "||||||||||||||||||||||||||||||||||||||||||||||"
puts "| propsal_test.rb"
puts "| #{#user.name}"
puts "| #{#user.account.name}"
puts "||||||||||||||||||||||||||||||||||||||||||||||"
I've got a functional test that's using fixtures. I also am using fixtures in my Unit tests, but they work without flaw. When running the functional tests, I get a:
NoMethodError: undefined method 'recycle!' for #<Response:0x10346be10>
/test/functional/responses_controller_test.rb:10:in 'test_testing'
My functional tests, at this point, are doing nothing more than a get to the index action. Example:
setup do
#response = responses(:one)
end
test "testing" do
get :index
assert true
end
My TestHelper class does include all fixtures, so the Responses fixtures are definitely loading. And like I said, the fixtures work perfectly fine in Unit tests.
Any idea what might be causing this?
Change
setup do
#response = responses(:one)
end
to
setup do
#myresponse = responses(:one)
end
and off you go!
The problem lies in "actionpack-3.0.1/lib/action_controller/test_case.rb" around line 386.
The testcase assumes that #response holds a "ActionDispatch::Response". You overwrite it, it's no "ActionDispatch::Response" anymore and the testcase fails.
I'm not sure if this is intended behaviour.
Anyway, just make sure you don't overwrite #response/#request/#controller/#routes and it should work.
Flo's answer is mostly correct, but I just wanted to clarify:
In Rails 3.0.x that #request is expected to be an ActionController::TestRequest type, which has the recycle! method defined on it. There's TestResponse, TestRequest, and TestSession.
You might want to actually initialize or manipulate objects of these types for certain situations. In my case, I needed to mock the site having a specific domain name with
#request = ActionController::TestRequest.new unless #request
#request.host = "www.hostname.com"
I just had a similar problem naming a variable #request.
I changed to #_request and it solved the problem.
I'm trying to perform an integration test via Watir and RSpec. So, I created a test file within /integration and wrote a test, which adds a test user into a base via factory_girl.
The problem is — I can't actually perform a login with my test user. The test I wrote looks as following:
...
before(:each)
#user = Factory(:user)
#browser = FireWatir::Firefox.new
end
it "should login"
#browser.text_field(:id, "username").set(#user.username)
#browser.text_field(:id, "password").set(#user.password)
#browser.button(:id, "get_in").click
end
...
As I'm starting the test and see a "performance" in browser, it always fires up a Username is not valid error.
I've started an investigation, and did a small trick. First of all I've started to have doubts if the factory actually creates the user in DB. So after the immediate call to factory I've put some puts User.find stuff only to discover that the user is actually in DB. Ok, but as user still couldn't have logged in I've decided to see if he's present in DB with my own eyes.
I've added a sleep right after a factory call, and went to see what's in the DB at the moment. I was crushed to see that the user is actually missing there! How come? Still, when I'm trying to output a user within the code, he is actually being fetched from somewhere. So where does the records, made by factory_girl within a runtime lie? Is it test or dev DB? I don't get it.
I've 10 times checked if I'm running my Mongrel in test mode (does it matter? I think it does, as I'm trying to tun an integration test) and if my database.yml holds the correct connection specific data.
I'm using an authlogic, if that can give any clue (no, putting activate_authlogic doesn't work here).
Don't forget that RSpec is probably using transations when running the specs. RSpec will wrap the execution of the spec within a transaction and rollback at the end. It means you won't be able to see the record from outside that transaction (i.e. from another SQL connection).
If you want to ensure the user record is actually created by Factory Girl, you can do something like:
before(:each)
#user = Factory(:user)
User.find_by_username(#user.username).should_not be_nil
#browser = FireWatir::Firefox.new
end
Somehow the solution went strange — I put factories to before(:all) block, and all the stuff worked as it should.
Factory Girl is going to create temporary DB entries in your test database. Your tests database is going to be cleared out after each test.