代码之家  ›  专栏  ›  技术社区  ›  ilivewithian

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

  •  9
  • ilivewithian  · 技术社区  · 16 年前

    我从自动化测试开始,我想测试我的一种数据访问方法。如果数据库没有返回任何记录,我将尝试测试代码的作用。

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

    谢谢

    10 回复  |  直到 16 年前
        1
  •  15
  •   matt b    16 年前

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

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

    不确定你正在使用什么语言/技术,但是在Java世界中,你可以使用JMOCK、EasyMoCK等来实现这一目的。

        2
  •  10
  •   Matthew Heusser    16 年前

    我认为在讨论什么是单元和什么是集成测试上浪费的时间比增加的价值要多。

    我不在乎。

    让我换一种说法:如果我在测试它,我会看到两种方法来实现它——伪造返回零行的数据库,或者实际连接到没有用于选择的数据的数据库。我可能会用最容易做和最容易实现的东西开始测试——如果它运行得足够快,我可以得到有意义的反馈。然后我会考虑另一个,如果我需要它跑得更快,或认为会有一些优势。

    例如,我可能会在工作时开始连接到实际的测试数据库。但是,如果软件需要与许多不同的数据库(Oracle、Postgres、MySQL、SQL Server和DB)一起工作,或者如果工作中的测试数据库经常“刷新”,我可能会编写完全隔离的“纯/单元”测试。

    在我年老的时候,我更喜欢使用“面向开发人员”和“面向客户”这两个术语,并且做一些更有意义的测试。我发现广泛地使用“单元”这样的术语,然后得到一个关于它的定义,这会导致人们做一些事情,比如模仿文件系统或模仿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

    祝你好运!让我们知道情况如何!

        3
  •  7
  •   mouviciel    16 年前

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

        4
  •  6
  •   Iain    16 年前

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

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

    如果测试需要一个真正的数据库来运行,那么称它为集成测试,并将其与单元测试分开。这一点很重要,因为如果将集成和单元测试混合在一起,那么代码的可维护性就会降低。

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

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

        5
  •  5
  •   j pimmel    16 年前

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

    测试 is not a unit test 如果:

    • 它与数据库对话
    • 它通过网络进行通信
    • 它接触到文件系统
    • 它可以与任何其他单元测试同时运行
    • 您必须对环境做一些特殊的事情(例如编辑配置文件)才能运行它。

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

    集成测试可以看作是对系统/应用层非常耦合的测试,因此基本原理在单元中进行测试,系统互操作性是集成测试的重点。

    尽管如此,这仍然是一个灰色地带,因为人们常常可以精确地指出这些规则的某些例外。

        6
  •  2
  •   Peter Morris    16 年前

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

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

    肯定是单元测试!

    [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")));
    }
    
        7
  •  1
  •   Esko Luontola    16 年前

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

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

        8
  •  0
  •   Stephen Doyle    16 年前

    很可能是单元测试…但这里有一条模糊的线。它实际上取决于正在执行的代码量——如果它包含在库或类中,那么它的单元测试;如果它跨越多个组件,那么它更像是一个集成测试。

        9
  •  0
  •   Max Schmeling    16 年前

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

    我可能是错的,但这正是我的想法,除非有人给我一个理由不这样想。

        10
  •  0
  •   Steven A. Lowe    16 年前

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