2008年10月20日星期一

带上用户的那顶帽子

你可曾在复杂的功能测试代码中挣扎着找出测试意图: 人肉过滤准备数据的过程. 抽丝剥茧的找到测试所覆盖的业务流程,猜测它究竟在测什么?

我们来看看这个测试:
userA logIn
rerun "defaultStage"
verify "defaultStage" is triggered and wait for completed
verify pipeline label of "defaultStage" is "1"
verify "secondStage" is triggered and wait for completed
verify pipeline Stage" is "1"

无可否认,测试达到了目的,验证了系统行为与期待一致。问题是这个测试中的“期待”到底是什么?

在带上用户的帽子回答这个问题的时候,我们很快意识到
verify "defaultStage" is triggered and wait for completed
verify pipeline label of "defaultStage" is "1"
对于用户来说意味着:
newly created "defaultStage" should be ran in the same pipeline

而后两句:
verify "secondStage" is triggered and wait for completed
verify pipeline Stage" is "1"
意味着:
next stage should be triggered automatically.

于是测试变成了:

userA logIn
rerun "defaultStage"
newly created "defaultStage" should be ran in the same pipeline
next stage should be triggered automatically.

测试变得更加可读,测试意图也变得更加明显。

作为Developer的特质之一就是细节驱动,我们将各种业务需求整理为更为详细的技术实现,并深陷其中, 造成了即便在完成功能测试的时候也不由自主的使用了经过“翻译”的语言。

特质之二就是记性不好(也许只是我),每天早上的Standup我都得靠着自己的Pair或者备忘录才能想起昨天作了什么。那么上面的测试失败时,我没信心自己会记得
verify "defaultStage" is triggered and wait for completed
verify pipeline label of "defaultStage" is "1"
到底意味着什么?

脱下Developer的帽子, 换一顶用户的帽子,来跟自己玩儿Q&A
"我要做什么?"
“login” 并 “rerun stage.”

"然后我必须要了解什么? 对我而言,什么是有价值的信息?"
“newly created "defaultStage" should be ran in the same pipeline”
“next stage should be triggered automatically.”

作为技术实现的:
verify "defaultStage" is triggered and wait for completed
verify pipeline label of "defaultStage" is "1"
是系统中的易变部分,随着系统的演化, pipeline label的格式很可能发生变化(譬如可订制),然而业务价值(newly created "defaultStage" should be ran in the same pipeline)却非常稳定,健忘如我也能立即捡起上下文。

带上用户的帽子,就是强迫自己以业务价值为角度进行思考。并将思考形式化,最终变成一种习惯。 而这种习惯将给团队带来更加简练,易读、易于维护的测试。

--
Hu Kai
blog : http://iamhukai.blogspot.com/

2008年10月15日星期三

使用Firebug的麻烦

firebug 的好处不多罗唆了,基本上可以满足开发,调试Web页面所有的需求。修改CSS, 强大的javascript调试功能, 便捷的页面Inspect,等等。

说下Firebug的Bug吧:

* 严重的内存泄露
大概是众所周知的麻烦了, 以至于当你打开gmail,它都会提醒你,firebug会让gmail变慢, bla bla bla。

会变慢多少呢?我和Tin同学很久以前写过一个小程序来测试自己的应用, 我们把每十秒一次的AJAX调用变为每一秒一次,在20分钟的时间内浏览器的内存占用从30M内存跑到900M。我们花了2天的时间来进行各个部分的javascript调优,大概让内存下降了几十M,对于整个内存泄露,简直就是杯水车薪,直到Tin同学无意间停掉firebug,同样的条件下,内存几乎没有增加。

* 关于缓存的假象
即便你正确的设定了Cache-Control, Expire等HTTP头, 你总会发现在被缓存的js, css文件出现在Firebug的Net视图中(被缓存的图片显示正常),并告诉你,下载这个文件花费了若干秒, 当你在无尽的Search中完全找不到浏览器拒绝进行缓存的头绪时。这里的讨论 会告诉你这是Firebug的一个Bug, WebKit似乎也有同样的问题。(今天和Tin同学用WiresharkLive HTTP Headers 验证了此问题,留此存照)




2008年10月9日星期四

使用Mercurial之乐

* 方便的安装。
不论是mac, linux还是windows,不论你是命令行的爱好者还是乌龟的忠实粉丝,你总能找到一款适合你的。

* 2个命令创建一个Mercuria仓库,
> hg init
> hg serve,
通过这两个命令你就可以拥有一个通过HTTP协议访问的mercurial仓库, 你可以方便的通过客户端通过命令访问,或者你可以轻松的使用浏览器来浏览当前的代码。

* 方便的分布式功能
上一次在印度我想在一台新电脑上安装源代码,无奈网络速度太慢,于是乎,我找到一个存有源码的机器,hg serve,这样我得到了一个本地服务器,通过它,我在1分钟内拿到了代码,然后将hgrc(一个mercurial的配置文件)的URL指向在中国的服务器,继续更新后面的几个patch。 将一个1个小时的操作变成2分钟的操作。

如果你急需要某个patch, 但是你的同事还没来得及提交到服务器上去,没关系,你大可以将自己的workingcopy指向同事的电脑, 运行hg pull就可以从他那里及时的拿到最新的代码。

没有branch的痛苦, 没有branch是因为每个人都是一个branch -_-!!!

* 便捷的本地提交
使用Mercurial,你可以在没有网络的情况下通过
> hg ci
进行本地提交,再也无需因为没有网络时候患上“写代码没有SCM恐惧症”,你也可以通过这个命令在日常开发中即达到小步前进,又不用每10分钟非得跑一遍测试。

* 离线操作
不论是Mercurial的提交或者是diff,rollback,strip, merge都可以在没有网络的情况下进行,想像一下在中国开发,服务器在美国的痛苦:那缓慢爬行的小乌龟。

* 速度优势
Mercurial是增量存储,并且它会每隔一段时间进行对整个Repository打一个快照,这样当你去clone repository(相当于svn checkout)的时候,它可以找到最近的一个快照,并在它的基础上应用后续的patch。

* 基于patch的管理
Mercurial将你的提交作为一个patch管理, 你可以很容易拿到别人的patch,通过hg客户端或者linux上的 patch命令将别人最新的修正打在你的工作目录里面。

* 更多的便捷操作
你想将本地的某些提交取消? hg strip
你想将server上的某些changeset取消?hg backout
你想订制hg log的输出方式?定义自己的hg template。

尝试Mercurial