在哪里/测试什么?模拟、存根、功能、单元...(在 Ruby/Rails 中)?

发布于 2024-09-12 05:59:46 字数 735 浏览 6 评论 0原文

我正在尝试测试一个相当大的 Rails 应用程序,我可能应该一直这样做,但从来没有感到完全舒服。现在我正在进行功能测试以查看用户是否创建成功。基本上,我想测试一些事情:

  • 用户是否已保存(即数据库中是否有新记录)
  • 他的信息(姓名、电子邮件等)是否正确
  • 是否有几个字段已自动保存添加到数据库 before_create
  • 是否发送电子邮件
  • 电子邮件文本是否合适(即,替换电子邮件模板中的用户名和激活链接)

据我了解,单元测试旨在测试模型,功能测试应测试控制器。正如我所看到的,我上面提到的几个测试应该是单元测试 - 具体来说,我认为我可以确保输入正确映射到数据库字段,并且 before_create 过滤器在具有用户模型的单元测试中工作。

其他人似乎呼吁进行功能测试 - 电子邮件是否已发送(可能还有其文本 - 尽管这可能属于 UserEmail 测试?)以及是否有新记录。

这是关于模拟/存根的问题。在用户控制器功能测试中,我应该确保使用适当的参数调用 user.save,还是应该测试数据库是否获取新记录?前者似乎需要一个存根,并假设,由于 Rails 已经经过充分测试,如果在用户模型上调用 .save,则该对象将被成功保存。但后者(例如,调用assert_difference)感觉更彻底。选择哪个?

抱歉,如果这个问题太复杂了——我知道这是一个很大的话题,但我希望理解这样一个特定的(如果很长)的例子将澄清很多关于一般测试的知识。

谢谢!

I'm trying to test a fairly large Rails app, which I probably should have been doing all along but never felt entirely comfortable with. Now I'm working on a functional test to see if a user is created successfully. Basically, I'd like to test a few things:

  • whether the user was saved (i.e., if there's a new record in the DB)
  • whether his information (name, email, etc.) is correct
  • whether a couple of fields have been automatically added to the database before_create
  • whether an email was sent
  • whether the email text is appropriate (i.e., substitute's the user's name and activation link in the email template)

As I understand it, unit tests are designed to test models and functional tests should test controllers. Several of the tests I mention above should be unit tests, as I see it -- specifically, I think I can make sure that inputs are correctly mapped to database fields and that the before_create filter works in a unit test with a User model.

Others seem to call for functioanl tests -- whether the email is sent (and possibly its text -- although maybe that belongs in a UserEmail test?) and whether there's a new record.

Here's the question about mocking/stubbing. In the user controller functional test, should I just make sure that user.save is called with the appropriate parameters, or should I test that the DB gets a new record? The former seems to call for a stub and assumes that, since Rails is so well tested, the object will be saved successfully if .save is called on the user model. But the latter (e.g., calling assert_difference) feels more thorough. Which to choose?

Sorry if this is too involved a question -- I understand it's a big topic, but my hope is that understanding a specific (if long) example like this will clarify a whole lot about testing in general.

Thanks!

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

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

发布评论

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

评论(2

扭转时空 2024-09-19 05:59:46

这不是一个容易回答的问题。基本上,Rails 世界中有两个阵营。有一个阵营会告诉你使用模拟,因为它会让你的测试更快。另一个阵营会告诉您使用数据库进行测试,因为它会更加“忠实”,因为它会测试数据库表是否具有正确的列,而模拟不会这样做。两个阵营都会告诉你他们的测试风格更清晰:-)

我的建议是尝试一种方法一段时间,然后尝试另一种方法。看看什么对你有用。最重要的是,尽量确保你的测试清晰且富有表现力。您可以找到有关如何开始测试 Rails

It's not an easy question to answer. Basically there are two camps in the Rails world. One camp will tell you to use the mock, as it will make your tests faster. The other camp will tell you to test with the database, as it will be more "faithful" as it tests that the database table has the proper columns, which the mock will not do. Both camps will tell you that their style of tests is clearer :-)

My advice is to try one way for a while, then try the other. See what works for you. Above all try to make sure your tests are clear and expressive. You can find hints on how to start testing Rails in this presentation by Gregg Pollack.

毁虫ゝ 2024-09-19 05:59:46

我喜欢进行功能测试的方式是不模拟/存根任何东西。基本上,一般来说存根/模拟对于单元测试非常有用,因为它允许您隔离类或功能单元。现在,当涉及集成和功能测试时,目的是测试“实际”类的交互,因此您希望避免模拟/存根。

因此,在您的情况下,我会在对用户控制器进行功能级测试时涉及数据库。如果您决定存根持久层,我认为您正在对控制器进行单元测试(假设没有其他依赖项) - 这样的测试不允许您捕获持久层的问题(例如,数据库中的不兼容更改)架构、数据库连接问题等)。

底线是这两种实践都是有效的,但适当的方法取决于您的目标是什么(即功能、集成或单元测试)。

The way I like to do my functional tests is to not mock/stub anything. Basically, in general stubbing/mocking is very useful for unit testing, as it allows you to isolate classes or units of functionality. Now when it comes to integration and functional tests, the purpose is to test "actual" classes' interactions so you'd want to avoid mocking/stubbing.

So in your case, I would involve the DB when doing a functional-level test for the user controller. If you decided to stub the persistence layer, I would argue you're unit testing the controller (assuming there are no other dependencies) - such a test would not allow you to catch issues with your persistence layer (e.g., incompatible changes in your DB schema, DB connection issues, etc.).

The bottom line is that both practices are valid, but the appropriate way of doing it depends on what your objective is (i.e., functional, integration or unit testing).

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