新手问题 测试的主要作用和必要体现在哪?

Catherine · 2015年12月12日 · 最后由 michael 回复于 2016年03月03日 · 11038 次阅读
本帖已被管理员设置为精华贴

现在在公司里写没有要求用到测试,空余时间想学点新的东西。

好像好的写代码习惯是 测试和代码 1:1..但作为个新手真不知道测试好在哪里,多花那 1 份的时间值在哪里....

举点形象的例子,或者自己的亲身经历跟我讲讲么..

可以不测啊,出问题了再修就可以了。

#1 楼 @lihuazhang 测试就是模仿在应用里的操作,而且尽可能考虑到所有在操作中出现的情况都写进测试?如果能写代码的时候严谨的考虑各种情况,效果也是一样吧?这样还真感觉测试有点不值呢..

前几天要改一个别人写的老方法,这个方法的上下文又比较多,全理清臣妾做不到,就是看测试代码理解这个方法的意图,通过跑测试确保我的改动没影响到别的功能。

所以我认为测试用处一是确保你的代码符合整个项目的预期,二是给后来的维护者说明你要解决的问题(因为文档咱们是不会好好写的,哈哈。文档没有动力维护,但是为了跑通测试你会主动维护测试的)

例如,升级 Ruby 版本,或者升级 Rails 版本的时候,或者升级某个 Gem,只要跑一下测试,就知道哪些地方不兼容,需要调整。

这个时候,如果人肉测试是要人命的。

#3 楼 @piecehealth 我明白了。另外关于文档,怎么都这么说啊,哈哈,上次一个朋友跟我说老板看到他写的文档后,问他小学语文老师是不是修锅炉的教的...

我觉得测试最大的意义在于添加/修改/删除一个功能后能尽量保证不影响别的功能。项目中相关的功能可能会很多,每次写完代码后要把相关的地方都手动测一遍很累也容易漏掉。

多花那 1 份的时间值在哪里

不值。但是如果你不写测试,你会多花 10 份时间,更不值。

感觉以后只要有人问测试意义的问题,就可以推荐@rei 这篇文章了。

现在我们公司就是没有测试代码,所有的修改都是人测。 五六万行的代码,每次完整测试一次都要三周。

举个刚遇到的问题。 Ticket 1: Windows 服务器用户名不应该接受非法的字符,例如 " ' / \ ? 等等特殊字符。

于是我加了代码,在 3 个 model 的 5 个判断处加上了 raise error if username =~ /.../.

Ticket 完成了,QA 输入了一个非法字符,成功拿到了错误提示,搞定。

真搞定了吗?没有。

第二周客户拿新版本去用,然后就遇到问题了。 Windows 服务器的用户名可以用反斜线分割域名和账号。 ↑看上面,我们把反斜线禁用了。 客户非常愤怒,让我们赶紧修。 Ticket 2: Windows 服务器用户名处无法输入 域名\用户名

于是我打开源代码,找到了正则表达式,去掉了反斜线。 随便测了一下,哦可以用了,搞定。

真搞定了吗?没有。

过了两天我们一个 Dev 来找我,说你这正则出现了 5 次却只改了 3 个地方啊……

噫 Ticket 3: ……

最近因为某些事情,需要重构公司的电商网站后台,从 node 迁移到 Rails,因为逻辑先于代码产生,自然的就开始 TDD……没错测试在重构的时候可以起到至关重要的作用,但测试不仅仅是一种检查代码的工具,更是一种工作流程,比如常说的 TDD、BDD,测试是下一步开发的开始,也是这一步开发的总结,通过测试很容易得到文档……

当然还有一种情况……比如我懒得写 UI 手测了,于是顺手写了几行测试跑通就好啦……

建议阅读《程序员修炼之道》,尤其是以下部分:

  • 提示 62:早测试,常测试,自动测试
  • 提示 63:要通过全部测试,编码才算完成

1 减少手工测试时间 通常写了一段代码,如果手工测试的话,得启动应用、登录、制造测试数据、人工验证结果。这时如果写一个单元测试,就省事多了。

2 有效避免引入 Bug 在开发新功能时,针对新功能,其实很难引入 Bug,因为开发人员会手工测试,可能还有会专门的 QA 进行测试;但却非常容易破坏原来的功能,QA 通常会问 Dev,你告诉我重点要测试哪些功能,Dev 通常会说,你还是全部测一遍吧。而如果有测试代码,就可以在编码过程中频繁地运行,在引入 Bug 的第一时间察觉到,从而将修复 Bug 的成本降到最低。

3 可以运行的活文档 看产品代码时一般很难看出业务规则,如果有测试代码,test case 的名称也比较好的话,就可以当文档来读了,并且如果对某段代码有疑问的话,可以很容易地修改或增加测试来验证自己的想法。

4 提前搞清需求细节 如果进行 TDD 的话,需要在开始编写产品代码前就要分析需求,设计测试用例,可以帮助开发人员提前搞清楚需求细节,而不是写一会儿发现一个问题又去问产品经理(这样对开发的效率影响是很大的)。

想写这么多,想到再补充。

持续集成。。。。

我也讲两句自己对测试的感受。

重构

原来带一个大部分是实习生组成的团队的时候,项目进行一个月的的时候,项目的代码简直不能看。我有心重构却不敢下手(真的可以体会到什么叫牵一发而动全身)。然后选择和团队老人一起做出各种测试的规范例子,让大家一定要 ShowCase 的时候不仅 show 功能还必须检查测试是否到位、规范。至少逐渐有了测试之后,我至少可以对某些不好的地方大胆放心的重构,那个感觉很爽。

理解代码

前段时间做一个 Ember 的插件,做了半年之后,发现自己以前写的代码不认识了,这个时候测试帮助我快速地理解这段代码。有时候去读一些其他人写的东西,尤其是一些文档更新跟不上的项目,规范的测试是一个不错的入手点。

代替文档

我的团队没有达到使用测试当做文档的地步,但是坐在我们旁边的团队确实做到了。在我们埋头写 github 的 wiki 时候,其实心里羡慕死他们了,不用刻意去维护文档。他们前端基本都不问后端接口的事情,直接看测试便知道。

保护现有功能的正常运行

重要的话说三遍! 一个爱折腾的人必须写测试! 一个爱折腾的人必须写测试! 一个爱折腾的人必须写测试!

先写这么多吧。

如果不在乎程序是否正确运行,重构之后也不在乎功能是否和原来一样,有了 bug 又不用(你)修,写测试就一点意义都没有了。

写测试是因为我在乎代码的功能是什么,如果不在乎的话,就不用写了啊。

这跟写代码的方式有关,相比写测试,我更愿意在写代码之前多思考一下。 还有就是大家要严格按规则写代码,我见一大批人,测试挂嘴边,然后等代码 提交上来。自己以前的测试都不过。

#19 楼 @isaaczeng 思考和测试都是必须的。 并不是写测试的人就没有思考能力了。

#20 楼 @msg7086 “这跟写代码的方式有关”这句话想必不用我解释吧,不要断章取义

重在回归,方便重构

  1. 你会忘掉代码的实现细节
  2. 你会维护别人移交的项目,但你不一定全部看过项目代码
  3. 别人会维护你移交的项目,但 TA 不一定全部看过项目代码

代码写一段时间就会忘记的,再想改就更难了。

基于测试用例的重构才是正确的重构。否则都叫重写。

偶觉得测试是为代码服务

  1. 测试很重要,重构,快速迭代,持续集成.. 这些好处随着项目的增大,会发现之前在测试花费的时间是值得
    1. 不要为了测试而测试,保证关键的业务和功能模块的单元测试和集成测试即可,写代码前多考虑一下代码的结构和复用也是很重要的。

写个简单的应用还好。

稍微写个复杂点的,总不能每次提交前都要手动把所有接口测一遍吧。 甚至有的开发就是测试驱动开发

测试驱动开发是学院派的臆想,现实中的需求可不仅仅是删帖、回帖、编辑这些简单的操作。现实中的需求如果全用测试模拟出来,会比开发项目本身还复杂,10 个人开发的项目,可能需要 20 个人去开发测试程序,不如雇佣 5 个人手工测试合算了。

以前开发过一个项目,这个项目每更新一个新版本后开发人员就会在生产环境把所有的功能测一遍。幸好项目功能不多。

这应该是一种信仰,不在乎对错。

多数时候测试更像是一个说明书,说明了功能代码的使用方式,会产生什么样的结果,这个时候看测试代码就能很快理解功能代码的意图,所谓的 TDD 就是干这个事,一般也就做到这个程度了; 至于保证程序健壮性的测试,那么必须对边界条件非常清楚,而且保证测试代码覆盖到所有可能的情况(理想状态),这种意义上的测试,成本就很高了,得看项目的性质,是否值得这么干

曾经深入接触过专业测试团队,200 人以上。 其实,把测试理解成信仰,总体来说有点过了。不过对程序员来说,也无可厚非。 作为软件生命周期的一部分,测试不能少,就像我们人类正常生命中,不能缺少钙元素一样。测试,类似体能锻炼,这样才能保证钙元素的充分吸收和循环。

正所谓测试驱动开发,再则,当一个程序足够大时,你不得不写测试了。

Ruby 不写测试不心虚么.. 一个误写的字符就能搞挂程序 这算是非编译型语言优点还是弱点呢 :trollface:

#28 楼 @hi2016 这是因为你没有做好 Isolation,而不是测试本身太难写。推荐去看看 https://www.destroyallsoftware.com/screencasts

36 楼 已删除

#4 楼 @libuchao 所得有道理,感觉测试在重构中的作用更大

测试还是挺重要的,我现在写代码有时没环境,全靠脑补 这样写出来的代码如果没有测试,兼职是灾难。

测试驱动能在开发的时候指导你设计接口,因为写测试必然先写怎么用调用接口,然后再实现它,这样能防止写出翔一样的接口。 重构时,重构没有改变代码行为的依据。 修改 bug 时,先写 bug 复现的测试,再解决 bug,有效保证以后的代码修改引入同样的 bug。

先想到这么多,最后,相信我,写测试的时间远低于今后你为了测试同一个地方的可用性而进行的手动测试的时间。

测试对于程序来说,不是必不必要的问题,而是怎么测的问题。就算不写测试,你一样在人肉测试。只不过人肉测试效率太低,出错率也高,对于中等和以上规模的程序,需要写测试来代替人肉测试,以减轻工作强度罢了. 功能和代码不断的扩充,不断重构和优化,这个过程中,没有好的测试,基本就掉入修 bug 泥潭了。有话说改一个 bug 带来 3 个 bug, 自动测试一定程度上可以减轻这个状况。 总之,逻辑简单,或者写完没有更改的必要,类似这种代码人肉测测也无可厚非,逻辑稍微复杂的,以后更改的可能性存在的,那么自动测试毫无疑问是必要的。

简单说,我觉得至少有三点:

测试可以模拟条件和输入输出,让你不需要运行程序,不需要打开额外窗口,不需要用鼠标或者键盘去交互,就能知道模拟出来的结果。这比人工测试快很多。比如说你想测试下密码组合的验证模块,你认为是用测试代码来获取结果方便,还是人工往密码框里输入各种组合方便?

假如你的软件涉及到生命财产安全,举个极端的例子,例如火箭发射或者医疗器械的软件,你觉得可以不测试,然后出了问题再修???

白盒测试可以给你代码覆盖率,让你对自己的代码执行流程有个更深的了解。可以发现更多潜在的 bug,漏洞和无用代码。

有一种情况下不用测试,就是程序很小,只有一种输出。那你跑一遍然后看下结果就可以当成是测试,也就不需要测试代码。

业务逻辑特别复杂,需要测试。例如游戏的逻辑,签到,抽奖什么的,必须的写测试

需要 登录 后方可回复, 如果你还没有账号请 注册新账号