开发者

Rails: Integration test data

I'm new to Rails testing and I'm confuse with the nature开发者_JAVA技巧 of rails integration test data:

test "should register new user and login" do
  ..
  # create user
  post users_path, :user => {:username => "newuser", :email => "newuser@gmail.com",
    :password => "secret",
    :password_confirmation => "secret"}
  assert assigns(:user).valid?
  ..
end

test "another should register new user and login" do
  ..
  # create user
  post users_path, :user => {:username => "newuser", :email => "newuser@gmail.com",
    :password => "secret",
    :password_confirmation => "secret"}
  assert assigns(:user).valid?
  ..
end

In the User model i have a validation to ensure that :username and :email are unique. But how come the test was able to post both data with no complain/error/invalid? Any help is appreciated, I thought there's a single DB only for the test and the test data should've clashed. Thanks.


Good question. Before the test framework (Test::Unit) runs each test it resets the database to its original state. So before each test you are guaranteed that the DB only has the fixture data and nothing else.

This is helpful. You don't want the data from one test still to be there when you start the next test. If it were, the DB state would be inconsistent if you did something like run a test by itself (instead of the whole suite) or run tests in a different order.

The solution: you can write a test that specifically verifies that the :username and :email are unique. Before I give an example, I should mention that it looks like you wrote a functional test for this validation. This is tempting because you're verifying the behavior the user will see, but the place to test validation is in the unit tests because validation rules in Rails get pushed down to the models. (To keep validation DRY. You don't have to duplicate your validation rules across a bunch of controllers)

So here's one way you could write the unit test:

test "should validate unique email" do
  attributes = { :username => "newuser", :email => "newuser@gmail.com", :password => "secret", :password_confirmation => "secret" }
  # create user
  user1 = User.create(attributes)
  assert_nil user1.errors.on(:username)
  assert_nil user1.errors.on(:email)

  # create another user with the same name and email
  user2 = User.create(attributes)
  assert_not_nil user2.errors.on(:username)
  assert_not_nil user2.errors.on(:email)
end

For a good article about this, see John Nunemaker's blog post from two years ago. Ignore the accidental HTML tags in his code samples. Nunemaker is an awesome Rails blogger.

There are some alternate testing libraries like Shoulda that have built-in functions to validate that your model validates uniqueness. But since you're new to Rails I'd recommend sticking with the default test framework for now. (In fact the folks at 37Signals who invented Rails still use the default too, so that says a lot for it. I also prefer to stick with the default.)

By the way, you can format code in a StackOverflow question by indenting it with four spaces.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜