单元测试普及(一):以前的测试方式

上一篇 / 下一篇  2012-09-29 09:30:31 / 个人分类:单元测试

 当然,我相信你一定会对自己的代码进行测试。没有人会在写完一大片代码之后,不经过运行就放到线上产品中。我的这篇文章主要还是想强调一下如何做测试。如果你并没能做到自动化测试,那么请你准备接受一次提高生产力和信心的洗礼。

wmTm)Aj!w9H"j0  提醒:我会在本文中提到单元测试和TDD。如果你已经对这些内容有所了解,那么你可以跳过下面这几条学习测试的理由而直接阅读后面部分,或者至少阅读结尾部分“你需要注意的理由”。51Testing软件测试网B9x i.mj

51Testing软件测试网/BX}\%u'w

  ● “我使用了类似jQuery这样的框架,这样已经能够确保我的代码工作正常。”51Testing软件测试网.[Ei*G(na/n

!pP_9rg-m ~r)aD1R0  ● “测试对于那些支持者而言是高级实践,但对于我来说不是”

@ s6TPN!D(F2t7b&x0

a1x;_ b%]^7{V5}0  ● “测试需要花费太多时间,我更愿意为产品编写代码”51Testing软件测试网b/_6yBC

0xI KsF3V2\0  不同的目的对应不同的测试

&mhT8wg&I:@,M0

\e,~muK0  测试包含了太多的内容,测试的方式也取决于你进行测试的目的。下面有几种测试方式,你可能会在你的应用中使用:

"f6^P-N3gvT051Testing软件测试网 YG5pw6p

  ● 可用性测试51Testing软件测试网+B C/bt ?7G5H

51Testing软件测试网xFaj(o\m-X C#D A

  ●性能测试51Testing软件测试网 u!L$I.w7E+LE~%PVd

51Testing软件测试网'D E ABUJ%fz

  ● 稳定性性/回归测试51Testing软件测试网-Cm"uFc-O$Tw

51Testing软件测试网4fv*a hq&{lr

  在本文中,我们会专注于稳定性和回归测试。换句话说,这类测试可以确保你的代码执行正确,并且不包含bug。在大部分情况下,绝对没有bug是不可能的。我们可以做的是采取一些有效措施来减少bug的数量,并且阻止老Bug的复现。51Testing软件测试网.LQ3Qr'_rI

51Testing软件测试网;?/C_%zpo;lA%m

  你是如何寻找bug的?51Testing软件测试网N)Jf+bZH

%\F^Mb)w0  程序员通常都需要应付程序的验收和bug的修复。在过去,这样的任务差不多都是通过调用alert然后刷新浏览器来检查变量的值,或者观察脚本的执行是否和期望的一致。51Testing软件测试网z6uan)|(E$yHD

51Testing软件测试网^Q{5r#I

  现在,大部分浏览器内置一个强大的控制台工具。对于那些没有内置控制台的浏览器,你也可以使用含有类似功能的Firebug Lite。调试过程基本类似:在代码中调用console.log,刷新浏览器来观察结果是否和期望的一致。

]5d8F1F y051Testing软件测试网{H7z#k~?#DSs Do

  调试:一个例子

w1k%}R"e n$t051Testing软件测试网AgQPY

  这里有一个调试用例,一个jQuery插件,用于将一个含有datetime属性(HTML5中的time元素)或者含有自定义属性data-datetime属性的元素中的innerHTML改为更容易人们阅读的字符串(比如:“3 hours ago”)。51Testing软件测试网R A)Z7L-J:t"bu o

jQuery.fn.differenceInWords = (function () {
^b-X2a3h5Z0 var units = {
"m8O6O HSd b0   second: 1000,
S$^3mT7A2i0   minute: 1000 * 60,
]_Xq7sB0   hour: 1000 * 60 * 60,51Testing软件测试网yqi1lM f\:y
   day: 1000 * 60 * 60 * 24,51Testing软件测试网#H u+r-}gF
   week: 1000 * 60 * 60 * 24 * 7,
5X'B:[,eqj K6u0   month: 1000 * 60 * 60 * 24 * 30
&S(A!qImNmk;h \0 };51Testing软件测试网aY.|$gNTd.p
 function format(num, type) {
O.h9d%Tx8@ h0  return num + " " + type + (num > 1 ? "s" : "");51Testing软件测试网.A)_vPR;sU o)^
 }
\lL8Sm2ft3d0 return function () {
YAX8w-Rl t0   this.each(function () {
si|`0R0     var datetime = this.getAttribute("datetime") ||51Testing软件测试网'|KX*N5O!vVKB
     this.getAttribute("data-datetime");51Testing软件测试网p2h7da1P7h3G)x)?~
     var diff = new Date(datetime) - new Date();
;vIU]4dG0     if (diff > units.month) {51Testing软件测试网5a.A+QUv#O#j
      this.innerHTML = "more than a month ago";51Testing软件测试网{!R+LO{ ik+V
     } else if (diff > units.week) {51Testing软件测试网 eL` g"{J~Rq
      this.innerHTML = format(Math.floor(diff / units.week), "week") + " ago";
_~Zw2_0N5^Q*E`yBE0     } else {51Testing软件测试网z1W!?aDF/\,c
       var pieces = [], num, consider = ["day", "hour", "minute", "second"], measure;51Testing软件测试网hml,G&f_9Zo
       for (var i = 0, l = consider.length; i < l; ++i) {
b|9}2@W-Jo0         measure = units[consider[i]];
-g&j+QgJ#dnC0         if (diff > measure) {51Testing软件测试网3k,Nu6E;V%x2he
         num = Math.floor(diff / measure);51Testing软件测试网 e6m+q)I|,M
         pieces.push(format(num, consider[i]));51Testing软件测试网2h@ qhw3i5S
       }
8`4|Od,e*]f0     }
;S$X*O^]qWw"s!qk0     this.innerHTML = (pieces.length == 1 ? pieces[0] :
/[&C*[pq0     pieces.slice(0, pieces.length - 1).join(", ") + " and " +51Testing软件测试网| yO4E9ll
     pieces[pieces.length - 1]) + " ago";51Testing软件测试网+jFjq(a1U"||
     }
,d0~b"_.z,H0   });51Testing软件测试网m4|(i8kz]&L z@
 };
o&HK Dc"si0}());
0P,S9A1yW)s,L0

:O$Fetj1G0  上面的代码首先处理了两个特殊情况:如果大于一个月则显示”more than a month“,如果大于一个星期显示对应大于的星期数。然后分别处理特定的天数,小时和秒。如果小于一天则直接省去天数,小时和秒的处理方法也如此。

8DNKW X!R051Testing软件测试网V0P Y}0t,i O

  虽然这段代码看起来比较合理,但是使用之后你会马上发现一些问题。8天之前这样的日期就会导致"and undefined"这样的结果。采用console.log方法进行调试,我们需要记录一些变量的值来判断什么地方出现问题。比如,通过记录不同的单 位,我们可以发现单位部分出了问题,因为日期字符串还可能包含时区,那么,ok,把这个问题修复掉:(此处作者将时区部分的字符串都替换成空字符串,其实 还应该包括以“-”开头的情况,此处为个人理解,如有异议可以联系我o(∩_∩)o)51Testing软件测试网#f7\of_z

9h6oaj3Gu-m![0  var diff = new Date(datetime.replace(/\+.*/, "")) - new Date();把日期的单位问题解决后,我们就可以得到“1 week ago”这样的答案。然后我们就可以将这个插件加入到产品中,然后继续做其他开发工作。

*?qmTq;q0

2}O,edq5J7jj0jUt0  第二天,有人告知我们说“3 days,80hours,4854minutes and 2912777 seconds”这样的结果是不可接受的。而造成这样结果的原因是我们没有对小于一周的日期进行处理。再次使用console.log进行调试,此刻我们 的代码中已经充满了log语句(或许包括了以前已经清理过的log语句),最后发现不同分支中剩余的差值没有被重新计算:

$l.I x+Ne2r4C051Testing软件测试网t'z0@*`Dcg

51Testing软件测试网;Z1]R]1L-_9h8ju

if (diff > measure) {
5i8y-F0a$T2as-D0 num = Math.floor(diff / measure);
d"w+vC1v-m0 diff = diff - (num * measure); // BUG: This was missing in our first attempt
F:no3G3TE!sB'M0 pieces.push(format(num, consider[i]));
h$Oqzv%c[0}

0Zy'v$g+? H0  现在我们已经定位并解决了这个bug,现在要做的就是去掉console.log语句,避免代码在那些不支持console对象的浏览器中报错。51Testing软件测试网Fgg$U$C Q

VO `fsT`*B;O0  断点调试

}*Ce"T0Y'e k051Testing软件测试网7~I8u/tu4_

  通过使用Firebug和一些类似的工具都可以轻易地实现对脚本的断点调试。但是大部分人还是认为console.log已经足够好用,特别是 和alert进行对比之后。确实,console不会阻塞UI,并且会让你觉得不需要太接近浏览器层面,但是它也只能做到如此。console.log调 试和alert调试法基本类似,有优雅之处,一样也有不优雅之处。51Testing软件测试网(\ d)c%Oa

51Testing软件测试网6x9v\2J'H/R

  一个更加复杂的方法是使用断点调试。51Testing软件测试网 hN9a7L9E

:O.xP~v#ggQ0

  使用断点调试的时候,你可以设置一些断点,然后查看所有相关变量,而不需要把变量一个一个记录下来。

,J B HQE0

  console.log带来的问题

)xj6{YM%_ h y,[0

  console.log式调试有一些问题。首先,console.log本身可能会带来一些问题。如果你曾经忘记在 重要的demo或者部署中移除调试代码,你肯定知道我说的是什么。如果浏览器不支持console对象,代码就会报错,包括在没有打开firebug的 Firefox中。“但是JavaScript是灵活的”,你可能会这么说。“你可以自己定义一个没有操作的console对象,然后这些问题就解决 了”。确实,你可以这么做,但这就像是你通过刷一层油漆的方式来解决车子生锈的问题。

*I"Ef"rR[ ekU X1]0

  如果使用console.log的方式不可接受,那么我们马上就会意识到下一个问题:。一旦一个调试策略已经定论, 你可以去掉所有的log语句。如果新的问题在同一处代码中出现,你还是回到了原来的方式,将原来美好的log语句重新引入。断点调试肯定是一个临时方案。 特设调试都是耗时,易于出错并且不可重复的解决方案。51Testing软件测试网Ge-w v'wc+h

51Testing软件测试网mMZ:]%H/I9V0X/k

TAG:

 

评分:0

我来说两句

Open Toolbar