单元测试具体怎么做到底是什么?应该怎么做

为什么要做单元测试?发布时间:
&&& 从前,单元测试谁都做不了或者成本太高,无论做或不做单元测试,都不会从根本上影响项目和企业的生死存亡。VU4的问世,使单元测试变得很简单并且效益巨大,做单元测试和不做单元测试,质量和成本将有重大差别,有可能影响到项目和企业的生死存亡。 &&& 如果项目周期不紧张,开发成本随意,反而可以不做单元测试,因为,只要有足够的后期测试,足够的应用检验,产品一样有高质量。说到底,质量问题是成本问题。&&& 华为有句名言:我们没有时间把事情一次做好,却总是有时间把事情一做再做。没有时间做单元测试,一定会有更多的时间来查错改错,区别在于,前者是主动的、可控的,后者是被动的、不可控的。&&& 无论项目处于哪个阶段,立即使用VU4实施单元测试,都会缩短项目周期。 &&& 过去可能不行,因为单元测试成本很高,多数接包方做不了,代码质量不可靠也没办法。现在有了VU4,单元测试已经很简单了,完全应该要求承包方做好单元测试,完成MC/DC指标,并且提交测试代码、测试数据和测试报告,只有这样,才能保证项目的代码质量。 &&& 如果在投标时承诺做好单元测试,保证完成MC/DC指标,承诺提交测试代码、测试数据和测试报告,将大幅提升竞争力。如果对手没有同样的承诺,则很可能被秒杀,因为任何发包方都必然重视项目的代码质量。赞助商链接
很多人做过单元测试,可能对单元定义没有较真过,其实普通小名词蕴含大概念。Martin Fowler在其 一文中对单元定义是一个类,一个类中可能有很多方法行为,单元不能粒度太细,也不能太粗,太细了就容易范DHH批评的宗教原教旨主义,也就是形式主义,影响了正常软件设计意图,太粗了则达不到持续交付的目标,软件BUG频出。这场讨论是来自Rails之父DHH提出“TDD已死”的讨论,主要是针对单元测试在Web框架比较难以实施,因为普通Web框架中就是一个MVC框架,Model实际是数据库,在MVC结构下单元测试无法插足,一般是使用变种的Controller,这使得C控制器的含义变成两个,一个是MVC的控制器,用于数据库模型Model和视图View的交互;另外一个专门用于对模型Model测试的,”TDD已死“派认为这样不妥,破坏了控制器原本设计含义。其实,banq我个人意见还是坚持以前的想法,这种尴尬是因为MVC这种不合时宜的结构模式造成的,我2010年曾经写了一篇:,里面实际谈到了MVC模式的僵化,建议以DCI等架构,当然包括后来的DDD/CQRS来替代,从今天观点来看,这样才能真正避免MVC模式和单元测试的冲突。Ruby阵营的另外一位牛人Andrzej Krzywda发表了更加佐证了我当初的观点。在这篇文章中,AK认为单元的定义需要从你采取的技术架构上定义,在一文中已经谈及了六边形Hexagonal架构 干净的架构和DDD/CQRS以及DCI。AK举了一个例子,如果你有订单Order, 一个订单中有很多订单条目OrderLines, 以及一个货运地址ShippingAddress和一个客户Customer. 那么你是否为这四个对象建立四个单元测试呢?很显然不是,而是只要为Order这个类建立一个单元测试就可以了,为什么呢?因为通过Order对象测试已经可以掌握整体了。测试可能从未知道ShippingAddress的存在。因为这是单元Order的内部实现细节。所以,一个类并不是一定是一个好的单元,通常是一组类。单元的定义是为了让你测试,而不管被测试单元内部如何变化,这是单元测试的设计目标,这样你在每次重构时就不必改变测试代码了。从DDD角度看,Order其实是一个聚合根,也就是说,单元测试中单元是指为每个聚合根做一个测试就可以了。一个DDD aggregate聚合是一组领域对象,能够被看成一个单元就可以了。在“干净的架构”中有一个用例的概念有所涉及,是通过一组操作来定义的。在“六边形架构”中有关于一个单元周围被适配器adapters围绕, 这个单元通常称为Middle Hex。在“DCI”架构中,DHH引述James Coplien的TDD的谈话。James已经小有名气,不仅从他对TDD有过强烈推动和意见,而且更多的他在DCI世界的活动。他是这项运动的创始人之一。 DCI是这里最鼓舞人心的架构。Ruby和DCI其实是一个梦幻般的组合。 DCI提供了良好的工具用于定义一个单位是什么。定义一个上下文为一个单元,一个单元是一组对象的协作的范式。[该贴被banq于 09:29修改过]
作为Ruby的MVC框架Rails创建者之所以提出TDD已死,其中一个原因可能是他已经深刻感受到MVC与TDD的矛盾之处,这种矛盾如同对象和关系数据库,已经到了水火不容,不可调和地步,也许只有宣布一方死亡才可保持另外一方的存在。其实随着后端RESTful架构和微服务的兴起,SpringMVC这种昔日MVC框架其实已经褪化成了REST框架,而前端MVC框架AngularJS的兴起正好说明了这种趋势。可能的情况下,Rails这种Ruby MVC框架如同SpringMVC,虽然打着MVC框架名头,实际其已经是一个RESTful框架,其控制器已经不是协调Model和View之间的调节者,而是一个响应REST中POST/GET等动作的处理器Handler,在这个处理器中实现对领域业务层的单元测试,就相当自然和优雅了。在Bob大叔的中,他提到MVC是作为适配器层,对业务规则的实体用例与外部Web进行适配,其实这个定义扭曲了MVC本来的定义,而REST的处理器作为适配器层是最恰当的。
/** * 保存一个操作步骤到队列中去 * $skip = new Skip();$skip-&setActionResult("同意");$skip-&setNextStep(5);$skip2 = new Skip();$skip2-&setActionResult("不同意");$skip2-&setNextStep(3);$as = new ActionStep();$as-&addSkip($skip);$as-&addSkip($skip2);$as-&setActionClassName("TwoResultAction");$as-&setPosition("副支队长@");$as-&setStepName("支队分管审批");$as-&setStepNum(4);$que = new ActionQueue(1);$que-&addActionStep($as);echo R::store($que-&getBean());==========================现实中,很自然的以聚合根作为基本测试单元。最原始的丑陋测试代码,没有用测试用例,白盒测试,自动化什么的。
赞助商链接
赞助商链接
最佳分辨率
OpenSource
Code & 2002-20谈谈单元测试之(一):为什么要进行烦人的单元测试? - CSDN博客
谈谈单元测试之(一):为什么要进行烦人的单元测试?
最近,在网上看到过一个调查,调查的内容是“程序员在项目开发中编写单元测试的情况”。当然,至于调查的结果,我想聪明的你已经可以猜到了。高达 58.3% 的比例,一般情况下不写单元测试,只有偶尔的情况才会写写。16.6% 的程序员从来都不写单元测试。只有很少的一部分程序员才会在自己的代码中进行单元测试,并保证方法测试通过。看到这些,你想到了什么?
虽然,这个调查可能会有些片面性,但这也基本反应了国内程序员的开发现状,很少有程序员能够比较认真的去编写单元测试。而且,甚至有的程序员根本就不知道为什么要写单元测试(这一点让我很郁闷)。他们经常会说,公司里不是有测试人员嘛,测试应该是他们要做的事,我们的工作只是开发(这位仁兄肯定没有学过软件工程)。当然,这些并不是偶然的,正如佛经里边说的“因果循环”,有果必有因。那么,到底是什么原因,导致程序员对单元测试这么不感冒呢?
通过与几个朋友的讨论,以及网上的调查,主要有这几种原因,导致程序员对单元测试很排斥,或许说很不以为意。
不知道怎么编写单元测试项目没有要求,所以不编写单元测试价值不高,完全是浪费时间业务逻辑比较简单,不值得编写单元测试不管怎样,集成测试将会抓住所有的 bug,用不着进行单元测试在项目的前期还是尽量去编写单元测试,但是越到项目的后期就越失控为了完成编码任务,没有足够的时间编写单元测试。编写单元测试会导致不能按时完成编码任务,导致项目延期
很显然,这几种原因归根结底,无外乎就是不了解单元测试,自认为很聪明,自己懒不想去测试,对项目的时间、进度把控不好。下面,我将一 一进行分析,剖析出程序员的开发心理,以此来给朋友们提个醒,最终聪明反被聪明误。
不知道怎么编写单元测试
这个问题在于,还没有接触过单元测试,同时,也没有体会过企业级的代码开发。不知道同时也不了解单元测试能带给你什么。设想一下,当你开发完一个功能模块的时候,你如何确定你的模块没有 bug 呢?如果涉及到具体的业务,你会执行 debug 模式,然后一点一点的深入到代码中去查看吗?如果你一直都是这样,那么你早就已经 OUT 了。赶快去了解一下单元测试的工具吧,你会收获很大的。
项目没有要求,所以不编写
这个问题反映出了一种现象,同时也是一种习惯。项目有没有要求,只能说明项目的管理上不严格,并不是程序员不编写单元测试的理由。他们在以往的开发中,并没有养成写单元测试的好习惯。可想而知,他们的代码质量,我就不敢恭维了。给个建议,尝试着写漂亮的代码,之所以因为漂亮,是指得健康、简洁、健壮。当然,完成漂亮的代码就离不开单元测试了。
单元测试价值不高,完全是浪费时间
这种说法其实是错误的。为什么这么说呢?在日常的开发中,代码的完工其实并不等于开发的完工。如果没有单元测试,那么如何保证代码能够正常运行呢?测试人员做的只是业务上的集成测试,也就是黑盒测试,对单个的方法是没有办法测试的,而且,测试出的 bug 的范围也会很广,根本不能确定 bug 的范围,还得去花时间来确定 bug 出在什么地方。难道这就不浪费时间了吗?甚至,这样的方式,时间浪费的会更多。
业务逻辑比较简单,不值得编写单元测试
所谓的业务逻辑比较简单,其实是相对的。当你对某一块业务逻辑很熟悉的时候,你自然会认为它很简单。然而,单元测试的必要性并不是仅仅在于测试代码的功能是否正确,还在于,当其他同事在了解你的业务的时候,能够很快的通过单元测试来熟悉代码的功能,甚至不用去读代码,就能够知道它做了哪些事情。因此,写单元测试不仅是解放了自己,更方便了别人。
项目前期还在尽量写测试,到了后期就失控了
这种问题的原因在于,对项目进度、项目中的技术点研究时间、人员的沟通、业务需求的熟悉程度等没有把控好。这个问题的出现并不是个人的问题,而是反映了项目管理中存在的问题。当然,个人的原因也存在,就是如何在有限的时间里,提高效率。这一点需要大家好好思考一下了。我的建议,多做计划,根据实际情况变更计划。多和项目组长、组成员进行沟通。及时反应项目中存在的问题。
为了完成编码任务,没有足够的时间编写单元测试
这个问题在于,程序员领取的任务较为复杂,或者自己的开发效率有待提高。其实,开发任务是包括编码和单元测试的。在领任务的时候,应该跟据自身的能力,跟组长或经理沟通好,以便留出一定的测试时间。当然,提高自己的编码效率也是很有必要的。至于如何提高开发效率,网上有很多这样的文章,这里就不再赘述了。
测试常常是程序员十分厌倦的一个活动。测试能给我们带来什么?了解这些是非常重要的,测试不可能保证一个程序是完全正确的,但是测试却可以增强我们对程序完整的信心,测试可以让我们相信程序做了我么期望它做的事情。测试能够使我们尽早的发现程序的 bug 和不足。
一个 bug 被隐藏的时间越长,修复这个 bug 的代价就越大。在《快速软件开发》一书中已引用了大量的研究数据指出:最后才修改一个 bug 的代价是在 bug 产生时修改它的代价的10倍。
当然,我们主要讨论的是单元测试。单元测试是一个方法层面上的测试,也是最细粒度的测试。用于测试一个类的每一个方法都已经满足了方法的功能要求。在开发中,对于自己开发的模块,只有在通过单元测试之后,才能提交到 SVN 库 或者 Git 库。
正是由于测试在开发中的重要地位,才会在IT界刮起了 TDD 的旋风。TDD,也就是测试驱动开发模式。它旨在强调在开发功能代码之前,先编写测试代码。也就是说在明确要开发某个功能后,首先思考如何对这个功能进行测试,并完成测试代码的编写,然后编写相关的代码满足这些测试用例。然后循环进行添加其他功能,直到完成全部功能的开发。
说了这么多,那么都有什么工具(框架)能帮助我们完成可重复的单元测试呢?下面我就介绍几个常用的。这里只介绍 Java 语言的。其他语言的请问谷老师(Google)。
JUnit(推荐使用JUnit4)
JUnit 在日常开发中还是很常用的,而且 Java 的各种 IDE (Eclipse、MyEclipse、IntelliJ IDEA)都集成了 JUnit 的组件。当然,自己添加插件也是很方便的。JUnit 框架是 Java 语言单元测试当前的一站式解决方案。这个框架值得称赞,因为它把测试驱动的开发思想介绍给 Java 开发人员并教给他们如何有效地编写单元测试。
TestNG,即Testing Next Generation,下一代测试技术。是根据JUnit和NUnit思想,采用 jdk 的 annotation 技术来强化测试功能并借助XML 文件强化测试组织结构而构建的测试框架。TestNG 的强大之处还在于不仅可以用来做单元测试,还可以用来做集成测试。
这里仅仅是介绍一下有哪些最常用的 Java 单元测试工具,对于如何使用这些工具,在后续的博客中会有介绍,这里就不再多说了。有兴趣的请关注后续的文章。
俗话说,一屋不扫,何以扫天下。开发中,我们自己的代码都不能保证功能的正确性,那么还有什么效率可言呢?做再多的任务,写再多的代码也只不过是在搭鸡窝,做着机器一样的重复的工作。IT界有一个原则,DRY原则 —— Don't Repeat Yourself !只有通过对自己的工作不断的检查,不断的测试,才能不断的突破,不断的脱颖而出,当然,你才能不断的提高。
Test Day Day Up!&Experience Day Day Up!&And
Money Day Day Up Too!
哎呀妈呀,中国式英语又出来了!
本文已收录于以下专栏:
相关文章推荐
单元测试是开发人员对代码逻辑进行的测试,需要写单元测试代码来实现。单元测试里面是调用函数,根据返回的结果去判断代码逻辑是否正确。通常的操作是CRUD,除了查询之外的操作都是要与数据库打交道的。比如删除...
上一篇文章《为什么要进行烦人的单元测试?》讨论了一下现阶段软件开发中,程序员们测试情况的现状。这篇文章中,我打算介绍一下单元测试的工具(插件),并且推荐大家以后在开发中,真正的用上单元测试,...
测试在软件声明周期中的重要性,不用我多说想必大家也都非常清楚。软件测试有很多分类,从测试的方法上可分为:黑盒测试、白盒测试、静态测试、动态测试等;从软件开发的过程分为:单元测试、集成测试、确认测试、验...
在ITOO高校云平台项目实践中,我们模板的模块因为在调别人的接口时出现了问题,为了弄明白是不是接口出了问题,就必须学会单元测试。
单元测试(unit testing),是指对...
摘要:单元测试是软件测试的基础,本文详细的论述了单元测试的两个步骤人工静态检查法与动态执行跟踪法,所需执行的工作项目及相关的策略和方法。通过对这两个步骤的描述作者将多年的单元测试经验及测试理论注入于全...
单元测试的重要性 
序:这是一篇写给所有开发者的建议,虽然不包含技术成分,但比技术本身成为重要.
测试的必要性
上一篇文章《测试工具 JUnit
3》简单的讨论了 JUnit 3 的使用以及内部的方法。这篇文章将会在 JUnit 3 的基础上,讨论一下 JUnit 4 的新特性。同时,与 JUnit...
单元测试好比房屋建筑现场的建筑监理员,他关心房屋的各个内部系统,如地基、构架、供电系统和管道设备等。房屋每部分工作都安全、正常。 单元测试是从开发者的角度来编写的。它们确保类的每个特定方法成功执行一系...
单元测试与功能测试之间的区别发布时间:
12:09    作者: kxhu    来源: kxhu的专栏字体:  小  中  大  | 上一篇 下一篇 | 打印  | 我要投稿  ...
codeception 基础使用[简译]
当我们使用 codeception 页面对象代码时,这些代码扩展自 BasePage 类。这样可以减少些重复。yii2-app-basic 和 yii2-a...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)到底什么是单元测试
什么是单元测试
首先需要介绍一下什么是单元测试。很多人像我一样,本科并不是计算机专业出身的,如果在职的公司不要求做单元测试的话,可能对这个词并没有一个确切的概念。而即使是计算机专业出身,如果毕业以后写的不多的话,可能对这个词的含义也不是很清楚。
什么是单元测试
首先需要介绍一下什么是单元测试。很多人像我一样,本科并不是计算机专业出身的,如果在职的公司不要求做单元测试的话,可能对这个词并没有一个确切的概念。而即使是计算机专业出身,如果毕业以后写的不多的话,可能对这个词的含义也不是很清楚。从名字上看,单元测试是为了测试某一个代码单元而写的测试代码。但是什么叫“一个代码单元”呢?是一个模块、还是一个类、还是一个方法(函数)呢?不同的人、不同的语言,都有不同的理解。一般的定义,尤其是是在OOP领域,是一个类的一个方法。在此,我们也这样理解:单元测试,是为了测试某一个类的某一个方法能否正常工作,而写的测试代码。
我们举一个例子说明一下,假如你有一个类,定义如下:
public class Calculator {
public int add(int one, int another) {
return one +
那么为了测试这个Calculator类的add()方法,我们可以写如下的单元测试代码:
public class CalculatorTest {
public void testAdd() throws Exception {
Calculator calculator = new Calculator();
int sum = calculator.add(1, 2);
Assert.assertEquals(3, sum);
这里的CalculatorTest是Calculator对应的测试类。而这里的testAdd()就是add()这个方法对应的测试方法。所以,写单元测试,就是给你的每个类的每个public方法写对于的测试方法。非public方法我们一般是不测试的,虽然可以通过反射等手段去做,但是一般看来,非public方法是这个类的实现细节,我们并不关心,我们只关心某一个public方法的输入、输出。
一般来说,一个方法对应的测试方法主要分为3部分,以上面的测试方法为例:
一般来说,我们写单元测试,会用到一些单元测试框架。常见的Java单元测试框架有、等等。在这个系列的文章中,我采用JUnit 4,这也是用的最多的一个测试框架。上面的第三部,Assert.assertEquals(3, sum); 用的就是JUnit里面的验证结果的方法,最常见的就是调用Assert类的一些assert方法。除了上面用到的assertEquals,还有assertTrue, assertNotNull等等。关于JUnit,我会在后面的系列文章中专门介绍。
如何在一个android project里面运行单元测试
我们知道,在一个android gradle project中,源代码默认是放在src/main/java下面的。而对应的单元测试代码则是放在src/test/java下面的,如下图所示:
其中的package name可以随意定,很多人喜欢跟src package name保持一致,我个人习惯在最后加上.test后缀,因为AndroidStudio太智能了,经常我需要重命名单元测试的package的时候,AndroidStudio会把src的package也给重命名了。
打开CalculatorTest,用鼠标右键点击testAdd()方法,选择Run testAdd(), 如下图所示:
从图中你可以看出,你可以按快捷键Ctrl+Shift+R快速运行,当然,这要求你的光标当前焦点是在这个方法内部的。如果你的焦点是在类内部,而不在某一个测试方法内部,那么Ctrl+Shift+R将运行这个测试类的所有测试方法。当然,你也可以通过右键点击测试类名来运行这个测试类里面的所有测试方法。
运行结束以后,你会在底部的“Run”这个tab看到运行的结果,如下图所示:
除了在AndroidStudio里面运行,你还可以在命令行通过gradle testDebugUnitTest,或者是gradle testReleaseUnitTest,分别运行debug和release版本的unit testing,这种方式可以一次性运行所有测试类的所有测试方法。 这种方式的运行结果如下图所示:
每个test case的报告可以在project_root/app/build/reports/tests/debug/index.html 这个xml里面看到。大致如下图:
这篇文章的代码在上,感兴趣的可以clone下来自己试试。
单元测试不是集成测试
这里需要强调一个观念,那就是单元测试只是测试一个方法单元,它不是测试一整个流程。举个例子来说,一个Login页面,上面有两个输入框和一个button。两个输入框分别用于输入用户名和密码。点击button以后,有一个UserManager会去执行performlogin操作,然后将结果返回,更新页面。
那么我们给这个东西做单元测试的时候,不是测这一整个login流程。这种整个流程的测试:给两个输入框设置正确的用户名和密码,点击login button, 最后页面得到更新。叫做集成测试,而不是单元测试。当然,集成测试也是有他的必要性的,然而这不是我们每个程序员应该花多少精力所在的地方。在这方面,有一个理论叫做,如下图所示:
Test Pyramid理论基本大意是,单元测试是基础,是我们应该花绝大多数时间去写的部分,而集成测试等应该是冰山上面能看见的那一小部分。
为什么是这样呢?因为集成测试设置起来很麻烦,运行起来很慢,发现的bug少,在保证代码质量、改善代码设计方面更起不到任何作用,因此它的重要程度并不是那么高,也无法将它纳入我们正常的工作流程中。
而单元测试则刚好相反,它运行速度超快,能发现的bug更多,在开发时能引导更好的代码设计,在重构时能保证重构的正确性,因此它能保证我们的代码在一个比较高的质量水平上。同时因为运行速度快,我们很容易把它纳入到我们正常的开发流程中。
至于为什么集成测试发现的bug少,而单元测试发现的bug多,这里也稍作解释,因为集成测试不能测试到其中每个环节的每个方面,某一个集成测试运行正确了,不代表另一个集成测试也能运行正确。而单元测试会比较完整的测试每个单元的各种不同的状况、临界条件等等。一般来说,如果每一个环节是对的,那么在很大的概率上,整个流程就是对的。虽然不能保证整个流程100%一定是对的。所以,集成测试需要有,但应该是少量,单元测试是我们应该花重点去做的事情。
那对于这个例子,单元测试是怎么样的呢?这个请看下一小节。
两种函数(方法),两种不同的测试方式
一个类的方法可以分为两种,一种是有返回值的,另一种是没有返回值的。对于有返回值的方法,我们要测起来比较容易,就跟上面的Calculator例子那样,输入相应的参数,得到相应的返回值,然后验证得到的返回值跟我们预期的值一样,就好了。
但是没有返回值的方法,要怎么测试呢?比如说刚刚login的例子,点击那个按钮,会执行Activity的login()方法,它的定义如下:
public void login() {
String username = ...
String password = ...
mUserManager.performlogin(username, password);
这个方法是void的,那么怎么验证这个方法是正确的呢?其实仔细想想,这个方法也是有输出的,它的输出就是,调用了mUserManager的performLogin方法,同时传给他两个参数。所以只要验证mUserManager的performLogin方法得到了调用,同时传给他的参数是正确的,就说明这个方法是能正常工作的。
那怎么样验证这个Activity的login()方法,会调用mUserManager的performLogin方法呢?这里涉及到的概念,在后面的文章关于Mockito的使用的时候,会介绍到,这里简单解释下,那就是在测试环境下,我们会使用一套mock framework(Mockito),生成一个mock的UserManager然后赋值给mUserManager,因为这个mUserManager是通过mock framework生成的,所以这个mock framework可以验证它的什么方法被调用了,参数是什么,等等。
上面讲述了单元测试的定义,以及与集成测试的区别,一般来说,单元测试不会接触到数据库,不会接触到网络,不会接触到一些复杂的外部环境,如果有的话,那可能是你测试的方式有误,测试的粒度不够“单元”,希望这篇文章能将这两者的区别解释清楚。
如果文中有任何的错误或疑问欢迎留言。
转自:/82788/
特别说明:尊重作者的劳动成果,转载请注明出处哦~~~http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt372
版权声明:本文内容由互联网用户自发贡献,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至: 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
用云栖社区APP,舒服~
【云栖快讯】红轴机械键盘、无线鼠标等753个大奖,先到先得,云栖社区首届博主招募大赛9月21日-11月20日限时开启,为你再添一个高端技术交流场所&&
移动测试(Mobile Testing)是为广大企业客户和移动开发者提供真机测试服务的云平台,拥有大量热门机型,...
全球领先的SaaS性能测试平台,具有强大的分布式压测能力,可模拟海量用户真实的业务场景,让应用性能问题无所遁形。
业内领先的面向企业的一站式研发提效平台,通过项目流程管理和专项自动化提效工具,能够很好地支持互联网敏捷项目的快速...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
阿里云双11狂欢,不只是5折
Loading...关注51Testing
单元测试要做多细?
发表于: 13:31 &作者:StackOverflow & 来源:51Testing软件测试网采编
推荐标签:
  这篇主要来源是StackOverflow上的一个回答——“How deep are your unit tests?”。一个有13.8K的分的人(John Nolan)问了个关于TDD的问题,这个问题并不新鲜,最亮的是这个问题的Best Answer,这个问题是——  “TDD需要花时间写,而我们一般多少会写一些代码,而第一个测试是测试我的构造函数有没有把这个类的变量都设置对了,这会不会太过分了?那么,我们写的这个单元的粒度到底是什么样的?并且,是不是我们的测试测试得多了点?”  答案  StackOverflow上,这个问题的答案是这样的——  “I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don’t typically make a kind of mistake (like setting the wrong variables in a constructor), I don’t test for it. I do tend to make sense of test errors, so I’m extra careful when I have logic with complicated conditionals. When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.”  老板为我的代码付报酬,而不是测试,所以,我对此的价值观是——测试越少越好,少到你对你的代码质量达到了某种自信(我觉得这种的自信标准应该要高于业内的标准,当然,这种自信也可能是种自大)。如果我的编码生涯中不会犯这种典型的错误(如:在构造函数中设了个错误的值),那我就不会测试它。我倾向于去对那些有意义的错误做测试,所以,我对一些比较复杂的条件逻辑会异常地小心。当在一个团队中,我会非常小心的测试那些会让团队容易出错的代码。  这个回答对TDD似乎有一种否定,最亮的是这个问题是由Kent Beck,Kent是XP和TDD的创造者,是开发实践方法的奠基人。以致于还有人调侃到——  The world does not think that Kent Beck would say this! There are legions of developers dutifully pursuing 100% coverage because they think it is what Kent Beck would do! I have told many that you said, in your XP book, that you don’t always adhere to Test First religiously. But I’m surprised too.  只是要地球人都不会觉得Kent Beck会这么说啊!我们有大堆程序员在忠实的追求着100%的代码测试覆盖率,因为这些程序员觉得Kent Beck也会这么干!我告诉过很多人,你在你的XP的书里说过,你并不总是支持“宗教信仰式的Test First”,但是今天Kent这么说,我还是很惊讶!  后面还有一些人不同意Kent, 我一下子从这个事中想到了《fight club》里的那个精神分裂者创建了一个连自己都反对的地下组织。呵呵。  其实我是非常同意Kent的,怎么合适怎么搞,爱怎么测试就怎么测试,只要自己和团队有信心就可以了。没有必要就一定要写测试,一定要测试先行。  其它答案  八卦完了,我们还是来认认真真地看看这个问题中其它的其它答案,因为这个问题的也是国人爱问题的问题。  第二个答案:值得借鉴  开发过程中,单元测试应该来测试那些可能会出错的地方,或是那些边界情况。  维护过程中,单元测试应该跟着我们的bug report来走,每一个bug都应该有个UT。于是程序员就会对自己的代码变更有两个自信,一是bug 被 fixed,二是相同的bug不会再次出现。  第三个答案:给敏捷咨师看的答案  这个答案在说,我们只注意到了TDD中的T,而忽略了第一个D,就是Driven…… bla bla bla… 又这扯这些空洞的东西了,国内的各种不学无术的敏捷咨询师最好这一口了。  第四个答案:致那些什么都要测试的人  如果我们需要测试一个像 int square(int x) 这样的开根函数,我们需要40亿个测试(每个数都要测试)。  事实上这种情况可能还更糟糕,如果有这样一个方法 void setX(int newX) 不会更改其它的成员变量,如:obj.z, Obj.y,那么,你是不是还要去测试一下别的变量没有被改变?  我们只可能测试那些有意义的,确实要测试的案例。  我的观点  我在《TDD并没有看上去的那么美》一文中说过我的观点了,我就不再多说了。我还是把下面这些观点列出来,供大家思考和讨论:  1)我国的教育对我们最大的洗脑不是掩盖事实,而让我们习惯于标准答案,习惯于教条,从而不会思考!敏捷开发中的若干东西似乎都成了中对某种标准答案的教条,实在是悲哀!  2)软件开发是一种脑力劳动,是一种知识密集型的,就像艺术作品一样,创作过程和成品是没有标准答案的。  3)软件的质量不是测试出来的,而是设计和维护出来的。就像工匠们在一点一点地雕琢他们的作品一样。  UT的粒度是多少,这个不重要,重要的是你会不会自己思考你的软件应该怎么做,怎么测试。
搜索风云榜
51Testing官方微信
51Testing官方微博
测试知识全知道

我要回帖

更多关于 js如何做单元测试 的文章

 

随机推荐