在数据库而不是假存储库上运行测试是一种不好的做法吗?
我知道优点是什么,并且当我使用更复杂的系统时,我会使用假数据。
如果我正在开发一些简单的东西,并且我可以轻松地在真实数据库中设置我的环境,并且所访问的数据非常小,以至于访问时间不是一个因素,并且我只运行一些测试,该怎么办?
创建假数据仍然很重要,还是我可以忘记额外的编码并直接跳到真实的数据?
当我说真实数据库时,我指的不是生产数据库,而是测试数据库,而是使用真实的 DBMS 和与真实数据库相同的模式。
I know what the advantages are and I use fake data when I am working with more complex systems.
What if I am developing something simple and I can easily set up my environment in a real database and the data being accessed is so small that the access time is not a factor, and I am only running a few tests.
Is it still important to create fake data or can I forget the extra coding and skip right to the real thing?
When I said real database I do not mean a production database, I mean a test database, but using a real live DBMS and the same schema as the real database.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
使用假数据而不是真实数据库的原因是:
现在,如果您正在构建一个小型应用程序,并且通过使用真正的数据库(例如 MySQL)您可以实现上述目标,那么请务必使用该数据库。 我愿意。 但毫无疑问,随着应用程序的增长,您最终将面临模拟数据库的需要。 没关系,需要的时候就做吧。 亚格尼。 只要确保您在需要时确实这样做即可。 如果你放手,你就会付出代价。
The reasons to use fake data instead of a real DB are:
Now, if you are building a small little application, and by using a real DB (like MySQL) you can achieve the above goals, then by all means use the DB. I do. But make no mistake, as your application grows you will eventually be faced with the need to mock out the DB. That's OK, do it when you need to. YAGNI. Just make sure you DO do it WHEN you need to. If you let it go, you'll pay.
这在某种程度上取决于您想要测试的内容。 通常,您想要测试代码中的实际逻辑而不是数据库中的数据,因此仅仅为了运行测试而设置完整的数据库是浪费时间。
还要考虑维护测试和测试数据库的工作量。 使用数据库测试代码通常意味着您将应用程序作为一个整体进行测试,而不是单独测试不同的部分。 这通常会导致需要做大量工作来保持数据库和测试同步。
最后一个问题是测试应该独立运行,因此每个测试应该在自己的数据库版本上运行,或者使其保持与测试运行之前完全相同的状态。 这包括测试失败后的状态。
话虽如此,如果您确实想在数据库上进行测试,也可以。 有一些工具可以帮助设置和拆除数据库,例如 dbunit。
我见过人们尝试创建这样的单元测试,但几乎总是结果发现所做的工作比实际价值要多得多。 大多数人在项目期间中途放弃了它,大多数人在项目期间完全放弃了 ttd,认为经验通常会转移到单元测试。
因此,我建议保持测试简单和隔离,并将您的代码封装得足够好,这样就可以单独测试您的代码。
It sort of depends what you want to test. Often you want to test the actual logic in your code not the data in the database, so setting up a complete database just to run your tests is a waste of time.
Also consider the amount of work that goes into maintaining your tests and testdatabase. Testing your code with a database often means your are testing your application as a whole instead of the different parts in isolation. This often result in a lot of work keeping both the database and tests in sync.
And the last problem is that the test should run in isolation so each test should either run on its own version of the database or leave it in exactly the same state as it was before the test ran. This includes the state after a failed test.
Having said that, if you really want to test on your database you can. There are tools that help setting up and tearing down a database, like dbunit.
I've seen people trying to create unit test like this, but almost always it turns out to be much more work then it is actually worth. Most abandoned it halfway during the project, most abandoning ttd completely during the project, thinking the experience transfer to unit testing in general.
So I would recommend keeping tests simple and isolated and encapsulate your code good enough it becomes possible to test your code in isolation.
只要 Real DB 不会妨碍你,而且你可以这样走得更快,我会务实地去做。
在单元测试中,“测试”比“单元”更重要。
As far as the Real DB does not get in your way, and you can go faster that way, I would be pragmatic and go for it.
In unit-test, the "test" is more important than the "unit".
我认为这取决于您的查询是否在存储库中固定(更好的选择,IMO),或者存储库是否公开可组合查询; 例如 - 如果您有一个存储库方法:
那么您的 UI 可以请求:
这将通过基于对象的假存储库,但对于实际数据库实现将失败。 当然,您可以通过让存储库在内部处理所有查询(无外部组合)来消除这一点; 例如:
因为这个无法组合,所以可以独立检查DB和UI。 对于可组合查询,如果您希望它有用,则必须始终使用集成测试。
I think it depends on whether your queries are fixed inside the repository (the better option, IMO), or whether the repository exposes composable queries; for example - if you have a repository method:
Then your UI could request:
This will pass for an object-based fake repo, but will fail for actual db implementations. Of course, you can nullify this by having the repository handle all queries internally (no external composition); for example:
Because this can't be composed, you can check the DB and the UI independently. With composable queries, you are forced to use integration tests throughout if you want it to be useful.
这更取决于数据库是否是由测试自动设置的,以及数据库是否与其他开发人员隔离。
目前这可能不是问题(例如只有一名开发人员)。 然而(对于手动数据库设置)设置数据库是运行测试的额外障碍,这是一件非常糟糕的事情。
It rather depends on whether the DB is automatically set up by the test, also whether the database is isolated from other developers.
At the moment it may not be a problem (e.g. only one developer). However (for manual database setup) setting up the database is an extra impediment for running tests, and this is a very bad thing.
如果您只是编写一个简单的一次性应用程序,并且您绝对知道它不会增长,那么我认为很多“最佳实践”就被抛之脑后了。
如果您编写的只是简单的“联系我们”表单,则您不需要使用 DI/IOC 或进行单元测试或模拟数据库访问。 然而,在“简单”应用程序和“复杂”应用程序之间划清界限很困难。
换句话说,请运用您的最佳判断,因为对此没有硬性的答案。
If you're just writing a simple one-off application that you absolutely know will not grow, I think a lot of "best practices" just go right out the window.
You don't need to use DI/IOC or have unit tests or mock out your db access if all you're writing is a simple "Contact Us" form. However, where to draw the line between a "simple" app and a "complex" one is difficult.
In other words, use your best judgment as there is no hard-and-set answer to this.
只要您不将它们视为“单元”测试,就可以针对该场景执行此操作。 这些将是集成测试。 您还需要考虑是否要一次又一次地通过 UI 进行手动测试,因为您可能只是自动化烟雾测试。 鉴于此,您甚至可能考虑根本不进行集成测试,而只在功能/ui 测试级别工作(因为它们已经涵盖了集成)。
正如其他人指出的那样,很难在复杂/非复杂之间划清界限,而且通常现在就为时已晚了:(。如果你已经习惯了这样做,我相信你不会得到太多如果不是这种情况,你可以从中学习:)
It is ok to do that for the scenario, as long as you don't see them as "unit" tests. Those would be integration tests. You also want to consider if you will be manually testing through the UI again and again, as you might just automated your smoke tests instead. Given that, you might even consider not doing the integration tests at all, and just work at the functional/ui tests level (as they will already be covering the integration).
As others as pointed out, it is hard to draw the line on complex/non complex, and you would usually now when it is too late :(. If you are already used to doing them, I am sure you won't get much overhead. If that were not the case, you could learn from it :)
假设您想要自动执行此操作,最重要的是您可以以编程方式生成初始条件。 听起来确实如此,甚至更好的是您正在测试真实世界的数据。
但是,也有一些缺点:
您的真实数据库可能无法涵盖代码中的某些条件。 如果你有虚假数据,就会导致这种行为发生。
正如您所指出的,您有一个简单的应用程序; 当它变得不那么简单时,您将需要可以将测试分类为单元测试和系统测试。 单元测试应该针对一个简单的功能,使用虚假数据会更容易做到这一点。
Assuming that you want to automate this, the most important thing is that you can programmatically generate your initial condition. It sounds like that's the case, and even better you're testing real world data.
However, there are a few drawbacks:
Your real database might not cover certain conditions in your code. If you have fake data, you cause that behavior to happen.
And as you point out, you have a simple application; when it becomes less simple, you'll want to have tests that you can categorize as unit tests and system tests. The unit tests should target a simple piece of functionality, which will be much easier to do with fake data.
假存储库的优点之一是您的回归/单元测试是一致的,因为您可以期望相同的查询得到相同的结果。 这使得构建某些单元测试变得更加容易。
如果您的代码(如果不是仅读取查询)修改数据,则会有几个缺点:
- 如果您的代码中有错误(这可能是您进行测试的原因),您最终可能会破坏生产数据库。 即使你没有打破它。
- 如果生产数据库随着时间的推移而发生变化,特别是在代码执行时,您可能会丢失添加的测试材料,并且以后很难将其从数据库中清除。
- 来自访问数据库的其他系统的生产查询可能会将您的测试数据视为真实数据,这可能会破坏未来某个地方的重要业务流程的结果。 例如,即使您使用特定标志或前缀标记数据,您能否确保访问数据库的任何人都会遵守此架构?
此外,某些数据库受隐私法监管,因此根据您的合同和主数据库的所有者,您可能会或可能不会被法律允许访问真实数据。
如果您需要在生产数据库上运行,我建议您在可以在非高峰时段轻松创建的副本上运行。
One advantage of fake repositories is that your regression / unit testing is consistent since you can expect the same results for the same queries. This makes it easier to build certain unit tests.
There are several disadvantages if your code (if not read-query only) modifies data:
- If you have an error in your code (which is probably why you're testing), you could end up breaking the production database. Even if you didn't break it.
- if the production database changes over time and especially while your code is executing, you may lose track of the test materials that you added and have a hard time later cleaning it out of the database.
- Production queries from other systems accessing the database may treat your test data as real data and this can corrupt results of important business processes somewhere down the road. For example, even if you marked your data with a certain flag or prefix, can you assure that anyone accessing the database will adhere to this schema?
Also, some databases are regulated by privacy laws, so depending on your contract and who owns the main DB, you may or may not be legally allowed to access real data.
If you need to run on a production database, I would recommend running on a copy which you can easily create during of-peak hours.
这是一个非常简单的应用程序,您看不到它的增长,我认为在真实的数据库上运行测试没有问题。 但是,如果您认为该应用程序将会增长,那么在测试中考虑到这一点就很重要。
让一切尽可能简单,如果以后需要更灵活的测试,那就这样做。 不过,请提前计划,因为您不想在 3 年内拥有一个依赖于旧的和 hacky(对于大型应用程序)测试的大型应用程序。
It's a really simple application, and you can't see it growing, I see no problem running your tests on a real DB. If, however, you think this application will grow, it's important that you account for that in your tests.
Keep everything as simple as you can, and if you require more flexible testing later on, make it so. Plan ahead though, because you don't want to have a huge application in 3 years that relies on old and hacky (for a large application) tests.
对数据库运行测试的缺点是速度慢,并且在运行测试之前设置数据库状态很复杂。
如果您可以控制这一点,那么直接针对数据库运行测试就没有问题; 这实际上是一个很好的方法,因为它比针对虚假数据运行更好地模拟您的最终产品。 关键是要采取务实的方法,并将最佳实践视为指导方针而不是规则。
The downsides to running tests against your database is lack of speed and the complexity for setting up your database state before running tests.
If you have control over this there is no problem in running the tests directly against the database; it's actually a good approach because it simulates your final product better than running against fake data. The key is to have a pragmatic approach and see best practice as guidelines and not rules.