ChatGPT解决这个技术问题 Extra ChatGPT

为什么使用 JUnit 进行测试?

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

无论我是编写简单的应用程序还是大型应用程序,我都使用 System.out 语句对其进行测试,这对我来说非常容易。

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

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

PS。我从未参与过我刚刚学习的大型项目。

那么目的是什么?

您知道每次更改程序中的任何内容时,您之前手动检查输出的所有工作都将失效,您必须从头开始重做它们?
不仅仅是“测试”,“聪明的测试”也很重要。这是一个很好的例子:wp.me/prMeE-11

D
Dave Newton

那不是测试,那是“手动查看输出”(在商业中称为 LMAO)。更正式地说,它被称为“手动查找异常输出”(LMFAO)。 (见下面的注释)

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

现在,只要您更改代码,就可以扩展到 50k、250k、1m LOC 或更多,以及 LMFAO。这不仅令人不快,而且是不可能的:你已经扩大了输入、输出、标志、条件的组合,而且很难运用所有可能的分支。

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

https://willjessop4.files.wordpress.com/2010/01/sad_panda.jpg

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

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

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


第一句话是-1,这是完全不真实的。
R
Rob Kielty

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

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

你可以争辩说

目视检查有效,我检查代码是否完成了它的意图,对于这些场景,一旦我看到它是正确的,我们就可以开始了。

现在首先,很高兴您对代码是否正常工作感兴趣。这是好事。你走在了曲线的前面!可悲的是,这种方法存在问题。

目视检查的第一个问题是,您将永远无法再次检查代码的正确性,这是一次严重的焊接事故。

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

仅仅因为它们没有与原始编码器的大脑合作,就很难有一双新的眼睛进来并验证代码的正确性。第二双眼睛的拥有者必须与代码的原作者交谈才能完全理解有问题的代码。众所周知,对话作为一种分享知识的方式是不可靠的。如果原始编码器对新的眼睛不可用,则这一点没有实际意义。在那种情况下,新的眼睛必须阅读原始代码。

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

通过单元测试,我们将代码分成其组成部分。然后,对于每个组件,我们设置了我们的摊位,说明程序应该如何运行。每个单元测试都讲述了程序的该部分应如何在特定场景中运行的故事。每个单元测试就像合同中的一个条款,从客户端代码的角度描述应该发生的事情。

这意味着一双新的眼睛有两股关于相关代码的实时和准确的文档。

首先,他们有代码本身、实现、代码是如何完成的;其次,他们拥有原始编码器在一组正式陈述中描述的所有知识,这些陈述讲述了该代码应该如何表现的故事。

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

您质疑这样做的用处是正确的,因为有可能编写无用的单元测试,不涵盖所有有问题的代码,变得陈旧或过时等等。我们如何确保单元测试不仅模仿而且改进了知识渊博、尽职尽责的作者在运行时目视检查其代码的输出语句的过程?首先编写单元测试,然后编写代码以使该测试通过。完成后,让计算机运行测试,它们速度很快,它们擅长做重复性任务,它们非常适合这项工作。

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

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

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

最后,提供测试可以让您积极地re-factor code,因为您可以安全地对代码进行重大改进,因为您知道您的更改不会破坏现有测试。

Test Driven Development 有一个警告,那就是您编写代码时必须着眼于使其可测试。这涉及对接口进行编码并使用诸如依赖注入之类的技术来实例化协作对象。查看 Kent Beck 的工作,他很好地描述了 TDD。查找 coding to interfaces 并研究


j
jmort253

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

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

人类测试所有这些不同的输入可能需要数周时间,而机器可能需要几分钟。

可以这样想:您也不是在“测试”静态的东西。您的应用程序很可能会不断变化。因此,这些单元测试旨在在编译或部署周期的不同点运行。也许最大的优势是:

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


卢声远 Shengyuan Lu

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

使每个测试用例独立(这很重要)JUnit 可以做到:每次将创建新的测试用例实例并调用 @Before。

从源 JUnit 中分离测试代码可以做到这一点。

与 CI JUnit 的集成可以通过 Ant 和 Maven 完成。

轻松安排和组合测试用例 JUnit 可以做@Ignore 和测试套件。

易于检查结果 JUnit 提供了许多 Assert 方法(assertEquals、assertSame...)

模拟和存根使您专注于测试模块。 JUnit 可以做到:使用 mock 和 stub 让您设置正确的夹具,并专注于测试模块逻辑。


A
Adowrath

单元测试确保代码按预期工作。它们也非常有助于确保代码仍然按预期工作,以防您以后必须更改它以构建新功能来修复错误。对代码进行高测试覆盖率可以让您继续开发功能,而无需执行大量手动测试。

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

JUnit中还有一些更高级的功能,比如

断言语句

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

其中一些方法是

fail([message]) - 让测试失败。可用于检查代码的某个部分是否未到达。或者在实现测试代码之前进行失败的测试。 assertTrue(true) / assertTrue(false) - 永远是真/假。如果测试尚未实施,可用于预定义测试结果。 assertTrue([message,] condition) - 检查布尔条件是否为真。 assertEquals([message,] expected, actual) - 测试两个值是否相等(如果实现则根据 equals 方法,否则使用 == 引用比较)。注意:对于数组,检查的是引用,而不是内容,请使用 assertArrayEquals([message,] expected, actual) 。 assertEquals([message,] expected, actual, delta) - 测试两个 float 或 double 值是否彼此相距一定距离,由 delta 值控制。 assertNull([message,] object) - 检查对象是否为空

等等。有关所有示例 here,请参阅完整的 Javadoc。

套房

使用测试套件,您可以在某种意义上组合多个测试类到一个单元中,这样您就可以一次执行它们。一个简单的示例,将测试类 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 { } 

n
n00begon

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


A
AKKI

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

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

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

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

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

为运行测试提供测试运行器。

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

JUnit 非常简单。它不那么复杂,花费的时间也更少。

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

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

Junit 在测试进度条中显示测试进度,如果测试正常,则显示为绿色,测试失败时变为红色。


S
Sreekar

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

您实际上可以自己编写所有测试用例,但这很麻烦。以下是问题:

我们可以添加 if(value1.equals(value2)) 并返回 0 或 -1 或错误消息,而不是 System.out。在这种情况下,我们需要一个“主”测试类来运行所有这些方法并检查结果并维护哪些测试用例失败和哪些通过。如果您想添加更多测试,您还需要将它们添加到这个“主”测试类中。对现有代码的更改。如果要从测试类中自动检测测试用例,则需要使用反射。 eclipse 不会检测到您的所有测试和运行测试的主类,您需要编写自定义调试/运行配置来运行这些测试。不过,您仍然看不到那些漂亮的绿色/红色输出。

这是 JUnit 正在做的事情:

它具有 assertXXX() 方法,可用于从条件打印有用的错误消息并将结果传达给“主”类。 “main”类叫做runner,它是JUnit提供的,所以我们不用写。它通过反射自动检测测试方法。如果您使用 @Test 注释添加新测试,则会自动检测到它们。 JUnit 也有 eclipse 集成和 maven/gradle 集成,所以运行测试很容易,您不必编写自定义运行配置。

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


我想在第一部分中,如果没有 JUnit,我们会做些什么来使单元测试比 system.out.println 语句好一点。可能JUnit是一些程序员这种尝试的结果,他们觉得有必要编写一个单独的测试框架来执行这种自动化,因此JUnit诞生了,可能是。
R
Rob Kielty

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

什么是朱尼特?

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

Junit 测试的重要特性 -

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


m
mohit sarsar

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


R
Rohit Singh

JUNIT:观察和调整

这是我对 JUNIT 的看法。

JUNIT 可用于: 1)在系统中添加新单元时观察系统行为。 2)对系统进行调整,迎接系统中的“新”单元。什么?确切地。

现实生活例如。

当您的亲戚访问您的大学宿舍时,1)您会假装更负责任。 2)你会把所有的东西放在它们应该放在的地方,比如鞋架上的鞋子不在椅子上,衣橱里的衣服不在椅子上。 3)你会摆脱所有的违禁品。 4)您将在您拥有的每台设备中开始清理。

在编程方面

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

假设你已经有一个很好的防弹代码,但是一个新的需求来了,你必须在你的代码中添加新的需求。这个新要求可能会破坏您的某些输入(测试用例)的代码。

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