测试 关于单元测试的一些疑惑

jarorwar · 2013年08月19日 · 最后由 jarorwar 回复于 2013年12月10日 · 6405 次阅读

写 ruby 代码也有 2 个月多了。rails 当然是必配的。 但是单元测试写的真的不多。可以说基本没怎么写~!。说下原因吧。 1、不太习惯 rails 里面这种单元测试的方式,在学习的时候,对单元测试也没太深入,所以可能不是很顺手的说~! 2、前几天耐着性子写了一个,但是过了几天,业务改变,再运行的时候惨不忍睹。。如果想炮通,必须修改测试代码。。个人感觉浪费时间啊~!(其实改个功能性的东西,或者页面的东西,花了 10 分钟改完了,单元测试写了 10 分钟,然后再调试,又花了 10 分钟,终于跑通了)我是这么一情况啊

不知道各位大神有什么建议啊~!欢迎拍砖,拍石头,下冰雹。,狠狠的砸吧~

=======

update

不知道有木有创业的兄弟,创业项目在时间紧迫的情况下,还有坚持写测试代码吗?

目测 LZ 没参与过多人团队的开发,要不然应该不会这么说的吧

#1 楼 @mouse_lin 目前,ror 我一个人在这里写,所以真的没参与过。求指教。。漂亮的图像啊

#2 楼 @jarorwar 多人开发,或者大型项目时候,如果你不写测试,别人去改代码,没测试的话,倘若改错,返工可是很大成本;你可以去 github 上面参与一些开源项目看看,就简单,你 fix 一个 gem 的 bug,都必须提供对应测试案例

#3 楼 @mouse_lin 哦。。但是写测试代码确实非常浪费时间。

楼主写得测试让咱们看看?

#5 楼 @iBachue 因为 测试跟不上业务的修改速度。我已经从代码里删除了。这样你怎么折腾都是 ok 的了。。所以。。。

#5 楼 @iBachue 正打算好好学习下,继续写呢http://ruby-china.org/topics/2848~!。一起学,共勉

不写测试没什么大不了的,只不过是没有按照最佳实践来, 代码里不按最佳实践写的地方多了去了。

但是这些技术债是迟早要还的。

#4 楼 @jarorwar 是花费时间不是浪费时间,单纯浪费时间的话就没人会去写测试了。我现在觉得写测试反而能提高效率,比起修改—保存—刷新,然后在页面上点来点去,可能还要填写一大堆测试数据强多了。

#10 楼 @PrideChung 哦。同意你的观点。我现在的测试数据都是直接在 seeds 里造好的。。这是不是有点 2

#11 楼 @jarorwar 想问一个问题,你说业务改变就惨不忍睹等等……你做的不是产品而是项目,需求来自于客户,你只是“听”,对吗?

#12 楼 @nightire 我们做的是项目,客户就是自己内部的运营人员。很多时候需求是否合理是不不用我们判断的,我们只要实现即可~!(有些东西是没有理由的,无条件服从)。另外,一个需求可能会波及很多个模块,如果要改的话,每个模块都要改~!

#14 楼 @bhuztez 3ks 的确是这样子。不知道各位的团队有密有测试人员。我们测试组的测试人员 就是纯手工打造的。。哈哈。。

#11 楼 @jarorwar 用 seed 还算好了,起码不是手工填数据。刚开始尝试写测试,可以不按全套 TDD 的做法来,完全掌握 TDD 需要不少时间,起步的时候会让你的产出率下降得相当严重,可能一天只能提交十几行产品代码,十分打击人。

我的应对做法是 Test After,在写好一个最小逻辑单元(通常是一个方法,或者函数)后再写测试代码,通过测试后再继续写产品代码。只测试一些比较关键的,出了错不容易发现的部分,通常是 Model,从来没有测过 UI。这样对产出率的影响比较小,也容易坚持下去。我自己不搞全套的 TDD,经常 Test After,更加不追求测试覆盖率。

当你在界面上点来点去为了 debug 一个功能的时候,考虑写个测试吧。

#16 楼 @PrideChung 谢谢了。我慢慢学习吧。

OK,我先说第一个问题:需求是否合理不过问,无条件实现。

在这个问题下,测试能帮助我们什么呢,比如说覆盖方法或模块的边界条件就是很好的例子。假如说你不写测试,在需求未变的情况下出了 bug,排查再修改的时间会更“浪费”。但如果有之前的测试做底子,你只需要用测试重现 bug,然后再重构就好了,目的性和指向性极强。

至于说需求变更导致测试和代码都要重写,这个我只能说很遗憾,测试原本就是为了忠实于需求的,需求本身都变了,测试能不变吗?你觉得因此而多写了代码(测试)很累,这是可以理解的,不过为了以后着想,以及为了团队所有成员的协作着想,这是值得的。

最后,如果需求总是变来变去,请不要责怪测试,因为这是你们团队整体的问题,或者是和其他利益相关方的沟通问题。

第二,需求会涉及多个模块,要改都得该。

这……是测试的错吗?或许你们应该从设计角度来考虑一下现在的代码实现,看看耦合度是不是太高了?或者类和模块的抽象度和通用度不够/可以改进?

大体上你可以有两种“武器”来解决依赖性问题的测试,一种是验收测试(有时候可以在一些情况下和集成测试互换概念,但这样并不好,所以 RSpec 和 Capybara 才会单独分离出 Features Spec),它不太关注系统模块中的耦合情况,而是从输入/输出的角度来做一个黑盒测试;比如说,从用户在界面上的操作开始,到用户看到的视觉反馈结束,隐藏中间的系统实现过程。

还有一种就是单元测试了,单元测试则完全不应该受系统模块的耦合约束,需要相互依赖调用的可以使用 stubbing / mocking。

所以说,就算你无法改变高耦合这样的项目现状,你也完全可以采取不同的测试策略来减少耦合带来的修改联动性;注意,不是说实现代码不用改,而是把测试分离开避免修改的联动性导致测试被连带修改。这样一来,被联动的代码只要其对应的业务逻辑(需求)没变,测试就不需要大改特改。

然而说到底,我还是觉得这是代码设计层面不够好,好的设计不应该总是“牵一发而动全身”,除非需求变化的太频繁,太剧烈——还是回到最初,这不是测试的问题,而是团队本身或沟通的问题。

最后,“Typing is not the bottlebeck”,不要误解“因为写了测试,所以我要多打/多改一倍的代码,浪费时间”,这种想法根本上就是带有偏见的,狭隘的。

===回答你最后一句话===

越是时间紧急,越要写测试,特别是创业项目——人无远虑,必有近忧!

#18 楼 @nightire 非常感谢您的耐心回答~!”代码设计层面不够好,好的设计不应该总是“牵一发而动全身”“这个我想才是根本原因。现在的测试我木有写,后面我抽空补上。可能主要是因为自己对测试这块的东西不太熟悉吧。所以写起来即费劲,又慢,挫折感强~!所以就看看各位兄弟是怎么弄的。以前做 java 的时候,junit 还是必备的,不过也只是针对 java 的 service 类。到了 ruby 这里,因为入门级别。所以就没有花太多时间去写测试。从而造成了恶性循环:不会写--->不想写--->写的慢--->挫折感--->不想写~!呵呵。

#19 楼 @jarorwar 抱歉,我不太会 Java,但仅就单元测试而言,我觉得也不会相差很大吧?

如果你觉得自己写测试水平还不够高,那就先像过去写 Java 一样对一些重要的业务逻辑写单元测试吧。等有空闲的时间了再尝试着补别的层级的测试也不失为一个办法。

请参考 Ken Beck (测试驱动开发的开创人) 对这个问题的回答

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.

#20 楼 @nightire 嗯。区别不是很大。只是 ruby 可以做到对 conroller,对 view 层的测试。这些在 java 里面(至少我觉得 80%)以上的中国程序员都没有去写~呵呵

#21 楼 @blacktulip 嗯。我想也是这样的吧~今天开始看书,学习。谢谢各位了~ @nightire ,真是良师啊~ 最近 ruby 写的我不想写 java 代码了。无奈,时不时还要去写一些。。呵呵

已经开始学习写测试了。赶脚不错啊。factory_girl 真的能创造无数美女吗~!

#22 楼 @jarorwar 写的一个 cms,java 代码加注解只有 400 多行,用 Gradle 进行单元测试,测试代码达到了 2200 多行....

#22 楼 @jarorwar 其实我是看到了80%的中国java程序员才忍不住过来吐槽的.....controller 可以使用Easymock,view 层可以使用EmmaJspTest 一起测,当然集成spring test后使用注解会变得更加简单 (是非常简单).....话说 java 本来就是做企业级web应用的,怎么可能没有相应的测试框架....写好单元测试是一个 java 程序员的最基本的素质或者说是每一个程序员的基本素质吧......还有,我读 java 的开源代码,都是从单元测试入手...这样才能读懂各个模块的功能啊....

#26 楼 @wjch 我只能说你很牛,或者你可以说我很菜。工作了四年,走过的企业从几十人到几千人,乃至万人的都走过,我不是说没有测试框架,我只是说很少写测试。至少本人(你可以鄙视我)写过的测试只是基于 service 层的,jsp 和 controller 层的没写过~!不知道您在那个公司高就。这么多的框架这么多的测试都做完了,我对您感到深深的尊敬~(谈不上崇拜)!

#25 楼 @wjch 能把您 400 行代码的 cms 分享给我看一下吗?最近正需要一个呢~!,谢了!

非常理解 lz。。。 看回复,大家都非常认同测试,我也标识认同。。。 但是真的是非常的费时间。。。 我就最后问大家一个问题,大家都有写测试吗?

@wjch 400 行 java 你没有漏算 import 吧?还有页面 jsp (相信你不会把查数据库之类的放 jsp 里吧?), 还有各种 web.xml, pom.xml 配置文件...

写功能性代码的测试就可以了 比如 Model 里的大多数方法

#27 楼 @jarorwar 不好意思,我只是个学生,这个 cms 是暑假没事接的活,小的商业项目,不方便透漏,毕竟要负责,肯定要写好测试,不经常上 ruby china,所以刚看到,看到我吐槽,请宽容些,请不要想喷子一样的发火. #31 楼 @luikore 用 JFinal+ 注解,至于配置文件,这是个什么东西?这又不是 ssh,你可以写工具类自己解析配置...而且我说的是 java 代码,不用想也知道肯定是指有效的生产代码,又不包括模型类和由美工写的前端,也不是所谓的配置和注解.java 解放生产力的东西多的是,不要一说 java 就想到 SSH 或 SSI 好不好...

400 行 Java 就能写出 CMS 来啊,好厉害

#33 楼 @wjch 哦,不包括模型 400 行还算正常啦...

#31 楼 @luikore 不过确实是用到 maven 了,这个项目模块名我叫 cdedu-cms,,通用数据库模块叫 db-generictype...泛型是刚学的....而且这个 cms 还没有权限功能....我也正在学权限功能的实现...

嗯嗯,用注解一下就可以省好多代码啊,又想起用 servlet 写 cms 的一个 dao 类就是几百行的极度苦逼...这个一下就简化了好多...也在试着学 ror,打算用它来学一些比较流行的技术....

#33 楼 @wjch 我想说的是理论跟实践永远不是一回事情。学生时代你有的是时间烧~上班了(一旦进入互联网公司),你就没有时间了。业务牛的,每月的发版频度是很大的。这个不是忽悠你~,所以,没有那么多时间给你去搞这个,搞那个,(我们是每周发一次【还是必发】)还不算有时候线上 bug 临时补发~!

#38 楼 @jarorwar 这......这么苦逼? 😨 .嗯,多谢提醒...确实还是应该抓紧时间找个妹子....

当然要写测试。。懒一点的话,只写 capybara 就好了

#39 楼 @wjch 建议你不要搞 java 了。高 ruby 吧。妹子不是问题。。

#40 楼 @xstmjh 谢谢。涨知识了。顺便问个问题。我在 factory_girl 里的测试数据怎么初始化到 test 库呢?

我刚开始学,教程里也是推荐 TDD(测试驱动开发)。→_→http://railstutorial-china.org/ 个人感觉比 { 开发->测试 } 这个流程效率要高,最重要的还是测试用例的设计,如果没做过测试的话这方面可能是要生疏点。

#26 楼 @wjch 其实用 play framework 会让生活更美好

#45 楼 @sanivbyfish play 没发跟 rails 比啊。。我说的是真的。我是从 play 进入 rails 的。

#46 楼 @jarorwar 当然是 java 的层面,我没写 rails 之前玩了一段时间 Grails,但问题在于他的 render 模板太慢,后来转用 play,发现 play 比传统得开发好。

现在当 rails 面前他们都是浮云

  1. 重构现有代码时,回归测试时,是否会产生相关的 bug,提高软件质量
  2. 改进现有功能时,集成测试时,是否对 API 有相关影响,增强向后兼容性
  3. 提交新的代码时,代码覆盖率测试时,是否有冗余代码,提高代码的可维护性
  4. TDD 或 BDD 开发流程时,解释代码的作用,提高代码的可读性

单元测试是上述测试的基础,如果@jarorwar没有上述需求,可以不用写单元测试,无非就是 a. bug 多点(增加客服人员和测试人员) b. 代码行数多了之后,不知道相关代码的作用(只增加,不删除或修改代码) c. 不提供对上一个版本的支持(宣传是新品,另收费) d. 看到有问题的代码,有可能改出更多,更严重的问题或将问题埋的更深 (能不改就不改)

更多的问题尚未发现,望砖之。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号