为什么使用 JUnit 进行测试?

也许我的问题是一个新手的,但我不能真正理解的情况下,我会使用

无论我编写简单的应用程序还是较大的应用程序,我都会使用 System.out语句对它们进行测试,这对我来说似乎很容易。

如果我们仍然必须调用相同的方法,检查它们返回的内容,那么我们为什么要使用 JUnit 创建测试类,在项目中创建不必要的文件夹,而且我们还要对所有内容进行注释呢?

为什么不编写一个类并立即使用 System.out对其进行测试,而不创建测试类呢?

另外,我从来没有参与过刚刚开始学习的大型项目。

那么目的是什么?

71321 次浏览

这不是测试,而是“手动查看输出”(业内称为 LMAO)。更正式的说法是“手动查找异常输出”(LMFAO)。(见下文注释)

任何时候更改代码,都必须为受这些更改影响的所有代码运行应用程序和 LMFAO。即使在小型项目中,这也是有问题和容易出错的。

现在可以扩展到50k、250k、1m LOC 或更多,并且在任何时候进行代码更改时都可以使用 LMFAO。这不仅是不愉快的,而且是不可能的: 您已经扩展了输入、输出、标志和条件的组合,并且很难执行所有可能的分支。

更糟糕的是,LMFAO 可能意味着访问一页又一页的网页应用程序,运行报告,研究几十个文件和机器上的数百万条日志线,阅读生成和发送的电子邮件,检查短信,检查机器人的路径,灌装一瓶苏打水,收集来自一百个网络服务的数据,检查金融交易的审计跟踪... ... 你明白了吧。“输出”并不意味着几行文本,“输出”意味着聚合系统行为。

最后,单元和行为测试 定义系统的行为。测试可以由持续集成服务器运行,并检查其正确性。当然,System.outs 也可以,但是 CI 服务器不会知道它们中的一个是否错误,如果错了,那么它们就是单元测试,您不妨使用一个框架。

无论我们认为自己有多好,人类都不是好的单元测试框架或 CI 服务器。


注意: LMAO 测试,但是在 非常有限的意义上。它不能在整个项目中或作为过程的一部分以任何有意义的方式重复。它类似于在 REPL 中增量开发,但是从来没有正式化那些增量测试。

JUnit 的主要优点是它是自动化的,而不必手动检查打印输出。您编写的每个测试都将保留在系统中。这意味着,如果您做了一个具有意想不到副作用的更改,您的测试将捕捉到它并失败,而不是您必须记住在每次更改后手动测试所有内容。

当您使用 System.out 之类的东西进行测试时,您只是在测试一小部分可能的用例。当您处理的系统可以接受几乎无限量的不同输入时,这并不是很彻底。

单元测试旨在允许您使用一组非常大且多样化的不同数据输入在应用程序上快速运行测试。此外,最好的单元测试还考虑了边界情况,例如位于被认为有效的边缘的数据输入。

对于一个人来说,测试所有这些不同的输入可能需要几个星期,而对于一台机器来说,可能需要几分钟。

可以这样想: 您也不是在“测试”某些将是静态的东西。您的应用程序很可能会经历不断的更改。因此,这些单元测试被设计为在编译或部署周期的不同时间点运行。也许最大的优势在于:

如果您在代码中破坏了某些内容,那么您将了解它 就现在,而不是在您部署之后,不是在 QA 测试人员发现错误时,也不是在您的客户端取消时。您还将有更好的机会修复 马上故障,因为很明显,破坏有问题的代码部分的事情很可能发生在您上次编译之后。因此,解决这一问题所需的调查工作量大大减少。

我们编写测试来验证程序行为的正确性。

通过使用 眼睛检查输出语句的内容来验证程序行为的正确性是一个 手动操作,或者更具体地说,是一个 视觉效果进程。

你可以这么说

可视化检查工作 ,我检查代码是否达到了预期的效果 一旦我发现这是正确的,我们就可以 去吧。

首先,如果您对代码是否正确工作感兴趣,那就太好了。这是好事。你走在前面了!遗憾的是,这种方法存在一些问题。

可视化检查的第一个问题是,如果再也无法检查代码的正确性,那么您就是一个糟糕的焊接事故。

第二个问题是,使用的一对眼睛与眼睛所有者的大脑紧密结合。如果代码的作者也拥有视觉检查过程中使用的眼睛,那么验证正确性的过程就依赖于视觉检查者大脑中内化的程序知识。

对于一双新的眼睛来说,仅仅因为它们没有与原始编码者的大脑合作,就很难进入并验证代码的正确性。第二双眼睛的所有者将不得不与 交谈代码的原始作者为了充分理解代码的问题。众所周知,交谈作为分享知识的手段是不可靠的。如果原始编码器对新的一对眼睛不可用,则该点是无意义的。在这种情况下,新的一双眼睛必须读取原始代码。

阅读单元测试未覆盖的其他人的代码比阅读与单元测试相关联的代码更困难。在最好的情况下,阅读其他人的代码是棘手的工作,在最坏的情况下,这是软件工程中最繁琐的任务。有一个原因,雇主,当广告职位空缺,强调一个项目是一个新领域(或全新的)之一。从头开始编写代码比修改现有代码更容易,从而使广告中的工作对潜在员工更具吸引力。

通过单元测试,我们将代码划分为它的组成部分。对于每个组件,我们然后设置我们的摊位说明如何程序 应该乖乖的。每个单元测试都讲述了程序的这一部分在特定场景中应该如何工作的故事。每个单元测试就像契约中的一个条款,描述从客户机代码的角度应该发生什么。

这就意味着一双新的眼睛有 股的 活生生的,准确的文档上的代码问题。

首先,他们有代码本身,实现,代码是怎么写的; 其次,他们拥有原始编码人员在一组正式语句中描述的所有知识,这些正式语句讲述了代码 应该守规矩。是如何运行的

单元测试捕获并正式描述原始作者在实现类时所拥有的知识。它们提供了客户端使用该类时的行为描述。

您质疑这样做的有用性是正确的,因为编写无用的单元测试、不覆盖所有有问题的代码、变得陈旧或过时等等都是可能的。我们如何确保单元测试不仅能够模仿而且能够改进知识渊博、认真负责的作者在运行时可视化地检查代码输出语句的过程?首先编写单元测试,然后编写代码使测试通过。当你完成后,让计算机运行测试,他们很快他们很擅长做重复的任务,他们是理想的适合这项工作。

通过在每次触发测试代码并为每个构建运行测试时检查它们来确保测试质量。如果测试失败,立即修复它。

我们将运行测试的过程自动化,以便在每次构建项目时运行测试。我们还自动生成代码覆盖率报告,详细说明测试覆盖和执行的代码的百分比。我们追求高比例。一些公司如果没有编写足够的单元测试来描述代码行为的任何变化,就会阻止代码更改被签入源代码控制。通常,第二双眼睛将与更改的作者一起检查代码更改。评审人员将仔细检查更改,以确保更改是可以理解的,并被测试充分覆盖。因此,审查过程是手工的,但是当测试(单元和集成测试,可能还有用户验收测试)通过这个手工审查过程时,就成为自动构建过程的一部分。每次签入更改时都会运行这些命令。作为构建过程的一部分,服务器执行此任务。

自动运行的测试,维护代码行为的完整性,并对 防止将来对代码库的更改破坏代码有所帮助。

最后,提供测试允许您积极地使用 重构代码,因为您可以在知道您的更改不会破坏现有测试的情况下安全地进行大的代码改进。

对于 测试驱动开发有一个警告,那就是您必须编写代码以使其具有可测试性。这包括编写接口代码和使用依赖注入等技术来实例化协作对象。看看 肯特 · 贝克的工作,他很好地描述了 TDD。查找 对接口进行编码并学习

我添加了一些 System.out 不能做的事情:

  • 使每个测试用例独立(这很重要)

    JUnit 可以这样做: 每次创建新的测试用例实例并调用 @Before时。

  • 从源代码中分离测试代码

    JUnit 可以做到。

  • 与 CI 的整合

    JUnit 可以使用 Ant 和 Maven 来完成。

  • 易于安排和组合测试用例

    JUnit 可以执行 @Ignore和测试套件。

  • 检查结果容易

    JUnit 提供了许多 Assert 方法(assertEqualsassertSame...)

  • 模拟和存根使您专注于测试模块。

    JUnit 可以做到的: 使用 mock 和 stub 可以使您设置正确的 fixture,并将重点放在测试模块逻辑上。

JUnit 是 Java 编程语言的单元测试框架。它在测试驱动开发中非常重要,是统称为 xUnit 的单元测试框架家族中的一员。

JUnit 提倡“先测试,后编码”的思想,强调为一段代码建立测试数据,这段代码可以先测试,然后再实现。这种方法就像“测试一点,代码一点,测试一点,代码一点...”,它提高了程序员的生产力和程序代码的稳定性,从而减少了程序员的压力和花在调试上的时间。

特征 JUnit 是一个开源框架,用于编写和运行测试。

提供标识测试方法的注释。

提供测试预期结果的断言。

为运行测试提供测试运行程序。

JUnit 测试允许您更快地编写代码,从而提高了质量

JUnit 非常简单,复杂度更低,花费的时间也更少。

JUnit 测试可以自动运行,它们检查自己的结果并提供即时反馈。没有必要手动梳理测试结果报告。

JUnit 测试可以组织成包含测试用例甚至其他测试套件的测试套件。

Junit 在一个条中显示测试进度,如果测试进展顺利,则为绿色,如果测试失败,则为红色。

单元测试确保代码按预期工作。它们还非常有助于确保代码仍然能够按照预期的方式工作,以防以后需要更改代码以构建修复 bug 的新功能。代码的高测试覆盖率允许您继续开发特性,而不必执行大量的手工测试。

你的手动方法由 System.out是好的,但不是最好的一个。这是您执行的一次测试。在现实世界中,需求一直在变化,大多数时候您对现有的函数和类进行了大量的修改。所以... 不是每次测试已经编写好的代码。

在 JUnit 中还有一些更高级的特性,比如

断言声明

JUnit 提供了用于测试某些条件的方法,这些方法通常以断言开始,并允许您指定错误消息、预期结果和实际结果

其中一些方法是

  1. 让测试失败。可能用于检查未达到代码的某一部分。或者在实现测试代码之前进行失败的测试。
  2. assertTrue(true)/assertTrue(false)-永远是真/假。如果测试尚未实现,则可用于预定义测试结果。
  3. assertTrue([message,] condition)-检查布尔 condition是否为真。
  4. assertEquals([message,] expected, actual)-测试两个值是否相等(如果实现,根据 equals方法,否则使用 ==参考比较)。注意: 对于数组,检查的是引用,对于 没有的内容,使用 assertArrayEquals([message,] expected, actual)
  5. assertEquals([message,] expected, actual, delta)-测试两个浮点值或双精度值是否相距一定的距离,由 delta值控制。
  6. assertNull([message,] object)-检查对象是否为空

查看完整的 Javadoc 获得所有的例子 给你

套房

使用 Test 套件,您可以在某种意义上将 合并多个测试类集成到一个单元中,这样您就可以同时执行它们。一个简单的例子,将测试类 MyClassTestMySecondClassTest组合成一个称为 AllTests的套件:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;


@RunWith(Suite.class)
@SuiteClasses({ MyClassTest.class, MySecondClassTest.class })
public class AllTests { }

JUNIT 是 Java 开发人员通常接受的方法。 如果他们可以为函数提供类似的预期输入,并据此决定编写的代码是否完美,或者如果测试用例失败,那么可能还需要实现不同的方法。 JUNIT 将使开发速度加快,并将确保0缺陷的功能。

对于为什么需要 JUnit,我的看法略有不同。

实际上,您可以自己编写所有的测试用例,但是它很麻烦:

  1. 我们可以添加 if(value1.equals(value2))并返回0或 -1或错误消息,而不是 System.out。在这种情况下,我们需要一个“ main”测试类,它运行所有这些方法并检查结果,并维护哪些测试用例失败,哪些被传递。

  2. 如果您想要添加更多的测试,您也需要将它们添加到这个“主”测试类中。对现有代码的更改。如果您想从测试类中自动检测测试用例,那么您需要使用反射。

  3. Eclipse 不能检测到所有要运行测试的测试和主类,需要编写自定义的调试/运行配置来运行这些测试。但是,您仍然看不到那些漂亮的绿色/红色输出。

下面是 JUnit 正在做的事情:

  1. 它具有 assertXXX()方法,这些方法可用于从条件打印有用的错误消息,并将结果传递给“ main”类。

  2. “ main”类称为 runner,由 JUnit 提供,因此我们不必编写任何。并通过反射自动检测测试方法。如果您添加带有 @Test注释的新测试,那么它们将被自动检测到。

  3. JUnit 还具有 eclipse 集成和 maven/gradle 集成,因此运行测试很容易,而且不需要编写自定义运行配置。

我不是 JUnit 方面的专家,所以这就是我现在所理解的,将来还会有更多的内容。

如果不使用测试框架,您就不能编写任何测试用例,否则您将不得不编写测试框架来公正地对待您的测试用例。 除了可以使用 TestNG 框架之外,这里还有一些关于 JUnitFramework 的信息。

Junit 是什么?

Junit 与 Java 编程语言一起被广泛应用于测试框架中。您可以将这个自动化框架用于单元测试和 UI 测试。它帮助我们定义具有不同注释的代码的执行流程。Junit 建立在“先测试,然后编码”的思想之上,这有助于我们提高测试用例的生产力和代码的稳定性。

Junit 测试的重要特性 -

  1. 它是一个开源测试框架,允许用户有效地编写和运行测试用例。
  2. 提供各种类型的注释来标识测试方法。
  3. 提供不同类型的断言以验证测试用例执行的结果。
  4. 它还为有效地运行测试提供了测试运行程序。
  5. 这是非常简单的,因此节省时间。
  6. 它提供了以测试套件的形式组织测试用例的方法。
  7. 它以简单和优雅的方式给出测试用例结果。
  8. 你可以将 jUnit 与 Eclipse、 Android Studio、 Maven & Ant、 Gradle 和 Jenkins 集成在一起

观察并调整

以下是我对 JUNIT 的看法。

JUNIT 可以用来,
1)观察系统在添加新单元时的行为。
2)对系统进行调整,以迎接系统中的“新”单元。
- 什么?-没错。

现实生活。

当你的亲戚拜访你的大学宿舍时,
1)你会假装更有责任感。
2)你要把所有的东西放在它们应该放的地方,比如鞋子放在鞋架上而不是椅子上,衣服放在橱柜里而不是椅子上。
3)你要处理掉所有的违禁品。
4)你将开始清理你拥有的每一个设备。

用编程术语来说

系统: 您的代码
UNIT: 新功能。
由于 JUNIT 框架用于 JAVA 语言,所以 JUNIT = JAVA UNIT (可能)。

假设您已经有了一个防弹性很好的代码,但是出现了一个新的需求,您必须在代码中添加新的需求。这个新需求可能会破坏某些输入(testcase)的代码。

适应这种变化的简单方法是使用单元测试(JUNIT)。
为此,在构建代码库时,应该为代码编写多个测试用例。每当有新的需求出现时,您只需运行所有的测试用例来查看是否有任何测试用例失败。 如果没有,那么您就是一个 BadA * * 艺术家,并且您已经准备好部署新代码。
如果任何一个测试用例失败,那么您可以更改代码并再次运行测试用例,直到获得绿色状态。