我是单元测试还是集成测试?

时间:2009-02-05 16:08:26

标签: testing automated-tests

我开始使用自动化测试,我想测试一种数据访问方法。我试图测试代码在数据库没有返回任何记录时所做的事情。

这是应该在单元测试还是集成测试中完成的事情?

由于

10 个答案:

答案 0 :(得分:15)

如果您的测试代码连接到实际数据库并且依赖于某些数据(或缺少数据)的存在以便测试通过,则它是一个集成测试。

我通常喜欢通过模拟用于获取实际数据的“数据访问方法”的组件来测试这样的东西,无论是JDBC连接还是Web服务代理或其他任何东西。使用模拟,你会说“当调用此方法时,返回此”或“确保此方法被调用N次”,然后告诉测试中的类使用模拟组件而不是真实组件。这是一个“单元测试”,因为您正在测试被测试类的行为,在一个封闭的系统中,您已经准确地声明了其他组件的行为方式。您已经完全隔离了被测试的类,并且可以确保您的测试结果不会是易失性的,并且取决于另一个组件的状态。

不确定您使用的是哪种语言/技术,但在Java世界中,您可以使用JMock,EasyMock等来实现此目的。

答案 1 :(得分:10)

我认为浪费了更多的时间来争论什么是单位与什么是整合测试,而不是增加价值。

我不在乎。

让我用不同的方式:如果我正在测试它,我会看到两种方法 - 伪造数据库返回零行,或者实际连接到没有select数据的数据库。我可能会开始测试最容易做的事情和最简单的实现 - 如果它运行得足够快,我可以获得有意义的反馈。然后我会考虑另一个,如果我需要它跑得更快或认为会有一些优势。

例如,我可能会在我的工作中开始连接到实际的测试数据库。但是,如果软件需要与许多不同的数据库一起工作 - Oracle,PostGres,MySQL,SQL服务器和数据库,或者工作中的测试数据库因为'刷新'很多,我可能会写'pure / unit'测试完全孤立存在。

在我年老的时候,我更喜欢更频繁地使用“面向开发人员”与“面向客户”这一术语,并进行更有意义的测试。我发现广泛使用像“单位”这样的术语,然后得到一个关于它的定义 - weenie导致人们做一些事情,比如嘲笑文件系统或嘲笑getter和setter - 我认为这些活动无益。

我坚信这一点;我在谷歌之前提出过它。

http://www.google.com/url?sa=t&source=web&oi=video_result&ct=res&cd=1&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DPHtEkkKXSiY&ei=9-wKSobjEpKANvHT_MEB&rct=j&q=heusser+GTAC+2007&usg=AFQjCNHOgFzsoVss50Qku1p011J4-UjhgQ

祝你好运!让我们知道它是怎么回事!

答案 2 :(得分:7)

进行测试,让其他人花时间分类。

答案 3 :(得分:6)

我的观点是你应该根据范围对测试进行分类:

  • 单元测试可以独立运行 没有任何外部依赖 (文件IO,网络IO,数据库, 外部Web服务)。
  • 集成测试可以触及外部系统。

如果测试需要运行真实数据库,则将其称为集成测试,并将其与单元测试分开。这很重要,因为如果混合使用集成和单元测试,则会使代码的可维护性降低。

混合测试包意味着新开发人员可能需要一大堆外部依赖项才能运行测试套件。想象一下,您想要对与数据库相关但实际上并不需要数据库运行的代码进行更改,如果您需要一个数据库来运行与之相关的测试,那么您将会感到沮丧。项目

如果外部依赖很难模拟(例如,在DotNet中,如果你使用Rhino Mocks并且外部类没有接口),那么创建一个触及外部系统的瘦包装类。然后在单元测试中模拟出包装器。您不应该需要一个数据库来运行这个简单的测试,所以不需要一个!

答案 4 :(得分:5)

有些人(包括我自己)对单元测试与集成测试的构成有严格的规定。

测试is not a unit test if:

  • 与数据库对话
  • 通过网络进行通信
  • 它触及文件系统
  • 它不能与任何其他单元测试同时运行
  • 您必须对您的环境执行特殊操作(例如编辑配置文件)才能运行它

这可能是区分单元测试将使用模拟为您做什么的一种方法,而不是任何真正的资源提供者 - 文件系统,db等。

集成测试可视为系统/应用层非常耦合的测试,因此基础测试在单元中进行测试,系统互操作性是集成测试的重点。

它仍然是一个灰色区域,因为人们经常可以查明这些规则的某些例外情况。

答案 5 :(得分:2)

我认为重要的问题是“应该我在做什么?”

在这种情况下,我认为你应该进行单元测试。模拟与DB对话的代码并让它返回一个可靠的结果(没有行),这样你的测试检查没有行时会发生什么,而不是当DB返回DB中的任何内容时会发生什么测试

绝对单元测试吧!

[TestMethod]
public void ForgotMyPassword_SendsAnEmail_WhenValidUserIsPassed()
{
    var userRepository = MockRepository.GenerateStub<IUserRepository>();
    var notificationSender = MockRepository.GenerateStub<INotificationSender>();
    userRepository.Stub(x => x.GetUserByEmailAddressAndPassword("me@home.com", "secret")).Return(new User { Id = 5, Name = "Peter Morris" });

    new LoginController(userRepository, notificationSender).ResendPassword("me@home.com", "secret");

    notificationSender.AssertWasCalled(x => x.Send(null),
        options => options.Constraints(Text.StartsWith("Changed")));
}

答案 6 :(得分:1)

我相信可以将其作为单元测试进行测试,而无需真正的数据库。而不是使用数据库的真实接口,而是用mock/stub/fake object替换它(更好的可视化PDF是here)。

如果将其作为一个单元测试来证明是太难了,并且你无法重构那些测试它的代码会很容易,那么你最好把它作为集成测试来编写。它将运行得更慢,因此您可能无法在代码更改后运行所有集成测试(不像您可以每秒运行数百和数千的单元测试),但只要它们定期运行(例如作为其中一部分)它们会产生一定的价值。

答案 7 :(得分:0)

最有可能是单元测试......但这里有一条模糊的线条。这实际上取决于正在执行多少代码 - 如果它包含在库或类中,然后是单元测试,如果它跨越多个组件,则更多的是集成测试。

答案 8 :(得分:0)

我认为应该在单元测试中完成。您没有测试它是否可以连接到数据库,或者您可以调用存储过程...您正在测试代码的行为。

我可能是错的,但这就是我的想法,除非有人给我一个理由去思考。

答案 9 :(得分:0)

这是一个单元测试,根据定义:您正在测试特定路径上代码的单个隔离元素