Art*_*lev 132 java tdd junit unit-testing
也许我的问题是一个新手,但我不能真正理解我将使用junit的情况?
无论我是编写简单的应用程序还是更大的应用程序,我都会使用System.out语句测试它们,并且它对我来说很容易.
为什么在项目中创建带有JUnit的测试类,如果我们仍然需要调用相同的方法,检查它们返回的内容,那么我们是否需要注释所有内容?
为什么不写一个类并一次测试它System.out而不是创建Test-classes?
PS.我从未参与过我刚刚学习的大型项目.
那么目的是什么?
Dav*_*ton 134
那不是测试,那就是"手动查看输出"(在商业中称为LMAO).更正式地,它被称为"手动查找异常输出"(LMFAO).(见下面的注释)
每次更改代码时,必须为受这些更改影响的所有代码运行应用程序和LMFAO.即使在小型项目中,这也是有问题且容易出错的.
现在可以在任何时候进行代码更改时扩展到50k,250k,1m LOC或更多,以及LMFAO.它不仅令人不愉快,而且是不可能的:你扩大了输入,输出,标志,条件的组合,而且很难运用所有可能的分支.
更糟糕的是,LMFAO可能意味着访问网页上的网页,运行报告,浏览数十万个文件和机器上的数百万条日志行,阅读生成和发送的电子邮件,检查短信,检查机器人的路径,填写一瓶苏打水,汇总来自一百个网络服务的数据,检查金融交易的审计跟踪......你明白了."输出"并不意味着几行文本,"输出"意味着聚合系统行为.

最后,单元和行为测试定义系统行为.测试可以由持续集成服务器运行并检查其正确性.当然,也可以System.out,但CI服务器不会知道其中一个是否错误 - 如果是,它们是单元测试,你也可以使用框架.
无论我们认为我们有多好,人类都不是好的单元测试框架或CI服务器.
注意:LMAO 正在测试,但是在非常有限的意义上.在整个项目中或作为流程的一部分,它不能以任何有意义的方式重复.它类似于在REPL中逐步开发,但从未将这些增量测试正式化.
Rob*_*lty 50
我们编写测试来验证程序行为的正确性.
通过用眼睛检查输出语句的内容来验证程序行为的正确性是一个手册,或者更具体地说,是一个可视化过程.
你可以争辩
视觉检查工作,我检查代码是否做了它的意图,对于这些场景,一旦我看到它是正确的,我们很高兴去.
现在,首先,您对代码是否正常工作感兴趣.这是好事.你处于领先地位!可悲的是,作为一种方法存在问题.
目视检查的第一个问题是,你是一个糟糕的焊接事故,从而无法再次检查你的代码的正确性.
第二个问题是使用的眼睛与眼睛主人的大脑紧密耦合.如果代码的作者也拥有视觉检查过程中使用的眼睛,则验证正确性的过程依赖于视觉检查员大脑中内化的程序的知识.
一双新眼睛难以进入并验证代码的正确性,因为它们与原始编码器的大脑没有合作.第二对眼睛的拥有者将不得不与代码的原始作者交谈,以便完全理解所讨论的代码.作为分享知识的手段,对话是众所周知的不可靠的.如果原始编码器不适用于新配对眼睛,那么这一点就没有实际意义了.在那种情况下,新的眼睛必须阅读原始代码.
读取单元测试未涵盖的其他人的代码比阅读具有相关单元测试的代码更困难.最好阅读其他人的代码是棘手的工作,最坏的情况是这是软件工程中最棘手的任务.雇主在宣传职位空缺时强调一个项目是一个绿地(或全新)项目,这是有原因的.从头开始编写代码比修改现有代码更容易,从而使广告工作对潜在员工更具吸引力.
通过单元测试,我们将代码划分为其组成部分.对于每个组件,我们然后设置我们的停顿,说明程序应该如何表现.每个单元测试都讲述了程序的这一部分应该如何在特定场景中起作用的故事.每个单元测试就像合同中的一个条款,它描述了从客户端代码的角度来看应该发生什么.
这意味着一双新眼睛在所讨论的代码上有两行实时和准确的文档.
首先,他们拥有代码本身,实现,代码如何完成 ; 第二,他们拥有原始编码器在一组正式陈述中描述的所有知识,这些陈述讲述了这段代码应该如何表现的故事.
单元测试捕获并正式描述原作者在实现课程时所拥有的知识.它们提供了客户端使用时该类行为的描述.
你是否正确地质疑这样做是否有用,因为有可能编写无用的单元测试,不覆盖所有相关代码,变得过时或过时等等.我们如何确保单元测试不仅模仿,而且改进了知识渊博,尽职尽责的作者在运行时直观地检查其代码的输出语句的过程?首先编写单元测试然后编写代码以使测试通过.完成后,让计算机运行测试,他们很快就能完成重复性任务,非常适合工作.
每次触发他们测试的代码并运行每个构建的测试时,通过查看测试质量来确保测试质量.如果测试失败,请立即修复.
我们自动执行运行测试的过程,以便在每次构建项目时运行它们.我们还自动生成代码覆盖率报告,详细说明测试涵盖和执行的代码百分比.我们追求高百分比.如果代码更改没有足够的单元测试来描述代码行为的任何变化,则有些公司会阻止将代码更改签入到源代码控制中.通常,第二对眼睛将与更改的作者一起审查代码更改.审核人员将通过更改确保更改可以理解且充分涵盖测试.因此,审核流程是手动的,但是当测试(单元和集成测试以及可能的用户验收测试)通过此手动审核流程时,它将成为自动构建流程的一部分.每次签入更改时都会运行这些更改.持续集成服务器在构建过程中执行此任务.
自动运行的测试,维护代码行为的完整性,并有助于防止将来更改代码库以破坏代码.
最后,通过提供测试,您可以积极地重新调整代码因素,因为您可以在知道更改不会破坏现有测试的情况下安全地进行大规模代码改进.
测试驱动开发有一个警告,那就是你必须编写代码以使其可测试.这涉及编码到接口并使用诸如依赖注入之类的技术来实例化协作对象.查看Kent Beck的工作,他很好地描述了TDD.查找编码到接口并研究设计模式
jmo*_*253 13
当您使用类似System.out之类的东西进行测试时,您只测试了一小部分可能的用例.当您处理可以接受几乎无限量的不同输入的系统时,这不是很彻底.
单元测试旨在允许您使用大量不同的数据输入快速运行应用程序上的测试.此外,最佳单元测试还考虑了边界情况,例如位于被认为有效边缘的数据输入.
对于人类来说,测试所有这些不同的输入可能需要数周时间,而机器可能需要几分钟.
可以这样想:你也没有"测试"一些静态的东西.您的应用程序很可能会经历不断变化.因此,这些单元测试旨在在编译或部署周期的不同点运行.也许最大的优势是:
如果您在代码中破坏了某些内容,那么您现在就会知道它,而不是在部署之后,而不是在QA测试人员发现错误时,而不是在您的客户取消时.你也有一个更好的机会立即修复故障,因为很明显,破坏了有关代码部分的事情很可能发生在你上次编译之后.因此,大大减少了解决问题所需的调查工作量.
我添加了一些其他System.out不能做:
使每个测试用例独立(这很重要)
JUnit可以这样做:每次创建并@Before调用新的测试用例实例时.
从源代码中分离测试代码
JUnit可以做到.
与CI集成
JUnit可以使用Ant和Maven来完成.
轻松安排和组合测试用例
JUnit可以做@Ignore和测试套件.
易于检查结果
JUnit提供了许多Assert方法(assertEquals,assertSame...)
模拟和存根使您专注于测试模块.
JUnit可以这样做:使用mock和stub让你设置正确的fixture,并专注于测试模块逻辑.
单元测试确保代码按预期工作.它们也非常有用,可以确保代码仍然按预期工作,以防您以后必须更改它以构建新功能来修复错误.对代码进行高测试覆盖后,您可以继续开发功能,而无需执行大量手动测试.
您的手动方法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 在这里.
使用测试套件,您可以将多个测试类组合到一个单元中,以便您可以一次执行所有测试类.一个简单的例子,将测试类MyClassTest和MySecondClassTest一个Suite 组合在一起,称为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 { }
Run Code Online (Sandbox Code Playgroud)
JUnit的主要优点是它是自动化的,而不是您手动检查打印输出.您编写的每个测试都保留在您的系统中.这意味着如果您进行具有意外副作用的更改,您的测试将捕获并失败,而不是您必须记住在每次更改后手动测试所有内容.
| 归档时间: |
|
| 查看次数: |
61787 次 |
| 最近记录: |