Rails:集成测试数据

发布于 2024-10-11 17:13:20 字数 985 浏览 1 评论 0原文

我是 Rails 测试的新手,我对 Rails 集成测试数据的性质感到困惑:

test "should register new user and login" do
  ..
  # create user
  post users_path, :user => {:username => "newuser", :email => "[email protected]",
    :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 => "[email protected]",
    :password => "secret",
    :password_confirmation => "secret"}
  assert assigns(:user).valid?
  ..
end

在用户模型中,我进行了验证以确保 :username 和 :email 是唯一的。但是为什么测试能够在没有抱怨/错误/无效的情况下发布这两个数据呢?感谢任何帮助,我认为只有一个数据库用于测试,并且测试数据应该发生冲突。谢谢。

I'm new to Rails testing and I'm confuse with the nature of rails integration test data:

test "should register new user and login" do
  ..
  # create user
  post users_path, :user => {:username => "newuser", :email => "[email protected]",
    :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 => "[email protected]",
    :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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一向肩并 2024-10-18 17:13:20

好问题。在测试框架 (Test::Unit) 运行每个测试之前,它将数据库重置为其原始状态。因此,在每次测试之前,您可以保证数据库仅包含夹具数据而没有其他数据。

这很有帮助。当您开始下一个测试时,您不希望一个测试的数据仍然存在。如果是这样,如果您执行诸如单独运行测试(而不是整个套件)或以不同顺序运行测试之类的操作,则数据库状态将不一致。

解决方案:您可以编写一个测试来专门验证 :username 和 :email 是否唯一。在给出示例之前,我应该提到,您似乎为此验证编写了一个功能测试。这很诱人,因为您正在验证用户将看到的行为,但测试验证的位置是在单元测试中,因为 Rails 中的验证规则会下推到模型中。 (为了保持验证干燥。您不必在一堆控制器中重复验证规则)

因此,这是编写单元测试的一种方法:

test "should validate unique email" do
  attributes = { :username => "newuser", :email => "[email protected]", :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

有关此内容的好文章,请参阅 John Nunemaker 两年前的博文。忽略他的代码示例中意外出现的 HTML 标记。 Nunemaker 是一位很棒的 Rails 博主。

有一些替代测试库(例如 Shoulda)具有内置函数来验证您的模型是否验证唯一性。但由于您是 Rails 新手,我建议您暂时使用默认测试框架。 (事实上​​,发明 Rails 的 37Signals 人员仍然使用默认值,所以这说明了很多。我也更喜欢坚持使用默认值。)

顺便说一句,您可以通过缩进来格式化 StackOverflow 问题中的代码四个空格。

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 => "[email protected]", :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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文