关于java:为什么要使用JUnit进行测试?

Why use JUnit for testing?

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

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

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

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

另外,我从来没有在我刚刚学习的大型项目上工作过。

那么目的是什么呢?


这不是测试,而是"手动查看输出"(在biz中称为lmao)。更正式的说法是"手动寻找异常输出"(lmfao)。(见下文注释)

每当您更改代码时,必须运行应用程序和lmfao以获取受这些更改影响的所有代码。即使是在小项目中,这也是有问题的,并且容易出错。

现在可以扩展到50K、250K、1M loc或更多,并且在任何时候进行代码更改时都可以使用lmfao。它不仅令人不快,而且不可能:您已经扩展了输入、输出、标志、条件的组合,而且很难执行所有可能的分支。

更糟糕的是,lmfao可能意味着访问一页又一页的web应用程序、运行报告、在数十个文件和机器上浏览数百万条日志行、读取生成和发送的电子邮件、检查文本消息、检查机器人的路径、装满一瓶苏打水、聚合来自100个web服务的数据、检查fin的审计跟踪。辅助事务…你明白了。""输出"并不意味着几行文本,"输出"意味着聚合系统行为。

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

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

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


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

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

你可以这么说好的。

visual inspection works, I check that the code does what it's meant to
do, for these scenarios and once I can see it's correct we're good to
go.

Ok.

现在,首先,您对代码是否正确工作感兴趣是很好的。这是件好事。你已经领先了!遗憾的是,作为一种方法,这种方法存在一些问题。好的。

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

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

一双新的眼睛很难进入并验证代码的正确性,仅仅是因为它们没有与原始编码人员的大脑合作。第二对眼睛的所有者必须与代码的原始作者进行交谈,以便完全理解所讨论的代码。谈话作为分享知识的一种手段是众所周知的不可靠。一个点,如果原来的编码器是不可用的新对眼睛。在这种情况下,新的眼睛必须阅读原始代码。好的。

阅读没有被单元测试覆盖的其他人的代码比阅读有相关单元测试的代码更困难。阅读他人代码充其量是一项棘手的工作,最糟糕的是,这是软件工程中最繁琐的任务。有一个原因是,当招聘广告中出现职位空缺时,雇主强调一个项目是一个新的(或全新的)项目。从零开始编写代码比修改现有代码容易,因此广告工作对潜在员工更具吸引力。好的。

通过单元测试,我们将代码划分为其组件部分。然后,我们为每个组件设置一个暂停,说明程序应该如何工作。每个单元测试都讲述了一个故事,说明程序的某一部分在特定场景中应该如何工作。每个单元测试就像合同中的一个子句,从客户机代码的角度描述应该发生什么。好的。

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

首先,它们拥有代码本身、实现、代码是如何完成的;其次,它们拥有原始编码人员在一组正式语句中描述的所有知识,这些语句讲述了代码应该如何工作的故事。好的。

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

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

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

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

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

最后,提供测试允许您积极地重新考虑代码,因为您可以安全地对代码进行大的改进,因为您的更改不会破坏现有的测试。好的。

对于测试驱动的开发有一个警告,那就是您必须编写代码以使其可测试。这涉及到对接口的编码以及使用依赖注入等技术来实例化协作对象。看看肯特·贝克的作品,他很好地描述了TDD。查找接口编码并研究设计模式好的。好啊。


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

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

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

这样想:你也没有"测试"静态的东西。您的应用程序很可能会经历不断的变化。因此,这些单元测试被设计为在编译或部署周期的不同点上运行。或许最大的优势在于:

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


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

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

还有一些更高级的功能在JUnit中类似

断言语句

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

其中一些方法是

  • fail([message])—让测试失败。可能用于检查代码的某个部分是否未到达。或者在测试代码实现之前进行失败的测试。
  • assertTrue(true)assertTrue(false)-将始终为真/假。如果测试尚未实现,则可用于预先定义测试结果。
  • assertTrue([message,] condition)—检查布尔型condition是否正确。
  • assertEquals([message,] expected, actual)—测试两个值是否相等(根据equals方法,如果执行,否则使用==参考比较)。注:对于数组,是检查的引用,而不是内容,使用assertArrayEquals([message,] expected, actual)进行检查。
  • assertEquals([message,] expected, actual, delta)—测试两个浮点值或双精度值是否在一定距离内,由delta值控制。
  • assertNull([message,] object)—检查对象是否为空
  • 等等。有关所有示例,请参阅完整的javadoc。

    套房

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

    1
    2
    3
    4
    5
    6
    7
    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 { }

    我添加了一些其他系统。out不能:

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

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

    • 将测试代码与源代码分开

      朱尼特能做到。

    • 与CI集成

      朱尼特可以和蚂蚁和马文一起做。

    • 轻松地安排和组合测试用例

      JUnit可以做@Ignore和测试套件。

    • 易于检查结果

      JUnit提供了许多断言方法(assertEqualsassertSame…)

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

      JUnit可以做到:使用模拟和存根可以使您设置正确的夹具,并将重点放在测试模块逻辑上。


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


    JUnit是Java编程语言的单元测试框架。它在测试驱动开发中很重要,是单元测试框架(统称为XUnit)系列之一。

    JUnit提倡"先测试后编码"的思想,重点是为一段代码设置测试数据,这段代码可以先测试后实现。这种方法类似于"测试一点,代码一点,测试一点,代码一点…",它提高了程序员的工作效率和程序代码的稳定性,减少了程序员的压力和调试时间。

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

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

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

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

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

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

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

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

    JUnit在一个条中显示测试进度,如果测试正常,则该条为绿色,如果测试失败,则该条变为红色。


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

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

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

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

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

  • 朱尼特正在做的是:

  • 它有assertXXX()方法,可用于打印来自条件的有用错误消息,并将结果传递给"主"类。

  • "main"类称为runner,由junit提供,因此我们不必编写任何内容。并通过反射自动检测测试方法。如果添加带有@Test注释的新测试,则会自动检测它们。

  • JUnit也有Eclipse集成和Maven/Gradle集成,所以很容易运行测试,您不必编写定制的运行配置。

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


    您不能在没有使用测试框架的情况下编写任何测试用例,否则您将不得不编写测试框架来公正地处理您的测试用例。这里有一些关于JUnit框架的信息,除此之外,您还可以使用testng框架。

    Junit是什么?

    JUnit是广泛使用的测试框架以及Java编程语言。您可以在单元测试和UI测试中使用这个自动化框架,它帮助我们用不同的注释定义代码的执行流程。JUnit基于"先测试,然后编码"的思想,这有助于提高测试用例的生产率和代码的稳定性。

    JUnit测试的重要特性-

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

  • 单元测试采用白盒测试法。白盒测试是一种测试软件的方法,它测试应用程序的内部结构或工作。

    什么时候演出?单元测试是软件测试的第一级,在集成测试之前执行。

    https://onlyfullstack.blogspot.com/2019/02/junit-tutorial.html网站

    https://onlyfullstack.blogspot.com/2019/02/what-is-junit-how-to-use-junit.html


    JUnit:观察和调整

    这是我对朱尼特的看法。

    JUnit可以用来,1)在该系统中添加新装置时,观察系统行为。2)在系统中进行调整,欢迎系统中的"新"单元。什么?确切地。

    Real life eg.

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

    In programming terms

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

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

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


    JUnit是Java开发人员通常接受的方法。如果它们可以为函数提供类似的预期输入,并相应地决定编写的代码是完全编写的,或者如果测试用例失败,那么可能还需要实现不同的方法。JUnit将快速发展,确保功能零缺陷。