依赖 NUnit 单元测试的顺序是否是一种不好的形式

发布于 2024-07-12 04:31:56 字数 431 浏览 6 评论 0原文

我一直在疯狂地创建单元测试,并发现我经常不得不在一个测试中设置一些我刚刚在上一个测试中拆除的东西。 在一个测试(例如插入测试)中创建某些内容(例如数据库记录)然后将其用于以后的测试(例如删除测试)是否合理? 或者每个测试都应该完全独立吗?

您甚至可以确定 NUnit 中测试的顺序还是它们总是按字母顺序完成?

注意:我特别询问一个测试文件中的测试顺序。 跨测试文件或以任何更全局的方式。

更新:感谢所有回答的人 - 有很多很好的答案,而且小组的感觉非常一致。 我选择了约翰·诺兰的答案,因为他提供了最完整的解释和大量链接。 正如您可能已经猜到的那样,尽管我认为它可能像约翰所说的那样有点“臭”,但我还是很想打破这条规则。 还要感谢 Fortyrunner 添加单元测试标签。

I have been creating Unit tests like crazy and find that I'm often having to set up something in one test that I just tore down in a previous test. Is it ever reasonable to create something (e.g. a database record) in one test (e.g. an Insertion test) and then use it for a later test (e.g. a Deletion test)? Or should each and every test always stand completely on its own?

Can you even determine the order of tests in NUnit or are they always done alphabetically?

Note: I am specifically asking about the order of tests within one test file. Not across test files or in any way more globally.

Update: Thanks to everyone that answered - there were a lot of good answers and the sense of the group is pretty unanimous. I've chosen John Nolan's answer as he provided the most complete explanation and lots of links. As you may have guessed, I've been sorely tempted to break this rule despite thinking that it might be a bit "smelly" as John put it. Thanks also to Fortyrunner for adding the unit-testing tag.

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

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

发布评论

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

评论(8

草莓味的萝莉 2024-07-19 04:31:56

依赖测试的顺序表明您正在跨测试保持状态。 这是 smelly

一种更干净的测试方法,您只需要依赖您想要检查其行为的单个功能。 通常,您会模拟让您的方法在测试中正常运行所需的其他对象。

考虑进行单元测试的一个好方法是 排列、执行、断言 模式。

以下是 Karl Seguin 的优秀免费 的片段电子书。 我已经注释了 Arrange、Act 和 Assert。

[TestFixture] public class CarTest 
{ 
    [Test] public void SaveCarCallsUpdateWhenAlreadyExistingCar()   
    {
         //Arrange
         MockRepository mocks = new MockRepository();
         IDataAccess dataAccess = mocks.CreateMock<IDataAccess>();   
         ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess); 
         //Act
         Car car = new Car(); 
         Expect.Call(dataAccess.Save(car)).Return(389); 
         mocks.ReplayAll(); 
         car.Save(); 
         mocks.VerifyAll(); 
         // Assert
         Assert.AreEqual(389, car.Id); 
         ObjectFactory.ResetDefaults();
    } 
}

Relying on the order of your tests indicates that you are persisting state across tests. This is smelly

A cleaner way of testing is where you only depend on the single piece of functionality you want to check the behaviour of. Commonly you mock the other objects you need to get your method under test to function.

A good way to think about approaching unit tests is the Arrange, Act, Assert pattern.

Below is a snippet from Karl Seguin's excellent free eBook. I've annoted Arrange, Act and Assert.

[TestFixture] public class CarTest 
{ 
    [Test] public void SaveCarCallsUpdateWhenAlreadyExistingCar()   
    {
         //Arrange
         MockRepository mocks = new MockRepository();
         IDataAccess dataAccess = mocks.CreateMock<IDataAccess>();   
         ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess); 
         //Act
         Car car = new Car(); 
         Expect.Call(dataAccess.Save(car)).Return(389); 
         mocks.ReplayAll(); 
         car.Save(); 
         mocks.VerifyAll(); 
         // Assert
         Assert.AreEqual(389, car.Id); 
         ObjectFactory.ResetDefaults();
    } 
}
御守 2024-07-19 04:31:56

查看允许您指定功能的测试夹具设置它将在夹具中的任何测试之前执行。 这允许您执行一次通用设置,无论您运行一个测试还是套件中的所有测试,它都将始终运行。

Look into test fixture setups that allow you to specify functions that will be executed before any of the tests in the fixture. This allows you to do common setup once and it will always run, whether you run one test, or all tests in the suite.

溇涏 2024-07-19 04:31:56

单元测试旨在独立运行,而不是作为顺序脚本运行。 如果您确实需要它们按顺序运行,请将它们收集到单个测试函数中。

如果您的单元测试昂贵的设置,当您认为你正在做单元测试。 如果您在大多数单元测试中使用 SQL 数据库,那么您实际上是在与数据访问层进行集成测试。

Unit tests are intended to stand alone, not be run as a sequential script. If you actually need them run sequentially, collect them into a single test function.

If your unit tests suffer from expensive set-up, you may be doing integration testing when you think you're doing unit testing. If you're hitting a SQL database inside most of your unit tests, you're actually integration testing with your data access layer.

奢华的一滴泪 2024-07-19 04:31:56

我认为每个测试完全独立于任何其他测试。 即使您可以强制执行测试的顺序,当测试必须更改时,这将是一场维护噩梦。

I would view each test as completely independent from any other test. Even if you could mandate the order of the tests, it would be a maintenance nightmare when the tests must change.

泼猴你往哪里跑 2024-07-19 04:31:56

我真的不会依赖测试的顺序。 相反,我会将通用设置代码放入一个单独的方法中,并从简单测试和更复杂的测试中调用它。 或者,只需在删除测试开始时调用插入测试本身。

I really wouldn't rely on ordering of tests. Instead, I'd pull the common setup code into a separate method and call that from both the simple test and the more complicated one. Alternatively, just call the insertion test itself at the start of the deletion test.

涙—继续流 2024-07-19 04:31:56

我强烈建议使所有单元测试独立。

您的业​​务逻辑/数据库结构等可能会随着时间的推移而改变,因此您最终将不得不替换或重写(甚至丢弃)现有的单元测试 - 如果您有多个其他测试,具体取决于您要替换的测试,这可能会导致不必要的麻烦,因为您还必须完成所有其他测试并检查这些测试是否仍按预期工作。

此外,一个失败的单元测试不应该能够拖累其他许多单元测试(它们本身可能完美地工作)。

I would strongly advise to make all your unit tests independent.

Your business logic / database structure etc. may change over time, so that you'll eventually have to replace or rewrite (or even discard) existing unit tests - and if you have several other tests depending on the one that you're replacing, this might cause unnecessary troubles because you'd have to go through all of the other tests as well and check if these are still working as expected.

In addition, one failing unit test should not be able to drag many others (that might perfectly work on their own) down.

稚然 2024-07-19 04:31:56

如果您有状态测试(数据库工作的常见问题 - 这就是我不在 SO 上时所做的),那么在我看来,避免测试文件中的顺序并不是绝对必要的。 但是,您必须认识到,如果您有 2 个测试,其中测试 2 取决于测试 1 通过,那么如果测试 1 失败,您将遇到“灾难性”双重失败,因为测试 2 没有预期的设置(并且,更重要的是,如果您认为测试 2 取决于测试 1 通过,那么您可能会担心测试 1 失败后测试 2 是否通过。

这就是为什么您希望测试尽可能独立 - 文件内和文件间。

依赖不同文件中的(组)测试之间的顺序是非常不明智的。

If you have stateful tests (a common problem with database work - which is what I do when I'm not on SO), then it seems to me that avoiding order within a test file is not absolutely necessary. However, you have to recognize that if you have 2 tests, with test 2 depending on test 1 passing, then you will get a 'catastrophic' double failure if test 1 fails, because test 2 doesn't have the expected setup (and, what's more, you want to worry if test 2 does pass after test 1 failed if you think that test 2 depends on test 1 passing).

That's why you want the tests independent whenever possible - both intra-file and inter-file.

It would be very unwise to depend on the order between (sets of) tests in different files.

悲凉≈ 2024-07-19 04:31:56

不幸的是,单元测试的运行顺序是不可预测的,或者至少将来可能会改变。 例如,单元测试框架将被更改,因此每个测试将在单独的线程中执行。
所以从我的角度来看,使用测试顺序是不合理的。
另一方面,您可以创建一组小型独立测试来测试代码的一小部分,然后创建一个或多个大型测试来按特定顺序运行小型测试。

Unfortunately run order of the unit test is not predictable or at least could be changed in future. E.g. unit testing framework will be changed so each test will be executed in separate thread.
So from my point of view using test order is not reasonable.
On the other hand you can create a set of small independent tests to test small parts of your code and then create one or several large tests that will run your small tests in specific order.

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