jenkins/hudson与virtual box集成问题的小提示

今天mc大爷在捣鼓他们新到手的R520,准备搭建一个虚拟测试平台,下面言归正传。

linux下安装virtual box最新的 VirtualBox 4.1.14 for Linux

同时,从jenkins插件库安装VirtualBox Plugin 插件(安装后记得重启jenkins)

打开jenkins中的 Manage Jenkins -> Configure System -> Cloud -> Add a new cloud -> VirtualBox

这时候他2b了,竟然直接往里面写virtual box中系统的ip地址和用户名!!! 其实这也不怪他,尼玛的一点说明都没有,wiki上的说的不太明了(其实是我们太2,没想到virtualbox竟然这么强大…)果断的连接失败,哈哈!

其实呢,wiki上的意思是先安装成功后,分别执行命令:

1
2
VBoxManage setproperty websrvauthlibrary null 
vboxwebsrv

vboxwebsrv的意思是启动virtualbox的web服务。
然后再在jenkins中进行设置,不过这时候他又苦逼了,连不上,用localhos:18083可以连接,用ip:18083就不行了,我们竟然又2b的认为是网络的原因,后来我想了想用了下 vboxwebsrv -help 恍然大悟。。。
直接用vboxwebsrv –host IP启动,在jenkins中验证,连接成功。

哦草,好久不练,差点都残了,记下来,共享。 via

一些正则表达式

非负整数:^\d+$

正整数:^[0-9]*[1-9][0-9]*$

非正整数:^((-\d+)|(0+))$

负整数:^-[0-9]*[1-9][0-9]*$

整数:^-?\d+$

非负浮点数:^\d+(\.\d+)?$

正浮点数 : ^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)$

非正浮点数:^((-\d+\.\d+)?)|(0+(\.0+)?))$

负浮点数:^(-((正浮点数正则式)))$

英文字符串:^[A-Za-z]+$

英文大写串:^[A-Z]+$

英文小写串:^[a-z]+$

英文字符数字串:^[A-Za-z0-9]+$

英数字加下划线串:^\w+$

E-mail地址:^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$

URL:^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$
或:^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\’:+!]*([^<>\"\"])*$

邮政编码:^[1-9]\d{5}$

中文:^[\u0391-\uFFE5]+$

电话号码:^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$

手机号码:^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$

双字节字符(包括汉字在内):^\x00-\xff

匹配首尾空格:(^\s*)|(\s*$)(像vbscript那样的trim函数)

匹配HTML标记:<(.*)>.*<\/\1>|<(.*) \/>

匹配空行:\n[\s| ]*\r

提取信息中的网络链接:(h|H)(r|R)(e|E)(f|F)  *=  *(‘|”)?(\w|\\|\/|\.)+(‘|”|  *|>)?

提取信息中的邮件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

提取信息中的图片链接:(s|S)(r|R)(c|C)  *=  *(‘|”)?(\w|\\|\/|\.)+(‘|”|  *|>)?

提取信息中的IP地址:(\d+)\.(\d+)\.(\d+)\.(\d+)

提取信息中的中国手机号码:(86)*0*13\d{9}

提取信息中的中国固定电话号码:(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}

提取信息中的中国电话号码(包括移动和固定电话):(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}

提取信息中的中国邮政编码:[1-9]{1}(\d+){5}

提取信息中的浮点数(即小数):(-?\d*)\.?\d+

提取信息中的任何数字 :(-?\d*)(\.\d+)?

IP:(\d+)\.(\d+)\.(\d+)\.(\d+)

电话区号:/^0\d{2,3}$/

腾讯QQ号:^[1-9]*[1-9][0-9]*$

帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

中文、英文、数字及下划线:^[\u4e00-\u9fa5_a-zA-Z0-9]+$

匹配中文字符的正则表达式: [\u4e00-\u9fa5]

匹配双字节字符(包括汉字在内):[^\x00-\xff]

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

sql语句:^(select|drop|delete|create|update|insert).*$

匹配首尾空格的正则表达式:(^\s*)|(\s*$)

匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

    来源

cygwin 中调用windows 环境下的ruby 各种包命令

作者:王少
原文地址: http://www.testwo.com/space.php?uid=1215&do=blog&id=5082
主要是解决了 在cygwin 直接调用win 环境中 所有的ruby 指令
如:>ruby -irb >ruby list …

window机器中安装了ruby 1.9.X版本,在cygwin中应用时,就会报错 $ ruby -vruby 1.9.2p290 (2011-07-09) [i386-mingw32]
$ gem listD:\worksoft\…\Ruby1.9.2\bin\ruby.exe: No such file or directory –/cygdrive/d/worksoft/…/Ruby1.9.2/bin/gem (LoadError)

解决方法:在cygwin中进入/home/King(username)或者通过window找到此目录,本人window目录:D:\cygwin\home\King 这里一般是administrator找到”.bashrc”,window下用notepad(或其它编辑器)打开,加入下列内容: alias gem=’gem.bat’alias rake=’rake.bat’alias erb=’erb.bat’alias irb=’irb.bat’alias rdoc=’rdoc.bat’alias ri=’ri.bat’alias rspec=’rspec.bat’alias cucumber=’cucumber.bat’alias bundle=’bundle.bat’

保存后,重新启动cygwin,再输入gem list试试。

TDD相关测试框架

TDD(测试驱动开发)相关测试框架
1. XUnit:相应于各语言的测试框架
2. EasyMock:模拟接口或类行为
3. DBUnit:数据库测试
4. Spring-test:提供数据库集成测试
5. 基于请求的web作测试
(1)Spring-mock:可以mock浏览器请求等
(2)JspTest:测试jsp页面
6. 基于控件的web作测试
(1)WicketTester
(2)Apache Shale
7. Apache commons VFS:虚拟文件系统,对文件系统进行模拟
8. HttpUnit:http测试
9. Jemmy和Abbot:测试驱动开发Swing
10. Hsqldb:内存数据库,模拟真实数据库
11. Dbdeploy:数据库结构的增量变动
12. GSBase:equals和hashcode测试
13. BeanInject:可以将测试替身强行赋给某个类的私有变量
14. JFCUnit:JFC类测试
15. ConTest:Java并发单元测试
16. XMLUnit:测试xml结构及内容
17. JUnitPerf:性能测试

ATDD(可接受性测试(功能测试)驱动开发)
1. Fit
2. Fitnesse
3. Exactor
4. TextTest
5. jWebUnit中提供的夹具

相关Website
1. xunitpatterns.com
2. MockObjects.com

一位程序员工作10年总结的13个忠告

展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告。

走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程 序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过的10年的路程,有些心得体会你可以借鉴一下,觉得说得有道理的你就接纳,觉得说得没道理 的,你就抛弃,以下是我发自内心的,给大家的忠告,特别是针对那些小弟弟妹妹们。

01. 自己的户口档案、养老保险、医疗保险、住房公积金一定要保管好。

由 于程序员行业每年跳槽一次,我不隐瞒大家,我至少换过5个以上的单位,这期间跳来跳去,甚至是城市都换过3个。还好户口没丢掉,其他都已经是乱了,好几个 城市里,都有交过三金,甚至是一个程序的2个区里交的都有,那些东西,10年后,会变得很重要。你买房子若有公积金,可以取出来,贷款利率也会比较低一 些,有孩子了,还需要上学,生病了还需要医疗保险。

特别是买房子时,你要商业贷款与公积金贷款的利率差别还是很大,有可能会有10万的差距。你平 时都注意这些,会给你带来的损失会最小,例如每个月缴纳300元的公积金,公司也缴纳300元,你一个月能存下来600元,一年就是7200元,10年就 是72000元。我以前都忽视了这些,到我需要买房子时,公积金里可能只有几千元,10年很快就过去了,结果我没能存下来多少公积金,医疗保险,养老金等 更别提了,都已经稀里糊涂了,这些损失10年累加起来,是很庞大的数字,大家要注意,跳槽换工作时也要保护好自身的利益,现在房价很贵,你可能是跟我一 样,大山里出来打拼的娃子,家里也没有丰厚的积蓄,只有靠自己拼搏,买房子是人生的一件大事,等你到了10年,才想到这个事情,已经晚了,特别是孩子要上 学,上幼儿园等,需要户口啥的都要齐全。

02. 不要轻易换笔记本电脑,不要跟潮流,不要买过多的电子产品,不要过于频繁的更换手机。

这 方面我的经验教训也是惨痛的。我大概前后购买过5-6个笔记本,以前的都是1万多元一台,最近买的是一台是1万多给女朋友的,自己买了一台是7500元左 右,手机大概换过接近10个了,这些钱加起来也足够有10万以上了,你可能一不小心就购买了这些电子产品,但是时间长了,你一回过头来想想,你为什么赚得 也不少,但是为什么还是那么穷,是因为你购买这些电子产品花费了过多的金钱了,平时笔记本啥的贵重物品要保护好,我一个同事不小心丢了2台笔记本电脑,接 近2万的损失啊,你净赚2万,不是那么容易的,这个窟窿不是开玩笑的,我曾经也被人偷了一个崭新的笔记本,损失1.5万左右,更糟糕的是最新的代码也丢被 偷了。

03. 这年代外语、学历、职称、驾驶证还是蛮重要的。

想找高薪,外资企业是正确的选择,在同样的打工里,外资企业的收入普遍是高的,我就想不明白,我们的赚钱能力怎么就比不过人家了,社会不断发展,将来可能去外国就像串门一样了,也说不定的,外语好将来的就业机会也会更多更广一些。
学历并不代表啥,但是学历也是敲门砖,例如有300个应聘者,那至少重点本科以下的,统统不看了,因为实在是来不及看了,你再厉害也被挡在机会的门外了,同样有时候你想改行什么的,职称也很重要,最起码评个中级职称,说不定还有机会能进入大学或者政府部门还是有可能性。

若 有充裕的时间,应该把驾驶证考了,因为你越到后面越忙与工作家庭,没机会学车了也说不定的,平时也别光顾拼命工作,工作10年后你才发现,原来身边的人都 至少硕士学历了,你被社会自动淘汰了,我现在就有这个感觉,虽然我带过很多硕士,他们的就业机会比我还好,经常能进入名牌企业,我也一直进不去。

04. 不要谈过多的女朋友,谈女朋友要看准,下手要稳准狠。

我 谈过2个女朋友,平均每个女朋友身上的开支前后大概会有10万左右,还好我不用谈第3个女朋友了,若投资失误,那也是很残忍的,谈女朋友也会消耗很多时间 精力、还会消耗很多金钱,实话的讲的确是这样的,人家女孩子也值钱啊,凭什么就那么轻易的跟你啊,我跟第一个朋友分手时,我的生活至少是倒退了3-4年, 一切从零开始,一切从头开始,我劝大家谈女朋友是人生最大的一笔买卖,投资失误会有惨痛的后果,不仅仅是金钱上的损失,更会有精神、心灵上的沉重打击,大 家要学会珍惜女朋友,要学会哄好女朋友,让老婆开心每一天,虽然鱼儿上钩了,不用再下鱼饵了,偶尔也别忘记放点米,这个鱼要是脱钩了,那不是开玩笑的。

05. 工作不要更换得太过于频繁,选好了行业方向最好别更换太频繁。

换工作,换行业方向,就像熊掰苞米一样的道理,有时候是丢了芝麻捡西瓜,有时候是丢了西瓜捡芝麻,这个道理我就不多讲了,大家都应该能明白的。

06. 要对身边的人好,要得到老板的信任、同事的认可及支持、珍惜良好的工作环境。

有 个朋友的QQ名字很有意思,“只爱陌生人”,陌生人是很有意思,但是最关键时刻,还是需要靠非陌生人,你每天跟同事一起生活,要维系好身边的人。你的成功 与失败,往往是你身边的30-40个人决定的。你就是世界首富,他身边也是那么不超过100个人的在左右着他的生活,当你工作10年了,没一个老板信任 你,没几个要好的同事朋友,那你惨了,你在这个世界上已经是很孤单了,你的收入,其实大多是来自这些身边的朋友给你介绍的生意,不大会网上掉几个馅饼的。
现在你身边的人有可能在不久的将来,给你提供很多好机会。

07. 钱很重要,但是生活质量比钱还重要,工作是很重要,但是家人比工作还重要。

钱 不是万能的,但是没钱是万万不能的。钱赚了,身体夸了,全送给医院了,钱赚了,身心疲惫了,人活着为了啥?不就为了开开心心生活嘛?工作重要,但是失去了 家人的爱,失去了女朋友,失去了老婆孩子,那这个工作有啥用了?工作很容易就换了,家人是换不了的,老婆不是想换就换的,孩子不是想换就换的,连自己的家 庭都不负责的人,怎么可能对公司负责呢?我一直是这个观念,来面试时觉得工作更重要的,我们一般不录取的,那太假了,或者太不懂事了。

08. 工作累了,也别太贪玩,有时候还是需要多想想如何才能赚钱。

时 间一晃就过去了,工作累了是可以适当放松,但是别太贪玩,10年很容易就过去了,10年后你要买房子,要娶老婆,要买车子,要生娃娃,身体也会变得脆弱一 些,需要良好的生活习惯,也经不起通宵了,通宵一次,你要低迷好几天才能缓过劲儿来,跟20刚出头完全不一样了,用钱的地方多了去了,父母也会变得更老一 些,可能也需要你的照顾,整个家子都指望你赚钱,别到了这个时候,你才意识到赚钱是那么的重要,更何况现在城市的房价,动不动就是100万,加上按揭的利 息,你很可能需要支付150万。还可能需要装修,买车子。可能你身上的压力是200万。别觉得谈钱就俗,你要学会赚钱,要有个需要赚钱的良好意识,当然你 出身富裕家庭,就不用考虑这些因素了。

09. 每天一点点进步,每月一点点积累,要敬业要爱业,我们给别人提供的也是服务。

总有 一天,你也会有累的时候,你也会有老的时候,这时候,你要靠啥呢?就要靠你平时的积累,你10年的积累,可以打倒很多竞争对手,他们再厉害,再怎么样,也 很难抵得过你10年的积累,特别是后面5-10年的积累,成果会很明显,前面的1-5年,算是做软件的入门吧,除非你有高人指点,那可能2-3年就可以修 成正果,软件在将来还是会值钱的,以为生活会越来越智能化,越来越数字化,软件的需求还是很有前途,最起码未来的10-20年里不用太担心失业问题了。

10. 对程序员来讲,开发思想、架构、代码就是财富,别老丢弃你的劳动成果,要学会保护你的劳动成果。

我 大概7-8年前的代码都在手上,经常改进来改进去,维护来维护去,在一定的程度上,让我生活轻松了不少,因为我不用什么都从头来过,我只要痛苦一次,以后 就要反复重复利用,软件的价值在于重复利用,而不是每个东西,都从头开发,那永远也是辛苦的程序员,这个生活质量就别提了,不管自己的代码丑还是拿不出 手,要学会精心维护,每天改进一点点,每个月一个小进步,每年一个大进步,多年的积累是宝贵的,这个早晚也会给你带来丰厚的收益。

11. 当程序员要防止原地踏步,不是工作年限长了,经验就丰富了,能力就强了,年纪越大工作越难找。

我 有一个朋友跟我开玩笑,工作5年的人,可能能力差距会很大,为什么呢?因为第一年他们干的事情都是一样的,都写程序了,2个人可能由于价值观不一样,5年 后差距会很大,甚至是大到无法追赶的程度,为啥?因为还有机会的因素在里面,有的人干了5年,还是在原地踏步,天天只会写那些添加、删除、修改的代码。那 你得注意了,需要不断的提高自己,才是硬道理。例如你会SQLServer,那要试着学习Oracle, 你是做C/S的,那得需要提高到B/S的,你是做单机软件的,那得需要提高到网络软件,你只关注自己的工作的,需要学会管理,关心他人的工作。你是当程序 员的,要试着提高当项目经理、部门经理,公司的总监等等,人有野心有目标才会不断进步,最俗的为了多赚钱,提高工作职位工作岗位,工作单位,也是可以理解 的。

年纪越大工作越难找,例如3-4千的工作是随便找找,玩一样,但是你30过后,最起码要找月薪上1万的工作,这样的工作是机会也少,一般小公 司也给不起,还得找个好公司才可以,好公司又不是天天招聘人,天天缺好的工作岗位,说不好听点儿,小公司的老板才赚多少啊?他来钱也很不容易的,小池塘就 不好容得下大鲨鱼了。

12.当创业的收入比打工还少时,那就别创业,要找比自己能力强的人创业,你不会吃亏。

创业的收入,比打工还少,那就是瞎扯蛋,恶搞。创业的真正意思并不是要你去吃苦没钱赚,那是忽悠无知的人的。当你创业时的收入,比打工还多,那你可以考虑创业,没有工资什么的,股份啥的,都是瞎扯蛋。
不要跟自己能力还弱的人一起创业,那损失最大的,很可能就是你,要创业,也要找比自己强的人一起创业,最起码赚不到钱,还能学到不少。不会有过多的损失。别热血一沸腾就创业了,创业了,也别烧自己的钱,家人的钱,那是很不抗烧的,没几下几十万就烧干了。

其实打工,也是创业的开始,每个月都能拿到钱,还可以学到知识,什么公司的股份都是空话,没几个小公司能成功,开起来了也走不了3年就分家了,都忽悠小孩子玩的,除非真的有科技含量或者是客户资源的,否则股份是一文钱不值的,就算创业每个月也按时拿工资才是硬道理。

13. 未来的生活节奏会更快,生活压力会更大,竞争会更激烈,社会服务体系会更完善。

在 未来,我们享受良好的服务的同时,也会为别人提供更良好的服务,需要在技能上还是服务质量上的要求会更高更严格。平时要注意提高自己,不要被时代淘汰掉, 我从小的朋友,一波又一波被社会无情的淘汰了,很小的时候,我出生在大草原与大山的交界处,我小时候的玩伴,还在大山里,我跟着家人杀出来了,我小学、中 学、大学、工作上的、这10年,我一直很坚强的拼搏下来,很不容易的在杭州立住脚了,说实话,参加工作后的十年,也是不断拼搏,不断提高的十年。

 

来源

QTP将死——开源测试登上舞台

QTP作为测试自动化的主流,已经很长时间了:
以前的主流测试是window GUI应用,和普通WEB应用;没有那些复杂的其他环境,如flex silverlight wpf 手机等。
以前良好协作的自动化用例管理平台,是TD(qc),能够实现用例与自动化关联。
以至于:QC/QTP甚至成了自动化测试招聘的标准……
现在呢?
随着WEB2.0+,移动互联网的兴起,QTP/QC还能胜任吗?
数年之前,EJB也是标准,但是EJB造成了一些招致IT人员反感的问题:
开发调试维护困难,方案太重
与应用服务器紧密绑定(昂贵)
性能低下……
我们回过头来看看,QTP/QC也不是与这个很类似吗?
QTP成也对象仓库败也对象仓库,录制的东西不比手写,手写的是自己的孩子自己认识,可维护性强;
QTP如果你不与QC关联,很难关联用例与需求
QTP实际运行性能低下,特别是插件(先不考虑插件的价格)
QTP做测试,必须有框架……
这里不想讨论LR。如果我们不用QTP/QC,开源世界里能否有东西胜任呢?答案是肯定的。
回头看看EJB:
Hibernate取代了EntityBean
Spring成了粘合剂
这二者联手将java世界的标准,送进了博物馆
那么QTP/QC中,开源世界的对位应该是哪些呢?
我认为:
QTP的取代者,会是webdriver,webdriver就像hibernate的地位;当然,你也可以不用webdriver,就你可以不用hibernate而用myBatis/dbutil等取代一样,你也可以用watir/htmlunit/seleniumRC/webaii/white/sikuli/bromine等任何来代替webdriver的地位;就跟你想在写原生sql一样,你也可以写(win32ole)win32api, linux xdotool来完成自动化。
Hibernate这头熊是如何被唤醒的?我们来回忆一下,当时hibernate的问题是sessionfactory获取datasource,依赖jndi查找,而Spring用了依赖注入解决了这个问题;Sring成了真正意义上的企业级粘合剂,更关键的是spring所带来的一种务实的思想。
那谁来把QTP从QC上解耦,并能提供良好的用例组织和管理呢?答案就是BDD目前的事实标准:Cucumber!!
引用维基百科:
行为驱动开发(缩写BDD)是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。BDD最初是由Dan North在2003年命名[1],它包括验收测试和客户测试驱动等的极限编程的实践,作为对测试驱动开发的回应。在过去数年里,它得到了很大的发展[2]。
2009年,在伦敦发表的“敏捷规格,BDD和极限测试交流”[3]中,Dan North对BDD给出了如下定义:
BDD是第二代的、由外及内的、基于拉(pull)的、多方利益相关者的(stakeholder)、多种可扩展的、高自动化的敏捷方法。它描述了一个交互循环,可以具有带有良好定义的输出(即工作中交付的结果):已测试过的软件。
BDD的重点是通过与利益相关者的讨论取得对预期的软件行为的清醒认识。它通过用自然语言书写非程序员可读的测试用例扩展了测试驱动开发方法。行为驱动开发人员使用混合了领域中统一的语言的母语语言来描述他们的代码的目的。这让开发着得以把精力集中在代码应该怎么写,而不是技术细节上,而且也最大程度的减少了将代码编写者的技术语言与商业客户、用户、利益相关者、项目管理者等的领域语言之间来回翻译的代价。
Dan North创造了首个BDD框架:JBehave[1];之后是Ruby语言的基于故事的RBehave[4],后来被纳入了RSpec项目[5]。他还与大卫赫利姆斯基、Aslak Hellesøy及其他人开发了RSpec,并一起编写了《The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends》。RSpec中第一个基于故事的框架,后来被主要由Aslak Hellesøy开发的Cucumber取代。
这一大段话,头都要晕掉了吧。OK,我们来看一个典型的BDD用例(用户故事):
你可以认为,这就是两个测试用例!那他与普通的测试用例有什么不同呢?
用户故事关联了需求,是包含了需求的用例
故事贯穿整个软件生命周期,直到验收
故事是软件的商业价值,是最“有效文档”
OK了!那如何把故事跟自动化关联起来呢?BDD框架提供了最简单最直接的方式:正则关联
BDT就是如此神奇!他提供了最简单的方式,就向胶水融合一样可以把任意代码与用户故事关联起来且不限于:单元测试,集成测试,UI自动化,接口验证,安全等
BDD框架,普遍自带数据驱动,关键字驱动,参数化。一个典型的ui automation例子(点击图片查看大图):
运行结果:
说几点:
  •   BDD,只是一种思想,一种轻量级测试实践;BDD注重有效文档,注重用户故事的拆分细化
  •   story可以使得黑盒与自动化人员分离;只要story控制的好,可以招廉价开发来实现自动化
  •   就跟你可以用google guice, picocontainer替换spring一样,BDD框架可以自由选择,因为都是提供相同风格的功能,
  •   比如py里可以用lettuce,.net上有cuke4nuke,groovy有easyb, spock,sikuli也支持BDD等
  •   VBS受限于语言表达力,就别想BDD了。
  •   如果你的企业愿意花几十万(不是为了只卖最贵),还不如只花几万来投在人力建设上,通过开源测试来提升团队, 企业里没有什么比人才更可贵的了。
  •   BDD对粘合自动化或者框架的唯一要求,支持代码编写并启动,比如selenium watir等,而依赖特定GUI的不见得适合。
  •   你不见得需要想开发QTP框架样重复造轮子,合理的使用开源社区现有轮子即可。
  •   BDD可以与bromine/robotium一起,测试iphone/android。
  •   BDD工具完全可以与CI整合,方式多种多样。

目前情况下,BDD缺少一个GUI界面的故事管理工具,你可以自己开发一个,或者买商业的,不过更多的人选择把story帖在墙上。
随着cucumber-jvm的火热,到了该是BDD成为测试主流的时候了,毕竟BDD只是一种思想,一种表现形式,不是一种具体的思路,也不强制你购买某个厂商的工具(当然thoughtworks也有BDD工具twist);现在企业都讲究整合,作为广大发展中测试人员,特别是在成长中公司的测试人员,拿起你的斧头,把该砍的都砍掉,做轻量级测试吧!你会找到自己的乐趣的。
常用BDD框架:JBehave rspec cucumber cuke4nuke spock等等
常见支持与BDD粘合的工具:watir selenium celerity white UIA3.0 robotium bromine(iphone) webaii soapui(core)等
常见与BDD一起使用的编程语言:ruby python groovy node.js java c# erlang lua,就是没有VBS
webdriver,自动化(特指测试自动化)领域的hibernate;cucumber,自动化领域的spring。
当冬眠的熊遇上春天……
让广大自动化人员在开源世界中热起来吧!
————————————–
注,当撰写本邮件时(2011年12月10日16:15):
1 本文仅代表我个人立场,代表我对测试技术的见解,与所在公司无关,无任何针对性。
2 我现在公司,没有从事与任何与QTP/QC相关的工作,我工作中也不使用QTP/QC。
3 文中所言一些技术实践,与我前一家公司有紧密关系;但是我没有泄露前一家公司的商业机密,没有违反前一家公司文化与价值。
4 文中很多东西来源于长期浏览开源世界,如果有语句,思想等重复,请见谅;本无无意抄袭。
5 本文一起合成,如果有语句语法问题,请原谅。。
6 本文出自ddter的“软件测试自动化超级QQ群 | 群号:88742462”的邮件讨论,本文只此一篇,其他抄袭篡改等言论,与本人(上海—地沟那个……)无关。

简单的网络爬虫

/* MiniCrawler: A skeletal Web crawler. 

   Usage:
     To start crawling, specify a starting
     URI on the command line. For example,
     to start at McGraw-Hill.com use this
     command line: 

       MiniCrawler http://McGraw-Hill.com  

*/  

using System;
using System.Net;
using System.IO; 

class MiniCrawler {  

  // Find a link in a content string.
  static string FindLink(string htmlstr,
                         ref int startloc) {
    int i;
    int start, end;
    string uri = null;
    string lowcasestr = htmlstr.ToLower(); 

    i = lowcasestr.IndexOf("href=\"http", startloc);
    if(i != -1) {
      start = htmlstr.IndexOf('"', i) + 1;
      end = htmlstr.IndexOf('"', start);
      uri = htmlstr.Substring(start, end-start);
      startloc = end;
    } 

    return uri;
  } 

  static void Main(string[] args) {
    string link = null;
    string str;
    string answer; 

    int curloc; // holds current location in response 

    if(args.Length != 1) {
      Console.WriteLine("Usage: MiniCrawler <uri>");
      return ;
    } 

    string uristr = args[0]; // holds current URI 

    try { 

      do {
        Console.WriteLine("Linking to " + uristr); 

        // Create a WebRequest to the specified URI.
        HttpWebRequest req = (HttpWebRequest)
               WebRequest.Create(uristr); 

        uristr = null; // disallow further use of this URI 

        // Send that request and return the response.
        HttpWebResponse resp = (HttpWebResponse)
               req.GetResponse(); 

        // From the response, obtain an input stream.
        Stream istrm = resp.GetResponseStream(); 

        // Wrap the input stream in a StreamReader.
        StreamReader rdr = new StreamReader(istrm); 

        // Read in the entire page.
        str = rdr.ReadToEnd(); 

        curloc = 0; 

        do {
          // Find the next URI to link to.
          link = FindLink(str, ref curloc); 

          if(link != null) {
            Console.WriteLine("Link found: " + link); 

            Console.Write("Link, More, Quit?");
            answer = Console.ReadLine(); 

            if(string.Compare(answer, "L", true) == 0) {
              uristr = string.Copy(link);
              break;
            } else if(string.Compare(answer, "Q", true) == 0) {
              break;
            } else if(string.Compare(answer, "M", true) == 0) {
              Console.WriteLine("Searching for another link.");
            }
          } else {
            Console.WriteLine("No link found.");
            break;
          } 

        } while(link.Length > 0); 

        // Close the Response.
        resp.Close();
      } while(uristr != null); 

    } catch(WebException exc) {
      Console.WriteLine("Network Error: " + exc.Message +
                        "\nStatus code: " + exc.Status);
    } catch(ProtocolViolationException exc) {
      Console.WriteLine("Protocol Error: " + exc.Message);
    } catch(UriFormatException exc) {
      Console.WriteLine("URI Format Error: " + exc.Message);
    } catch(NotSupportedException exc) {
      Console.WriteLine("Unknown Protocol: " + exc.Message);
    } catch(IOException exc) {
      Console.WriteLine("I/O Error: " + exc.Message);
    } 

    Console.WriteLine("Terminating MiniCrawler.");
  }
}

selenium WebDriver 资源收集

基本上都是从各大站点搜集的资料,为了尊重作者和译者,所以直接以链接形式分享,不定期更新。

 

 

 

 

持续集成(第二版)

作者:Martin Fowler

译者:雷镇

 

 

最后更改于:2006年5月1日

 

目录

 

用持续集成构建特性

持续集成实践

只维护一个源码仓库

自动化 build

让你的build自行测试

每人每天都要向mainline提交代码

每次提交都应在集成计算机上重新构建 mainline

保持快速 build

在模拟生产环境中进行测试

让每个人都能轻易获得最新的可执行文件

每个人都能看到进度

自动化部署

持续集成的益处

引入持续集成

最后的思考

延伸阅读

 

相关文章

持续集成(第一版)

进化式数据库设计

 

 

我还可以生动记起第一次看到大型软件工程的情景。我当时在一家大型英国电子公司的QA部门实习。我的经理带我熟悉公司环境,我们进到一间巨大的,充满了压抑感和格子间的的仓库。我被告知这个项目已经开发了好几年,现在正在集成阶段,并已经集成了好几个月。我的向导还告诉我没人知道集成要多久才能结束。从此我学到了软件开发的一个惯例:集成是一个很耗时并难以预测的过程。但是事实并非总是如此,我的 ThoughWorks 同事所做的项目,以及很多其它遍布世界各地的软件项目,都不会把集成当回事。任何一个开发者本地的代码和项目共享基准代码的差别仅仅只有几小时的工作而已,而且这只要几分钟的时间就可以被集成回去。任何集成错误都可以很快被发现,并被快速修复。这鲜明的差别并非源于昂贵和复杂的工具。其中的精华蕴含于一个简单的实践:使用统一的代码仓库并频繁集成(通常每天一次)。

 

当我向别人介绍持续集成方法时,人们通常会有两种反应:“这(在我们这儿)不管用”和“做了也不可能有什么不同”。但如果他们真的试过了,就会发现持续集成其实比听起来要简单,并且能给开发过程带来巨大的改变。因此第三种常见的反应是:“我们就是这么做的,做开发怎可能不用它呢?”

 

“持续集成”一词来源于极限编程(Extreme Programming),作为它的12个实践之一出现。当我开始在ThoughWorks 开始顾问职业生涯时,我鼓励我所参与的项目使用这种技巧。Matthew Foemmel 将我抽象的指导思想转化为具体的行动。我们看到了项目从少而繁杂的集成进步到我所描述的不当回事。Metthew和我将我们的经验写进了这篇论文的第一版里。这篇论文后来成了我网站里最受欢迎的文章之一。

 

 

尽管持续集成不需要什么特别的工具,我们发现使用一个持续集成服务器软件还是很有效果的。最出名的持续集成服务器软件是 CruiseControl,这是一个开源工具,最早由 ThoughWorks 的几个人开发,现在由社区维护。之后还有许多其他持续集成服务器软件出现,有些是开源的,有些则是商业软件,比如ThoughtWorks Studio 的 Cruise

 

用持续集成构建特性

 

对我来说,解释持续集成最简单的方法就是用一个简单的例子来示范开发一个小 feature。现在假设我要完成一个软件的一部分功能,具体任务是什么并不重要,我们先假设这个 feature 很小,只用几个小时就可以完成。(我们稍后会研究更大的任务的情况。)

 

一开始,我将已集成的源代码复制一份到本地计算机。这可以通过从源码管理系统的 mainline 上 checkout 一份源代码做到。

 

如果你用过任何源代码管理系统,理解上面的文字应该不成问题。但如果你没用过,可能会有读天书的感觉。所以我们先快速解释一个这些概念。源代码管理系统将项目的所有源代码都保存在一个“仓库(repository)”中。系统的当前状态通常被称为“mainline”。开发者随时都可以把mainline复制一份到他们自己的计算机,这个过程被称为“check out”。开发者计算机上的拷贝被称为“工作拷贝(working copy)”。(绝大部分情况下,你最终都会把工作拷贝的内容提交到mainline上去,所以两者实际上应该差不多。)

 

现在我拿到了工作拷贝,接下来需要做一些事情来完成任务。这包括修改产品代码和添加修改自动化测试。在持续集成中,软件应该包含完善的可自动运行的测试,我称之为自测试代码。这一般需要用到某一个流行的 XUnit 测试框架。

 

一旦完成了修改,我就会在自己的计算机上启动一个自动化 build。这会将我的工作拷贝中的源代码编译并链接成为一个可执行文件,并在之上运行自动化测试。只有当所有的 build 和测试都完成并没有任何错误时,这个 build 过程才可以认为是成功的。

 

当我 build 成功后,我就可以考虑将改动提交到源码仓库。但麻烦的情况在于别人可能已经在我之前修改过 mainline。这时我需要首先把别人的修改更新到我的工作拷贝中,再重新做 build。如果别人的代码和我的有冲突,就会在编译或测试的过程中引起错误。我有责任改正这些问题,并重复这一过程,直到我的工作拷贝能通过 build 并和 mainline 的代码同步。

 

一旦我本地的代码能通过 build,并和 mainline 同步,我就可以把我的修改提交到源码仓库。

 

然而,提交完代码不表示就完事大吉了。我们还要做一遍集成 build,这次在集成计算机上并要基于 mainline 的代码。只有这次 build 成功了,我的修改才算告一段落。因为总有可能我忘了什么东西在自己的机器上而没有更新到源码仓库。只有我提交的改动被成功的集成了,我的工作才能结束。这可以由我手工运行,也可以由 Cruise 自动运行。

 

如果两个开发者的修改存在冲突,这通常会被第二个人提交代码前本地做 build 时发现。即使这时侥幸过关,接下来的集成 build 也会失败掉。不管怎样,错误都会被很快检测出来。此时首要的任务就是改正错误并让 build 恢复正常。在持续集成环境里,你必须尽可能快地修复每一个集成 build。好的团队应该每天都有多个成功的 build。错误的 build 可以出现,但必须尽快得到修复。

 

这样做的结果是你总能得到一个稳定的软件,它可能有一些 bug,但可以正常工作。每个人都基于相同的稳定代码进行开发,而且不会离得太远,否则就会不得不花很长时间集成回去。Bug被发现得越快,花在改正上的时间就越短。

 

持续集成实践

 

从上面的故事我们大概了解了持续集成是如何在我们的日常工作中发挥作用的。但让一切正常运行起来还需要掌握更多的知识。我接下来会集中讲解一下高效持续集成的关键实践。

 

只维护一个源码仓库

 

在软件项目里需要很多文件协调一致才能 build 出产品。跟踪所有这些文件是一项困难的工作,尤其是当有很多人一起工作时。所以,一点也不奇怪,软件开发者们这些年一直在研发这方面的工具。这些工具称为源代码管理工具,或配置管理,或版本管理系统,或源码仓库,或各种其它名字。大部分开发项目中它们是不可分割的一部分。但可惜的是,并非所有项目都是如此。虽然很罕见,但我确实参加过一些项目,它们直接把代码存到本地驱动器和共享目录中,乱得一塌糊涂。

 

所以,作为一个最基本的要求,你必须有一个起码的源代码管理系统。成本不会是问题,因为有很多优秀的开源工具可用。当前较好的开源工具是 Subversion。(更老的同样开源的 CVS 仍被广泛使用,即使是 CVS 也比什么都不用强得多,但 Subversion 更先进也更强大。)有趣的是,我从与开发者们的交谈中了解到,很多商业源代码管理工具其实不比 Subversion 更好。只有一个商业软件是大家一致同意值得花钱的,这就是 Perforce

 

一旦你有了源代码管理系统,你要确保所有人都知道到哪里去取代码。不应出现这样的问题:“我应该到哪里去找xxx文件?” 所有东西都应该存在源码仓库里。

 

即便对于用了源码仓库的团队,我还是观察到一个很普遍的错误,就是他们没有把所有东西都放在源码仓库里。一般人们都会把代码放进去,但还有许多其它文件,包括测试脚本,配置文件,数据库Schema,安装脚本,还有第三方的库,所有这些build时需要的文件都应该放在源码仓库里。我知道一些项目甚至把编译器也放到源码仓库里(用来对付早年间那些莫名其妙的C++编译器很有效)。一个基本原则是:你必须能够在一台干净的计算机上重做所有过程,包括checkout和完全build。只有极少量的软件需要被预装在这台干净机器上,通常是那些又大又稳定,安装起来很复杂的软件,比如操作系统,Java开发环境,或数据库系统。

 

你必须把build需要的所有文件都放进源代码管理系统,此外还要把人们工作需要的其他东西也放进去。IDE配置文件就很适合放进去,因为大家共享同样的IDE配置可以让工作更简单。

 

版本控制系统的主要功能之一就是创建 branch 以管理开发流。这是个很有用的功能,甚至可以说是一个基础特性,但它却经常被滥用。你最好还是尽量少用 branch。一般有一个mainline就够了,这是一条能反映项目当前开发状况的 branch。大部分情况下,大家都应该从mainline出发开始自己的工作。(合理的创建 branch 的理由主要包括给已发布的产品做维护和临时性的实验。)

 

一般来说,你要把build依赖的所有文件放进代码管理系统中,但不要放build的结果。有些人习惯把最终产品也都放进代码管理系统中,我认为这是一种坏味道——这意味着可能有一些深层次的问题,很可能是无法可靠地重新build一个产品。

 

自动化build

 

通常来说,由源代码转变成一个可运行的系统是一个复杂的过程,牵扯到编译,移动文件,将 schema 装载到数据库,诸如此类。但是,同软件开发中的其它类似任务一样,这也可以被自动化,也必须被自动化。要人工来键入各种奇怪的命令和点击各种对话框纯粹是浪费时间,也容易滋生错误。

 

在大部分开发平台上都能找到自动化 build 环境的影子。比如 make,这在 Unix 社区已经用了几十年了,Java 社区也开发出了 Ant,.NET 社区以前用 Nant,现在用 MSBuild。不管你在什么平台上,都要确保只用一条命令就可以运行这些脚本,从而 build 并运行系统。

 

一个常见的错误是没有把所有事都放进自动化 build。比如:Build 也应该包括从源码仓库中取出数据库 schema 并在执行环境中设置的过程。我要重申一下前面说过的原则:任何人都应该能从一个干净的计算机上 check out 源代码,然后敲入一条命令,就可以得到能在这台机器上运行的系统。

 

Build 脚本有很多不同的选择,依它们所属的平台和社区而定,但也没有什么定势。尽管大部分的 Java 项目都用 Ant,还是有一些项目用 Ruby(Ruby Rake 是一个不错的 build 脚本工具)。我们也曾经用 Ant 自动化早期的 Microsoft COM 项目,事实证明很有价值。

 

一个大型 build 通常会很耗时,如果只做了很小的修改,你不会想花时间去重复所有的步骤。所以一个好的 build 工具应该会分析哪些步骤可以跳过。一个通用的办法是比较源文件和目标文件的修改时间,并只编译那些较新的源文件。处理依赖关系要麻烦一些:如果一个目标文件修改了,所有依赖它的部分都要重新生成。编译器可能会帮你处理这些事情,也可能不会。

 

根据你的需要,你可能会想 build 出各种不同的东西。你可以同时 build 系统代码和测试代码,也可以只 build 系统代码。一些组件可以被单独 build。Build 脚本应该允许你在不同的情况中 build 不同的 target。

 

我们许多人都用 IDE,许多 IDE 都内置包含某种 build 管理功能。然而,相应的配置文件往往是这些 IDE 的专有格式,而且往往不够健壮,它们离了 IDE 就无法工作。如果只是 IDE 用户自己一个人开发的话,这还能够接受。但在团队里,一个工作于服务器上的主 build 环境和从其它脚本里运行的能力更重要。我们认为,在 Java 项目里,开发者可以用自己的 IDE 做 build,但主 build 必须用 Ant 来做,以保证它可以在开发服务器上运行。

 

让你的build自行测试

 

传统意义上的 build 指编译,链接,和一些其它能让程序运行起来的步骤。程序可以运行并不意味着它也工作正常。现代静态语言可以在编译时检测出许多 bug,但还是有更多的漏网之鱼。

 

一种又快又省的查 bug 的方法是在 build 过程中包含自动测试。当然,测试并非完美解决方案,但它确实能抓住很多 bug——多到可以让软件真正可用。极限编程(XP)和测试驱动开发(TDD)的出现很好地普及了自测试代码的概念,现在已经有很多人意识到了这种技巧的价值。

 

经常读我的著作的读者都知道我是 TDD 和 XP 的坚定追随者。但是我想要强调你不需要这两者中任何一个就能享受自测试代码的好处。两者都要求你先写测试,再写代码以通过测试,在这种工作模式里测试更多着重于探索设计而不是发现 bug。这绝对是一个好方法,但对于持续集成而言它并不必要,因为这里对自测试代码的要求没有那么高。(尽管我肯定会选择用 TDD 的方式。)

 

自测试代码需要包含一套自动化测试用例,这些测试用例可以检查大部分代码并找出 bug。测试要能够从一条简单的命令启动。测试结果必须能指出哪些测试失败了。对于包含测试的 build,测试失败必须导致 build 也失败。

 

在过去的几年里,TDD 的崛起普及了开源的 XUnit 系列工具,这些工具用作以上用途非常理想。对于我们在 ThoughWorks 工作的人来说,XUnit 工具已经证明了它们的价值。我总是建议人们使用它们。这些最早由 Kent Beck 发明的工具使得设置一个完全自测试环境的工作变得非常简单。

 

毋庸置疑,对于自动测试的工作而言,XUnit 工具只是一个起点。你还必须自己寻找其他更适合端对端测试的工具。现在有很多此类工具,包括FITSeleniumSahiWatirFITnesse,和许多其它我无法列在这里的工具。

 

当然你不能指望测试发现所有问题。就像人们经常说的:测试通过不能证明没有 bug。然而,完美并非是你要通过自测试 build 达到的唯一目标。经常运行不完美的测试要远远好过梦想着完美的测试,但实际什么也不做。

 

每人每天都要向 mainline 提交代码

 

集成的主要工作其实是沟通。集成可以让开发者告诉其他人他们都改了什么东西。频繁的沟通可以让人们更快地了解变化。

 

让开发者提交到 mainline 的一个先决条件是他们必须能够正确地 build 他们的代码。这当然也包括通过 build 包含的测试。在每个提交迭代里,开发者首先更新他们的工作拷贝以与 mainline 一致,解决任何可能的冲突,然后在自己的机器上做 build。在 build 通过后,他们就可以随便向 mainline 提交了。

 

通过频繁重复上述过程,开发者可以发现两个人之间的代码冲突。解决问题的关键是尽早发现问题。如果开发者每过几个小时就会提交一次,那冲突也会在出现的几个小时之内被发现,从这一点来说,因为还没有做太多事,解决起来也容易。如果让冲突待上几个星期,它就会变得非常难解决。

 

因为你在更新工作拷贝时也会做 build,这意味着你除了解决源代码冲突外也会检查编译冲突。因为 build 是自测试的,你也可以查出代码运行时的冲突。后者如果在一段较长的时间还没被查出的话会变得尤其麻烦。因为两次提交之间只有几个小时的修改,产生这些问题只可能在很有限的几个地方。此外,因为没改太多东西,你还可以用 diff-debugging 的技巧来找 bug。

 

总的来说,我的原则是每个开发者每天都必须提交代码。实践中,如果开发者提交的更为频繁效果也会更好。你提交的越多,你需要查找冲突错误的地方就越少,改起来也越快。

 

频繁提交客观上会鼓励开发者将工作分解成以小时计的小块。这可以帮助跟踪进度和让大家感受到进展。经常会有人一开始根本无法找到可以在几小时内完成的像样的工作,但我们发现辅导和练习可以帮助他们学习其中的技巧。

 

每次提交都应在集成计算机上重新构建 mainline

 

使用每日提交的策略后,团队就能得到很多经过测试的 build。这应该意味着 mainline 应该总是处于一种健康的状态。但在实践中,事情并非总是如此。一个原因跟纪律有关,人们没有严格遵守在提交之前在本地更新并做 build 的要求。另一个原因是开发者的计算机之间环境配置的不同。

 

结论是你必须保证日常的 build 发生在专用的集成计算机上,只有集成 build 成功了,提交的过程才算结束。本着“谁提交,谁负责”的原则,开发者必须监视 mainline 上的 build 以便失败时及时修复。一个推论是如果你在下班前提交了代码,那你在 mainline build 成功之前就不能回家。

 

我知道主要有两种方法可以使用:手动 build,或持续集成服务器软件。

 

手动 build 描述起来比较简单。基本上它跟提交代码之前在本地所做的那次 build 差不多。开发者登录到集成计算机,check out 出 mainline 上最新的源码(已包含最新的提交),并启动一个集成 build。他要留意 build 的进程,只有 build 成功了他的提交才算成功。(请查看 Jim Shore 的描述。)

 

持续集成服务器软件就像一个监视着源码仓库的监视器。每次源码仓库中有新的提交,服务器就会自动check out 出源代码并启动一次 build,并且把 build 的结果通知提交者。这种情况下,提交者的工作直到收到通知(通常是 email)才算结束。

 

在 ThoughtWorks,我们都是持续集成服务器软件的坚定支持者,实际上我们引领了 CruiseControl 和 CruiseControl.NET 最早期的开发,两者都是被广泛使用的开源软件。此后,我们还做了商业版的 Cruise 持续集成服务器。我们几乎在每一个项目里都会用持续集成服务器,并且对结果非常满意。

 

不是每个人都会用持续集成服务器。Jim Shore 就清楚地表达了为什么他更偏好手动的办法。我同意他的看法中的持续集成并不仅仅是安装几个软件而已,所有的实践都必须为了能让持续集成更有效率。但同样的,许多持续集成执行得很好的团队也会发现持续集成服务器是个很有用的工具。

 

许多组织根据安排好的日程表做例行 build,如每天晚上。这其实跟持续集成是两码事,而且做得远远不够。持续集成的最终目标就是要尽可能快地发现问题。Nightly build 意味着 bug 被发现之前可能会待上整整一天。一旦 bug 能在系统里呆这么久,找到并修复它们也会花较长的时间。

 

做好持续集成的一个关键因素是一旦 mainline 上的 build 失败了,它必须被马上修复。而在持续集成环境中工作最大的好处是,你总能在一个稳定的基础上做开发。mainline 上 build 失败并不总是坏事,但如果它经常出错,就意味着人们没有认真地在提交代码前先在本地更新代码和做 build。当 mainline 上 build 真的失败时,第一时间修复就成了头等大事。为了防止在 mainline 上的问题,你也可以考虑用 pending head 的方法。

 

当团队引入持续集成时,这通常是最难搞定的事情之一。在初期,团队会非常难以接受频繁在 mainline 上做 build 的习惯,特别当他们工作在一个已存在的代码基础上时更是如此。但最后耐心和坚定不移的实践常常会起作用,所以不要气馁。

 

保持快速 build

 

持续集成的重点就是快速反馈。没有什么比缓慢的 build 更能危害持续集成活动。这里我必须承认一个奇思怪想的老家伙关于 build 快慢标准的的玩笑(译者注:原文如此,不知作者所指)。我的大部分同事认为超过1小时的 build 是不能忍受的。团队们都梦想着把 build 搞得飞快,但有时我们也确实会发现很难让它达到理想的速度。

 

对大多数项目来说,XP 的10分钟 build 的指导方针非常合理。我们现在做的大多数项目都能达到这个要求。这值得花些力气去做,因为你在这里省下的每一分钟都能体现在每个开发者每次提交的时候。持续集成要求频繁提交,所以这积累下来能节省很多时间。如果你一开始就要花1小时的时间做 build,想加快这个过程会相当有挑战。即使在一个从头开始的新项目里,想让 build 始终保持快速也是很有挑战的。至少在企业应用里,我们发现常见的瓶颈出现在测试时,尤其当测试涉及到外部服务如数据库。

 

也许最关键的一步是开始使用分阶段build(staged build)。分阶段 build(也被称作 build 生产线)的基本想法是多个 build 按一定顺序执行。向 mainline 提交代码会引发第一个 build,我称之为提交 build(commit build)。提交 build 是当有人向 mainline 提交时引发的 build。提交 build 要足够快,因此它会跳过一些步骤,检测 bug 的能力也较弱。提交 build 是为了平衡质量检测和速度,因此一个好的提交 build 至少也要足够稳定以供他人基于此工作。

 

一旦提交 build 成功,其他人就可以放心地基于这些代码工作了。但别忘了你还有更多更慢的测试要做,可以另找一台计算机来运行运行这些测试。

 

一个简单的例子是两阶段 build。第一阶段会编译和运行一些本地测试,与数据库相关的单元测试会被完全隔离掉(stub out)。这些测试可以运行得非常快,符合我们的10分钟指导方针。但是所有跟大规模交互,尤其是真正的数据库交互的 bug 都无法被发现。第二阶段的 build 运行一组不同的测试,这些测试会调用真正的数据库并涉及更多的端到端的行为。这些测试会跑上好几小时。

 

这种情况下,人们用第一阶段作为提交 build,并把这作为主要的持续集成工作。第二阶段 build 是次级build,只有在需要的时候才运行,从最后一次成功的提交 build 中取出可执行文件作进一步测试。如果次级 build 失败了,大家不会立刻停下手中所有工作去修复,但团队也要在保证提交 build 正常运行的同时尽快修正 bug。实际上次级 build 并非一定要正常运行,只要 bug 都能够被检查出来并且能尽快得到解决就好。在两阶段 build 的例子里,次级 build 经常只是纯粹的测试,因为通常只是测试拖慢了速度。

 

如果次级 build 检查到了 bug,这是一个信号,意味着提交 build 需要添加一个新测试了。你应该尽可能把次级 build 失败过的测试用例都添加到提交 build 中,使得提交 build 有能力验证这些 bug。每当有 bug 绕过提交测试,提交测试总能通过这种方法被加强。有时候确实无法找到测试速度和 bug 验证兼顾的方法,你不得不决定把这个测试放回到次级 build 里。但大部分情况下都应该可以找到合适加入提交 build 的测试。

 

上面这个例子是关于两阶段 build,但基本原则可以被推广到任意数量的后阶段 build。提交 build 之后的其它 build 都可以同时进行,所以如果你的次级测试要两小时才能完成,你可以通过用两台机器各运行一半测试来快一点拿到结果。通过这个并行次级 build 技巧,你可以向日常 build 流程中引入包括性能测试在内的各种自动化测试。(当我过去几年内参加 Thoughtworks 的各种项目时,我碰到了很多有趣的技巧,我希望能够说服一些开发者把这些经验写出来。)

 

在模拟生产环境中进行测试

 

测试的关键在于在受控条件下找出系统内可能在实际生产中出现的任何问题。这里一个明显的因素是生产系统的运行环境。如果你不在生产环境做测试,所有环境差异都是风险,可能最终造成测试环境中运行正常的软件在生产环境中无法正常运行。

 

自然你会想到建立一个与生产环境尽可能完全相同的测试环境。用相同的数据库软件,还要同一个版本;用相同版本的操作系统;把所有生产环境用到的库文件都放进测试环境中,即使你的系统没有真正用到它们;使用相同的IP地址和端口;以及相同的硬件;

 

好吧,现实中还是有很多限制的。如果你在写一个桌面应用软件,想要模拟所有型号的装有不同第三方软件的台式机来测试显然是不现实的。类似的,有些生产环境可能因为过于昂贵而无法复制(尽管我常碰到出于经济考虑拒绝复制不算太贵的环境,结果得不偿失的例子)。即使有这些限制,你的目标仍然是尽可能地复制生产环境,并且要理解并接受因测试环境和生产环境不同带来的风险。

 

如果你的安装步骤足够简单,无需太多交互,你也许能在一个模拟生产环境里运行提交 build。但事实上系统经常反应缓慢或不够稳定,这可以用 test double 来解决。结果常常是提交测试为了速度原因在一个假环境内运行,而次级测试运行在模拟真实的生产环境中。

 

我注意到越来越多人用虚拟化来搭建测试环境。虚拟机的状态可以被保存,因此安装并测试最新版本的build相对简单。此外,这可以让你在一台机器上运行多个测试,或在一台机器上模拟网络里的多台主机。随着虚拟化性能的提升,这种选择看起来越来越可行。

 

让每个人都能轻易获得最新的可执行文件

 

软件开发中最困难的部分是确定你的软件行为符合预期。我们发现事先清楚并正确描述需求非常困难。对人们而言,在一个有缺陷的东西上指出需要修改的地方要容易得多。敏捷开发过程认可这种行为,并从中受益。

 

为了以这种方式工作,项目中的每个人都应该能拿到最新的可执行文件并运行。目的可以为了 demo,也可以为了探索性测试,或者只是为了看看这周有什么进展。

 

这做起来其实相当简单:只要找到一个大家都知道的地方来放置可执行文件即可。可以同时保存多份可执行文件以备使用。每次放进去的可执行文件应该要通过提交测试,提交测试越健壮,可执行文件就会越稳定。

 

如果你采用的过程是一个足够好的迭代过程,把每次迭代中最后一个 build 放进去通常是明智的决定。Demo 是一个特例,被 demo 的软件特性都应该是演示者熟悉的特性。为了 demo 的效果值得牺牲掉最新的 build,转而找一个早一点但演示者更熟悉的版本。

 

每个人都能看到进度

 

持续集成中最重要的是沟通。你需要保证每个人都能轻易看到系统的状态和最新的修改。

 

沟通的最重要的途径之一是 mainline build。如果你用 Cruise,一个内建的网站会告诉你是否正有 build 在进行,和最近一次 mainline build 的状态。许多团队喜欢把一个持续工作的状态显示设备连接到 build 系统来让这个过程更加引人注目,最受欢迎的显示设备是灯光,绿灯闪亮表示 build 成功,红灯表示失败。一种常见的选择是红色和绿色的熔岩灯,这不仅仅指示 build 的状态,还能指示它停留在这个状态的时间长短,红灯里出现气泡表示 build 出问题已经太长时间了。每一个团队都会选择他们自己的 build传感器。如果你的选择带点幽默性和娱乐性效果会更好(最近我看到有人在实验跳舞兔)。

 

即使你在使用手动持续集成,可见程度依然很重要。Build 计算机的显示器可以用来显示 mainline build 的状态。你很可能需要一个 build 令牌放在正在做 build 那人的桌子上(橡皮鸡这种看上去傻傻的东西最好,原因同上)。有时人们会想在 build 成功时弄出一点噪音来,比如摇铃的声音。

 

持续集成服务器软件的网页可以承载更多信息。Cruise 不仅显示谁在做 build,还能指出他们都改了什么。Cruise 还提供了一个历史修改记录,以便团队成员能够对最近项目里的情况有所了解。我知道 team leader喜欢用这个功能了解大家手头的工作和追踪系统的更改。

 

使用网站的另一大优点是便于那些远程工作的人了解项目的状态。一般来说,我倾向于让项目中发挥作用的成员都坐在一起工作,但通常也会有一些外围人员想要了解项目的动态。如果组织想要把多个项目的 build情况聚合起来以提供自动更新的简单状态时,这也会很有用。

 

好的信息展示方式不仅仅依赖于电脑显示器。我最喜欢的方式出现于一个中途转入持续集成的项目。很长时间它都无法拿出一个稳定的 build。我们在墙上贴了一整年的日历,每一天都是一个小方块。每一天如果 QA 团队收到了一个能通过提交测试的稳定 build,他们都会贴一张绿色的贴纸,否则就是红色的贴纸。日积月累,从日历上能看出 build 过程在稳定地进步。直到绿色的小方块已经占据了大部分的空间时,日历被撤掉了,因为它的使命已经完成了。

 

自动化部署

 

自动化集成需要多个环境,一个运行提交测试,一个或多个运行次级测试。每天在这些环境之间频繁拷贝可执行文件可不轻松,自动化是一个更好的方案。为实现自动化,你必须有几个帮你将应用轻松部署到各个环境中的脚本。有了脚本之后,自然而然的结果是你也要用类似的方式部署到生产环境中。你可能不需要每天都部署到生产环境(尽管我见过这么做的项目),但自动化能够加快速度并减少错误。它的代价也很低,因为它基本上和你部署到测试环境是一回事。

 

如果你部署到生产环境,你需要多考虑一件事情:自动化回滚。坏事情随时可能发生,如果情况不妙,最好的办法是尽快回到上一个已知的正常状态。能够自动回滚也会减轻部署的压力,从而鼓励人们更频繁地部署,使得新功能更快发布给用户。(Ruby on Rails 社区开发了一个名为 Capistrano 的工具,是这类工具很好的代表。)

 

我还在服务器集群环境中见过滚动部署的方法,新软件每次被部署到一个节点上,在几小时时间内逐步替换掉原有的软件。

 

 

在 web 应用开发中,我碰到的一个有趣的想法是把一个试验性的 build 部署到用户的一个子集。团队可以观察这个试验 build 被使用的情况,以决定是否将它部署到全体用户。你可以在做出最终决定之前试验新的功能和新的 UI。自动化部署加上良好的持续集成的纪律是这项工作的基础。

 

持续集成的益处

 

我认为持续集成最显著也最广泛的益处是降低风险。说到这里,我的脑海中还是会浮现出第一段描述的早期软件项目。他们已经到了一个漫长项目的末期(至少他们期望如此),但还是不知道距离真正的结束有多远。

 

延迟集成的问题在于时间难以估计,你甚至无法得知你的进展。结果是你在项目最紧张的阶段之一把自己置入了一个盲区,此时即使没有拖延(这很罕见)也轻松不了多少。

 

持续集成巧妙的解决了这个问题。长时间的集成不再存在,盲区被彻底消除了。在任何时间你都知道你自己的进展,什么能运转,什么不能运转,你系统里有什么明显的 bug,这些都一目了然。

 

Bug 让人恶心,它摧毁人的自信,搞乱时间表,还破坏团队形象。已部署软件里的 bug 招致用户的怒气。未完成软件里的 bug 让你接下来的开发工作受阻。

 

持续集成不能防止 bug 的产生,但它能明显让寻找和修改 bug 的工作变简单。从这个方面看,它更像自测试代码。如果你引入 bug 后能很快发现,改正也会简单得多。因为你只改了系统中很小的一部分,你无需看很多代码就能找到问题所在。因为这一小部分你刚刚改过,你的记忆还很新鲜,也会让找 bug 的工作简单不少。你还可以用差异调试——比较当前版本和之前没有 bug 的版本。

 

Bug 也会积累。你的 bug 越多,解决掉任何一个都会越困难。这部分原因是 bug 之间的互相作用,你看到的失败实际上是多个问题叠加的结果,这使得检查其中任何一个问题都更加困难。还有部分原因是心理层面的因素,当人们面对大量 bug 时,他们寻找和解决 bug 的动力就会减弱。《Pragmatic Programmer》一书中称之为“破窗综合症“。

 

使用持续集成的项目的通常结果是 bug 数目明显更少,不管在产品里还是开发过程中都是如此。然而,我必须强调,你受益的程度跟你测试的完善程度直接相关。其实建立测试系统并非想象中那么困难,但带来的区别却显而易见。一般来说,团队需要花一定时间才能把 bug 数量减少到理想的地步。做到这一点意味着不断添加和改进测试代码。

 

如果你用了持续集成,你就解决了频繁部署的最大障碍之一。频繁部署很有价值,因为它可以让你的用户尽快用到新功能,从而快速提供反馈,这样他们在开发过程中可以有更多的互动。这可以帮助打破我心目中成功的软件开发最大的障碍——客户与开发团队之间的障碍。

 

引入持续集成

 

看到这里,你一定想要尝试一下持续集成了。但是从哪里开始呢?我在上面描述了一整套的实践,这些可以让你体验到所有的好处。但你也不必一开始就照单全收,你有自己的选择余地,基本上取决于你的环境和团队的特性。我们也从过去的实践中吸取了一些经验和教训,做好下面这些事会对于你的持续集成运作有重要的意义。

 

最早的几步之一是实现 build 自动化。把所有需要的东西都放进版本控制系统里,这样你就可以用一条命令 build 整个系统。这对许多项目而言不是什么小任务,这对于其他东西正常工作非常重要。刚开始你可能只是偶尔需要的时候做一个 build,或者只是做一个自动的 nightly build。当你还没有开始持续集成时,自动 nightly build 也是一个不错的开始。

 

其次是引入一些自动化测试到你的 build 中。试着指出主要出错的地方,并要让自动化测试暴露这些错误。建立又快又好的测试集合会比较困难,特别在已存在的项目中,建立测试需要时间。你必须找个地方开始动手,就像俗话说的,罗马不是一天建成的。

 

还要试着加快提交 build 的速度。虽然需要几个小时 build 的持续集成也比什么都没有好,但能做到传说中的10分钟会更好。这通常要对你的代码动一些大手术,以剥离对运行缓慢那部分的依赖。

 

如果你刚刚开始一个新项目,从一开始就用持续集成。对build时间保持关注,当慢于10分钟时就立即采取行动。通过快速行动,你可以在代码变得太大之前做一些必要的架构调整。

 

比所有事情都重要的是寻找帮助。找一个以前做过持续集成的人来帮你。像所有新技巧一样,当你不知道最终结果怎样的时候会非常难以实施。请一个导师(mentor)可能会花些钱,但如果你不做,你会付出时间和生产效率损失的代价。(免责声明/广告:是的,我们 ThoughtWorks 在这个领域提供咨询服务。不管怎样,我们曾经犯过你可能会犯的大多数错误。)

 

最后的思考

 

在我和 Matt 写完最初那篇论文后的几年,持续集成已经成为了软件开发的一个主流方法。ThoughtWorks 的项目很少有不用到它的。我们也能看到世界各地的人们在用持续集成。与极限编程中一些充满争议的实践不同,我很少听到关于持续集成的负面消息。

 

如果你还没用持续集成,我强烈建议你试一下。如果你已经在做了,可能这篇文章中的某些方法可以帮你得到更好的效果。过去几年中,我们已经了解了很多关于持续集成的知识,我希望还有更多的知识可以让我们学习和提高。

 

延伸阅读

 

本文篇幅所限,只能覆盖部分内容。想了解持续集成的更多细节,我建议看一下 Paul Duvall 的(这本书得到了Jolt大奖)。目前为止还没有多少关于分阶段build的文章,但有一篇 Dave Farley 发表在《ThoughtWorks 文选》中的文章还不错(你也可以在这里找到)。

文章来自译言,感谢翻译者的贡献,原始链接:http://article.yeeyan.org/view/2251/94882

不要让未来的你,讨厌现在的自己

“不要让未来的你,讨厌现在的自己”这句话与“今天的不断拼搏,是为了实现小时候吹过的牛逼”有异曲同工之妙。今天要分享的是关于两个人的人生,我对阿信并不熟悉,但却非常喜欢康永的文字,世上竟有人能把知性与感性结合得如此完美。至于其他,不在我的兴趣之列。

正文:

人生,如果以100岁为单位,要如何掌握人生的节奏?

对蔡康永与阿信来说,节奏不仅是音乐,还代表人生。他们喜爱创作时的慢步调、享受表演时的快节奏,但不管外界如何看舞台上的精彩,他们只用自己认可的“tempo(节奏)”冲过一个又一个的人生浪花。

蔡 康永是全台访问过最多人的主持人,他在传统之下成长,却以颠覆传统与挑战束缚的形象深植人心。爱问犀利的问题,不是因为职业病,而是对“人性”感兴趣;他 爱唱反调,其实只是因不甘心被简单的快乐喂饱,他想用更颠覆的脑袋,将他的思想、价值观用更犀利的语言“翻译”给这个世界听。

五月天乐团主唱阿信,同样也是一个不甘寂寞的灵魂,如同他的〈放肆〉歌词:“牛顿要我们都活在地上,偏偏我就想要飞翔,要推翻柏林围墙,要站上巨人的肩膀。”叛逆的背后,其实是有所坚持,颠覆的背后更是想要突破。

两人出道只差1年,蔡康永1996年进入电视圈,五月天1997年进入流行乐坛,近年都走红中国。随著声名愈来愈大,他们对生活很知足,却对自己不甘心。也因为不甘心,想被世界看见,对人生更不“呼拢”。他们不断阅读,寻找各种人生答案。

他们要“过瘾”的人生,让自己有一部分被世界看见;他们要“自信”的人生,培养的方法,就是最好一辈子活在“不放心”里。

如果再以100岁为单位,问他们如何安排他们的人生节奏?答案居然很简单,到底是什麼呢?以下是两人交锋的精采纪要:

学习:诸事蒙昧,别任性

若人类被设定为以100岁的年龄死掉,看起来这是时间的残酷,但残酷同时也带来自由。就好像吃一顿饭,如果你知道会有8道菜,每道菜都会品尝出滋味,反之,如果没完没了,到最后只会希望赶快结束……

信:〈后青春期的诗〉是给我自己的一首歌,我的青春期已经被我延长过,我今年34岁了,但再延也没多久。以前想到一件事时,会想以后有空再来做,但有些事的确有完成的期限,我现在会想,如果有想做却只能趁现在做的事,那就开始吧!

蔡: 前阵子我看一部吸血鬼影集,2个吸血鬼在对话。其中一个说,“我真搞不懂,人类这麼脆弱,又这麼容易死掉,有什麼让我们著迷的地方?”另一个吸血鬼回答, “因为他们每件事情都很著急。”吸血鬼是永生不死,所以他们没有什麼好著急的,事情没有完成,100年或1千年后再完成就可以了。在他们眼中,我们这麼著 急,反而很有趣、很迷人。

人类被设定为约以100岁为范围的年龄死掉,我觉得这是一种自由,这是时间的残酷带来的自由。如果你一直逃避人生是有界限的,想靠养生而活久一点,就会没那麼放松,反之,很确切知道人皆会死,绝望反而会带来一种轻松的感觉。

人家说,村上春树的小说弥漫悲观的气氛,却让阅读的人很轻松。就好像吃一顿饭,如果知道有8道菜,每道菜都会品尝出滋味,反之,如果没完没了,到最后你只会希望这顿饭赶快结束。

事情总要有个结束,才品尝得出滋味。年龄肯定让你认识了时间残忍的本质,令人感到绝望,也正因为绝望,产生了轻松的感觉。所以想做什麼,就开始去做,无论成不成,你都做,我觉得这是一种很不错的活法。

“摸索”应该是活著最有趣的过程,尤其在人生初期,别拒绝学习,因为诸事蒙昧,拒绝学习,就是冒险,因为赌的是后来的人生,自己也失去了改变的可能。

信: 我以前很任性,也很感谢很多人,愿意冒著被我讨厌的风险,逼我做很多事情。如果国中老师没有扁我,我可能不会好好念书,也不会考上师大附中,就不会认识现 在的团员。幸好,我有因为外力而认真念书,我觉得应该要让自己拥有选择的机会,不要让未来的你讨厌现在的自己,我很认同“人生的初期不要太任性”这句话。

蔡: 这句话是一位财经界好友讲的,那时,他在教训一位不想学会计的晚辈。他说,如果现在不学,会失去转变人生重要方向的机会。人的愿望是会改变的,除非你很有 把握,从现在开始到80岁,都玩线上游戏、谈恋爱,要不然等愿望改变,自己会的还只是玩游戏、喝酒,人生要怎麼转方向?

这段话给我很大的启发,此后演讲,我再也不敢像以前那样跟学生说,“不要花时间去学不喜欢的东西,与其在课堂上睡觉,不如翘课去谈恋爱,然后失恋,那对人生是更重要的经历。”因为,其他想转方向的人都已经学好了,可是你没学,所以转不过去,你会很痛苦的。

我可能是台湾访问过最多人的,至今,很多人的随口一席话,还是让我醍醐灌顶。我喜欢看书,因为可以躲到另一个比我厉害的脑子里;在我看来,读书跟嗑药一样,可以让人感到世界无限美好、充满自信、浑身力量强大。

信:我的个性也不是急,但就是想在短短的人生里去做些什麼,而且遇到困难,反而更想做。一开始玩乐团有很多困难,一路到现在,写一首歌的过程还是很痛苦。完成时,从头到尾听一遍,只会快乐5分钟,在此之前,我会痛苦5个小时、5天或是5个月。

蔡: 人生是“过瘾”跟“幸福”比较重要。你花很多力气写歌就是过瘾,写出来后,重复听上20遍,却一直在快乐中,那就很白痴。我在录影前的挣扎很过瘾,当我知 道来宾很难对付,一旦想出对策,我就进摄影棚实施这个策略,如果失败了,没有关系,反正我做了,打仗本来有输有赢;如果成功,会很高兴自己把城堡攻下来。 但播出时,我绝不会看,电视很可怕,它会用快乐餵饱我们,餵到我们撑为止,连我都无法免疫。

想想,100年的节奏很快,哪有时间一直看著自己做的节目傻笑。

信: 从小,我最大的问题就是不会讲话,老实说,对自己没信心是我主要的动力。我不善於用言语表达自己完整的感受,第一次的演唱会,我是看著写在地上的讲稿照本 宣科,但我比别人多了耐性,愿意多花时间。例如讲“放肆”,我没办法5分钟讲完,但我可以花5天的时间写成歌词,让大家在几分钟内听完,理解我想讲的事。

蔡: 你刚讲的是用功。用功的过程比较像是在找自己麻烦。每一集开场,你可以说,“欢迎收看《康熙来了》,”但我会想不同的开场白,节目去掉广告,只有45分 钟,我也不要花1分钟让来宾跟观众问好。你会花很多力气准备,其实是因为不甘心,我们都觉得自己有一部分东西要被世界看见。

写文章也是,如果100个人写过了,干嘛再写?我又不是不读书。很多人觉得自己文章写得很好,是因为不读书,不知道别人已经写过800遍了。前面有800个作家压在你头上,你得更厉害才行。我觉得,培养自信,最好是一辈子活在很不放心的状态里。

信: 如果因为代言需要写歌,我也要写得让人耳目一新,这就是你讲的不甘心。最好的励志歌已经被写出来了,就是〈明天会更好〉,在那之后,它用的每个句子,你最 好都不要再用。所以我写词,同一句话,我会写10种,甚至用到100种讲法,包括连接词、介词,我都会想,衍生出来的抉择就很多。我现在有一套标准,“要 自己喜欢”,做了这个东西,我会不会再听一次?如果在车上不小心听到,我会不会喜欢?还是请司机快点转台?

如果你问蔡康永,怎麼抽出时间,保持大量阅读习惯,他会回答,应该去问那些不看书的人,为何没时间?阿信则“摇滚”地形容,看书很爽,所以无论如何都会挤出时间。

蔡康永堪称最用功的主持人,他会花上好几个小时研读受访者资料,曾让大师李敖在录影现场,直问,“你怎麼知道这些没对外人讲的事?”

阿信学的是美术与设计,从画笔到文笔,他的词富含文学底蕴,被形容就是一首首的摇滚诗,光是歌词就让出版社集结成书。他也重拾画笔,与高中同学不二良自创设计品牌,只因为品牌是他在40岁前就要完成的梦想。

阿信说,人们对梦想,总是要求的多,投入的少;对世界是抱怨的多,付出的少。

蔡康永则认为,如果只谈梦想,那也未免太可爱了,没有梦想,不会妨碍追求幸福的可能,重点是你要觉得活著值得。

学会:在乎你在乎的人跟事

世界上,你真正在乎的人不会超过10个,你在乎的事情不会超过10件。如果在死前,你觉得最在乎的3个人,你值得他们在乎,然后你最在乎的3件事,你都有做到,那就已经是超级好了。

信:大部分人不开心、不平静,都是因为要求自己以外的人、要求环境、要求社会。至於,有没有被世界看到,我觉得那是之后的事,但在这之前,是自己的关比较难过。只要做到百分百想做的,之后是尽人事、听天命,这样的好处是,心情随时很好、很平静。

蔡: 我这辈子都遵守一个规则,不要把自己放在某一个族群里生活,才感到安心。人在娱乐圈,不要因为别人都做这种事,就做这种事;你在30岁,不要因为别人都做 这种事,就做这种事。事实上,如果抓住生活的重心,你应该忘记自己在人生的哪一段。假若你是30岁,你可以把自己当成17岁的人来生活,也可把自己当成 80岁的人来生活。

信:很多事情我满在乎本质,但我发现,我在意的常是很多人不在意的事。

蔡:我一直都搞不懂,把一切都弄的很稳定,人生有什麼乐趣?我看到抽屉分类很整齐,袜子、衣服井然有序,就会觉得,这麼简单有什麼好分类。有些人的脑子里装了很多数据,我会觉得,又不是没有网路可以查,装那麼多数字干嘛?叫你讲个道理,却讲不出所以然。

不管你现在是20、30或是40岁,唯一的人生原则,只要在乎你在乎的人跟事。20岁时,在乎你在乎的人跟事;30岁时,更在乎你在乎的人跟事;40岁时,更更在乎你在乎的人跟事。

说穿了,人生的基本需求都一样,你就是会有一点点你在乎的人跟事,那些事满足了,你就会觉得幸福,那些事不满足,纵然有游艇、飞机、城堡,都没有用。

世界上,你真正在乎的人不会超过10个,在乎的事情也不会超过10件,排出优先顺序排,如果在死前,你觉得最在乎的3个人,你值得他们在乎,然后你最在乎的3件事,你有做到,就已经超级好了。人生无比慈悲,才会是这个结果,甚至,只在乎1件事、1个人就足够。

学著:在别人生命留下痕迹

在活著的当时,启发过一些人,帮助过一点人度过难关,你撒出去的种子在某些人的心里埋了下去,某天,在需要的时候,开出一朵花来,已经幸运的不得了。

蔡:有次,我问蔡国强,“像你这麼棒的艺术家,到底想要什麼?”他回答一个我完全想不到的答案——不朽。

做创作的人,最后追求的,即使不夸张到使用这2个字,起码还是希望在文明累积的过程,留下痕迹。在活著的当时,启发过一些人,帮助过一点人度过难关。

人跟人的相遇要在对的时刻,要不然就错过了。我观察,大陆内地的年轻人空了很多心灵的位子。当他们呼唤一个有燃烧感的乐团时,五月天出现了;他们呼唤自由自 在的美女时,小S出现了。参与的当下最令人庆幸,如果能在某一时刻,变成唯一,就算1、2年内结束,我也觉得是非常仁慈的恩赐。

我会把自己 拔离现在的时空去思考事情。20年、50年后,五月天不会是音乐史上最红的乐团,《康熙》也绝不是电视史上最红的节目,一旦没有了,立刻会被忘记。但是没 关系,你撒出去的种子在某些人的心里埋了下去,某天,在需要的时候,开出一朵花来,已经幸运得不得了,如果阿信的歌,能帮助一个过不去的人度过那个晚上, 那你的歌就光芒四射了。

信:大陆的年轻人其实有很多我们想像不到的地方,我的感觉是,他们对於美好的事物,或是有力量的事物,非常渴望,甚至是饥渴的。

蔡: 我们在作品里传递想法,对於台湾年轻人的重要性,远不及内地年轻人。台湾的年轻人很像走进速食店,有100种套餐任君点选,对他们来讲,吃什麼不是餵饱肚 子,只不过是100种中的1种。对内地的年轻人来说,等他们成长到40、50岁时,他们对一个自由自在、热情燃烧人生的看法,会跟没听过五月天,没看过康 熙的人不一样。这就是我讲的,你有在别人身上留下痕迹,此生不能再期望更多。

就像写作,到底是被阅读重要,还是有人付费比较重要?你付我100万元,没有半个人读,跟100万人读,但没付我半毛钱,我自己是想要被100万人阅读,所以我写博客。

信:如果人可以活100年,你希望最后的墓志铭上写什麼?

蔡:我希望可以不要惨到要靠墓志铭才被人记得。

喜欢你的人不需要你的解释,不喜欢你的人,也不需要你的解释,所以,你要解释给谁听?墓志铭也一样,喜欢你的人不用靠墓志铭来记得你,不喜欢你的人才不在乎你的狗屁墓志铭写在哪里。我连墓都不要,哪里有水沟,(骨灰)倒一下就好了。

你的墓要很豪华吗?

信:我只要留一句话就好——“记得我的歌,不要记得我。”

蔡:所以,你还是希望不朽啊!

信:一定要的!我很认同这2字。写歌是全世界最神奇的事。我是学画画的,画图还要煞有其事的去买水彩纸、颜料,写歌只要一枝笔、一张纸,甚至都不用,只要记在脑子,坐著就可以写歌。

写出来后,权力很大,只要把一个人教会,他喜欢就会一辈子记得,而且会像病毒一样一直传染、扩散,谁都可以唱。你有尝试过写词吗?

蔡:超失败。我很会写文章,可是我不会写歌词。文字创作的人都有洁癖,如果不够厉害,才不要招惹那个东西。对於不会的事,我充满神秘的尊敬,就像我对於初级会计一样。

我不会写歌,脑子少了那一块,因此很崇拜那件事,如果只是歌,我还觉得没有被打败,但加上歌词,超越我的能力。被歌词打败,真的败得很没尊严,可是值得的,你永远都可以很高兴,世界上有比你厉害的人,他们启发了很多自己做不到的乐趣。

人很妙,会为了几乎要接近的境界疯狂,而不会为了永远达不到的境界痴迷。最受大众欢迎的明星,其实是大部分人都能做得到。太阳马戏团是一般人做不到的事,不 过,有哪个咬钢丝旋转,或跟熊跳舞的人变成万世巨星?没有!大家只觉得那是奇迹,好像上帝用闪电打了一下,因为我们都做不到,感觉没什麼好参与;但 是,MichaelJackson的舞你跳不到,可是你会跳舞,好像有点快接近了,却一辈子都接近不了,大家就会好爱、好爱那个人。

某个程度,我得同意音乐的创作几乎是最过瘾的事,不只是五月天,我听巴哈的赋格曲、普契尼的咏叹调,连听昆曲我都会觉得,天呐!人怎麼这麼容易就被控制住。做电视用的是世间的语言,音乐人用的是非世间的语言,那个很过瘾,你们得到了一把钥匙,是一般人得不到的。

●传承者蔡康永:1962年生。作家、知名主持人。加州大学洛杉矶分校电影电视研究所硕士。著有《痛快日记》《LA流浪记》《那些男孩教我的事》《有一天啊,宝宝》等书。

●接班人陈信宏(五月天阿信):1975年生。作家、五月天乐团主唱。实践大学室内设计系。著有《Happy‧Birth‧Day摇滚诗的诞生与转生》《浪漫的逃亡-游日非流行指南》等书,并自创STAYREAL品牌。

文│林静宜

从电影到电视,透过大量的阅读,蔡康永把他的价值观“翻译”给这个世界。阿信在高中时组乐团,信仰摇滚,让一路在平淡中长大的自己,开始不一样的命运。

抽言:

阿信:我感谢很多人,愿意冒著被我讨厌的风险,逼我做很多事情;人应该要让自己拥有选择的机会,不要让未来的你,讨厌现在的自己。

蔡康永:人生初期,别拒绝学习,因为诸事蒙昧,难免摸索,任性的拒绝学习,就是冒险,因为赌的是后来的人生,自己也失去了改变的可能。

附:微博名句

  1. 15 岁觉得游泳难,放弃游泳,到18岁遇到一个你喜欢的人约你去游泳,你只好说“我不会耶”。18岁觉得英文难,放弃英文,28岁出现一个很棒但要会英文的工 作,你只好说“我不会耶”。人生前期越嫌麻烦,越懒得学,后来就越可能错过让你动心的人和事,错过新风景。——《康永,给残酷社会的善意短信》
  2. “享 有”比“拥有”贵重。我们“享有”空气,但无法“拥有”空气,我们“享有”阳光,但无法“拥有”太阳。同样的,我们享用友情亲情,但没办法,也不该想“拥 有”那个友人亲人,我们也享用爱情,但没办法,也不该想“拥有”那个爱人。就享有吧,“享有”比“拥有”贵重多了。——《康永,给未知恋人的爱情短信》
  3. 谈恋爱的对象,最好比你笨——不用太笨,只要笨到,会真心相信你的承诺,爱情就得以成立了。…..嗯…..可是啊……谈恋爱的对象,最好比你聪明——不用太聪明,只要聪明到,不去追究你的承诺,爱情就得以延续了。——《康永,给未知恋人的爱情短信》
  4. 一 朵云里面的两滴雨,恋爱了。旁边别的雨滴很冷淡,反正很快要掉落,何必呢。但这两滴雨,还是要恋爱。不久这天到来,云变成雨,一滴滴纷纷掉落。而恋爱着的 这两滴雨,拥抱在一起,往下掉,他们准备好要掉在地面,消失不见,但就在消失前,他们从两滴变成了一滴。——《康永,没人在乎的小报导》
  5. 你要拥有他?真好,只是,你能拥有他的什么呢?你能拥有他的疾病吗?你能拥有他的疤痕吗?你能拥有他的回忆吗?……好像都不能耶,那,你能拥有他的什么呢?——《康永,给未知恋人的爱情短信》
  6. 你很重要,因为你就是你能拥有的全部。你存在,整个世界才存在。你看得到阳光,整个世界才看得到阳光。你失去平衡,世界就失去平衡。你消失,世界就消失。所以你很重要,你就是你能拥有的全部。——《康永,给残酷社会的善意短信》
  7. 气质可以假装,通常可以假装一晚上都不穿帮;而幽默感没办法假装,一分钟都假装不了.所以我珍视幽默感,远超过气质.——《康永,给残酷社会的善意短信》
  8. 你以为你对他的想念,已经到了极致了,已经不可能想念得更多了,结果,在某一个意想不到的时刻,你又成功的,比原来想他的程度,再更多想念他一点点——《康永,给未知恋人的爱情短信》
  9. 你恋爱了,只是你爱的人,有时并不真的存在。他可能只是一堵无辜的白墙,被你狂热的,把你心里最向往的爱情电影,全部在他身上投影一遍——【康永~给未知恋人的爱情短信】
  10. 对方说:“我已经不爱你了。”,你着急了,脱口而出:“没关系的啊!我们还是可以在一起的啊!”,说完,你忽然哭了,不是因为伤心对方不爱你了,而是因为这一瞬间,你猛然醒悟,自己已经成为爱情的乞丐——【康永~给未知恋人的爱情短信】
  11. 球 赛快结束时,播报员激动喊着:“时间越来越少了!剩下的时间是越来越少了!”,这样播报当然没错.但我听到时总忍不住想着:别激动啊…时间一直都是越 来越少的.不管你是谁,不管你几岁,不管你在做什么,时间从来都不会越来越多,时间永远是越来越少的…永远,越来越少….【康永,给残酷社会的善 意短信】
  12. 你那时发给我的短信,我一直留着没有删除.因为我还是需要一点证据,证明即使是你,也有过那么爱我的时候——【康永~给未知恋人的爱情短信】
  13. 对 方穿得很丑,我们也要”昧着良心”称赞漂亮吗?对方煮菜难吃,我们也要”昧着良心”称赞好吃吗?我大部份时候会建议:“是的”.因为这事和良心实在没啥关 系,却严重影响你的人际关系.别把良心消耗在这么表面的事上,良心没这么廉价,如果真的在乎,用得到良心的地方多的是啊.【康永,给残酷社会的善意短信】
  14. 你说,你就要老了。。。我回答,不会的,在我们没有见面以前,你不会老的。。。。如果我们永远见不到,你就永远都不会老的。。。。。爱情是我们的发条.它没转动,我们的音乐盒,就永远都不会转动。。。。。【康永~给未知恋人的爱情短信】
  15. /被劈腿了真伤心/只好安慰自己眼光还不错/喜欢的人别人也喜欢/《蔡康永的躲避诗》
  16. 一 直被问,在此答了~~(问)你为什么答应韩寒帮【独唱团】第一辑写文章?(康永答):令狐少侠相邀,那是令狐少侠看得起咱们。/(问)你这次怎么拿捏风 格?(康永答):既是令狐少侠的场子,就照令狐少侠的风格:笑意中带杀意。/(问)你今天干嘛一直称韩寒为令狐少侠?(康永答):他很像啊。/
  17. 《蔡康永为大家写的躲避诗》://我也不想以貌取人呀//我也有努力看见你的灵魂呀//结果你的灵魂也没有比你的外表美呀//
  18. 《蔡康永为大家写的躲避诗》//後来的每一次笑//都只是第一次那个真实的笑//所剩下的东西//
  19. 看见那个人现在的样子,总忍不住在过了转角以後,稍微停住脚步,想像一下:当初如果没有分手的话,现在,在自己身边的,就是这个人了。。。。《康永~给未知恋人的爱情短信》
  20. 大 学需要念4年吗?初中加高中需要念6年吗?小学需要念6年吗?念完毕业就22岁了,这22年里,多少年是教室里的瞌睡?多少年是百无聊赖的寒暑假?最后从 这条生产线上,咻的一声,滑到待运送纸箱里的这个22岁的人,不会已经被折磨到,濒临新鲜期限的边缘了吗?《康永,给无聊大人的诚实短信》
  21. 不 要恨那些“以貌取人”的人,不要恨这件事。“以貌取人”是人的天性,恨它,它也不会消失。它就是一堵墙,你用恨,是恨不倒它的,你又不是孟姜女。只要在必 要时,你能翻过这堵墙,让别人看得到真正的你,让墙挡不住你,就够了。翻墙是费事,但比倒在墙下“恨墙”值得。【康永~给残酷社会的善意短信】
  22. “你看吧,我不是早就跟你说过了!”这话很容易让人发火,让我们想回嘴:“对啦!你最厉害啦!”这话为啥这么讨厌?因为你就已经在倒楣了,再听见这种完全帮不 上忙的风凉话,除了发火,还能有什么别的感觉?所以,如果小时候已经受够了这话,长大后就练习别说这句吧。【康永,给无聊大人的诚实短信】
  23. 恋 爱不是坚固的溜冰场。恋爱是一片结了冰的湖面。我们是可以在上面手牵着手,轻飘飘的嬉戏,绕着我们自己的圈圈,只是不会有人来警告我们,冰会在那一秒溶 化、裂开,恋爱中的我们会在哪一秒,带着忽然冻结的欢笑,掉进冰冷的水中,孤单,挣扎,觉得好冷。。。【康永,给未知恋人的爱情短信】
  24. 我 们有时要勇於说出“关你屁事”四字,或起码怀抱这种气魄。很多非亲非故的外人爱问:“怎麼还不结婚?”,“怎还不生孩子?”,请问,关你屁事呢?难道结婚 生子你保证幸福吗?不幸福你赔一千万吗?这些人从不自觉失礼,回敬他一句“关你屁事”,或可教育他一下。【康永,给无聊大人的诚实短信】
  25. 学 校烂,上课闷,你就从此拒绝学习和阅读,以示抗议吗?杀错方向啦。他们教学失败,那是他们搞砸他们的工作。你拒绝学习和阅读,你是在搞砸你的人生啊。这不 是抗议,是自残,你抗议的对象无感,而你自己尝苦果。就像你连续吃到三家烂餐厅,难道你就从此绝食,以示抗议吗?【康永~给残酷社会的善意短信】
  26. “你 看看谁谁家的孩子!你为什么就不能像他那样呢?”若有爸妈爱讲这话,嗯,别家孩子的出色表现,就像是路边橱窗的展示品,你看到会羡慕,但那些展示品造出来 需要各种成本,不是想造就会成,造成了也未必划算,你不管过程,只管怨叹橱窗里的好东西不是你的,很任性啊。【康永,给无聊大人的诚实短信】
  27. 讲 话时最好自觉的降低音量,不光是因为太大声会吵到别人,而是因为如果一个人连自己的音量都控制不好,会让别人很难信任你其他各方面的能力。就像如果一只狮 子连自己的脚步轻重都控制不好,老是弄出不必要的声响,你要怎么相信这只狮子能猎到鹿?……【康永,给残酷社会的善意短信】
  28. 好 多人认识了字,却只“看字”,不“阅读”。他们看路标,看证件,看各种说明书,但他们不“阅读”。.真可惜。他们明明有了翅膀,但他们只用这对翅膀搧风升 火,对付生活。他们不相信,如果把那对翅膀伸展开,他们其实可以飞翔的。…………【康永,给无聊大人的诚实短信】
  29. 鸡生 蛋,鸡也拉屎,但你肯定只吃蛋,不吃屎的.对鸡如此,对人亦然:每个出色的人,都会生蛋,也会拉屎.例如他很会开公司,那你就买他家股票来赚钱,至于他乱 说话,你就不用学.你最要紧是多吃鸡蛋,少理鸡屎,吸取营养,壮大自己.很多人放着蛋不吃,整天追究屎,难道你靠吃屎能变壮大?【康永.给残酷社会的善意 短信】
  30. 蝴蝶这样美丽,蜘蛛看着,爱上了蝴蝶。蜘蛛忍不住在网上织出一句又一句“我爱你”,织成了森林中最美的一张网。蝴蝶很感动,快乐 的降落在网上,就被黏住,怎么挣扎都动不了,力气用完,蝴蝶就死掉了,死在无数句“我爱你”上面。蜘蛛看着眼前的这一幕,不能明白发生了什么事情。【康 永,没人在乎的小报导】
  31. 才华这种东西,和冰箱里冷冻的肉很像,再怎麼上等的肉,冷冻太久不用,也就酸臭了。。。如果你知道自己有才华, 就跟知道自己冰箱里有冷冻的肉一样,不是什麼值得傲慢的事情,把那个才华拿来做成些什麼,胜过存一堆酸臭的肉,塞爆你冰箱,最後连冰箱都弄坏。【康永~给 残酷社会的善意短信】
  32. 趁上司进隔间里上厕所时,偷偷尾随而入,然後在洗手台一边洗手,一边等随便哪个同事进来,你就对这同事随口赞美上 司几句,这时仍在隔间里的上司,听到了就一定会对你有好印象。不过这个贱招,可能会连累那个後进来的同事,因为不知情的他,可能会臭骂你拍马屁的上司! 【康永,给残酷社会的善意短信】
  33. 如果手段是邪恶的,那整件事就注定是邪恶的。有些人或组织,说他为了正当美好的目标,不得已使用邪恶的 手段。永远不能接受这种说法!一旦接受,他的手段只会越来越邪恶,而正当美好的目标,永远不会实现。对邪恶无尽让步的世界,等于中毒的土壤,一切花朵,都 成奢望。【康永~给残酷社会的善意短信】
  34. 恋爱的纪念物,从来就不是那些你送给我的手表和项链,甚至也不是那些甜蜜的短信和合照。。。恋爱最珍贵的纪念物,是你留在我身上的,如同河川留给地形的,那些你对我造成的改变。。。。。【康永~给未知恋人的爱情短信】
  35. 他 们爱说“我从不去那种地方”,“我从不想那种事”,“我从不和那种人做朋友”。他们自认有原则,但其实他们只是很害怕,他们害怕”改变”。他们只愿死守住 不知谁硬塞给他们的那些没意思的想法,过一辈子。唉,做为植物的蒲公英,都比他们勇敢啊,敢让种籽飞翔去流浪。【康永.给残酷社会的善意短信】
  36. 如 果羡慕成功者的富贵,请别一味模仿他们富贵后的事,那些名牌表呀包呀酒呀车呀,都是他们富贵后的事,硬撑著模仿了,也只能图个穷开心而已。要模仿,就模仿 他们富贵前的事,他们那些鹰般的探查,蛇般的专注,蚁般的搜括,蛹般的耐心,全是些风吹日晒,灰头土脸的事啊。【康永~给残酷社会的善意短信】
  37. 爱情不是宗教。宗教是你感受到以后,就可以进一步相信。而爱情是就算你感受到了,你还是可能不相信。我遇过一些这样的人,他们再怎么强烈的感受到爱情,他们还是不相信。。。。【康永~给未知恋人的爱情短信】
  38. 当 你对别人乱发脾气,譬如指控对方“只爱钱”,你会被指正,因为对方被伤害,会反击。但当你对人生发脾气,说出“再努力也没用啦”、“事情永远不会改变啦” 这些气话时,却不会被指正,因为别人没事,你伤害的只是你面对人生的信心和斗志,令你自己越活越没意思。…【康永,给残酷社会的善意短信】
  39. 美好的人,并不是那么难遇到。难遇到的,是美好而且深爱我们的人。因为深爱,我们才得以享有体会进而理解他们的美好,他们的不为外人所知的美好。。。。。【康永~给未知恋人的爱情短信】
  40. 苦 尽就会甘来吗?嗯…这要看你吃的是哪种苦。如果你吃的是有方向的苦,比方:为了吸引人而减肥减到快饿死.或,为号召顾客而赔本撑半年.这就比较可能苦 尽甘来。但如果是没有方向的吃苦,一味的被瞎整,被欺负,那有什么道理会苦尽甘来?横竖要吃苦,弄清方向,才有指望。【康永~给残酷社会的善意短信】
  41. 活 着就是会吃到苦。如果味道实在太苦,那就赶快吐掉,然后去漱口。如果是吐不掉的,非吞下去不可的苦,那就赶快吞下去。不管是要吐掉,还是要吞下,反正就是 不要把苦含在嘴巴里,细细咀嚼。苦味存在,是为了帮助我们下次趋吉避凶,不是每餐拿来给我们下饭的。。。【康永~给残酷社会的善意短信】
  42. 生 活中老是有人在找你麻烦吗?想一下金庸“笑傲江湖”里,令狐冲、田伯光、风清扬三人的情节吧:田伯光每砍令狐一刀,令狐接不住招,就进山洞去求教风清扬, 终于一步步练成了绝世高招。如果没有讨厌鬼像魔鬼教练一刀刀砍我们,我们可能就没有动力这麽积极的练功吧。。。{康永~给残酷社会的善意短信}

无觅相关文章插件,快速提升流量