作为一个纯 JAVA 的GUI应用,JMeter 对于CPU和内存的消耗还是很惊人的,所以当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至还会引起JAVA内存溢出的错误。不过,JMeter 也可以像 LoadRunner 一样通过使用多台机器运行所谓的 Agent 来分担 Load Generator 自身的压力,并借此来获取更大的并发用户数。根据 JMeter官方文档的署名,你需要自己完成这个配置,不过不用担心,这将非常简单 ^_^
1. 在所有期望运行 JMeter 作为 Load Generator 的机器上安装 JMeter,并确定其中一台机器作为 Controller,其他的机器作为 Agent。然后运行所有 Agent 机器上的JMeter-server.bat文件——假定我们使用两台机器 192.168.0.1 和 192.168.0.2 作为 Agent;
2. 在Controller 机器的 JMeter 安装目录下找到 bin 目录,再找到 JMeter.properties 这个文件,使用记事本或者其他文字编辑工具打开它;
3. 在打开的文件中查找“remote_hosts=”这个字符串,你可以找到这样一行“remote_hosts=127.0.0.1”。其中的 127.0..0.1 表示运行 JMeter Agent 的机器,这里需要修改为“remote_hosts=192.168.0.1:1664,192.168.0.2:1664”
默认的端口号为:1099
——其中的 1664 为 JMeter 的 Controller 和 Agent 之间进行通讯的默认 RMI 端口号;
4. 保存文件,并重新启动 Controller 机器上的 JMeter.bat,并进入 Run -> Remote Start 菜单项。看到啥了?^_^
话说上回,我们用Badboy录制了Jmeter的
脚本,用Jmeter打开后形成了原始的脚本。但是在实际应用中,为了增强脚本的多样性,就要使脚本
参数化。这里我以登录为例,参数化
用户账号与用户密码。
图1 :原始脚本
这里我利用Jmeter的CSV Data Set Config来实现参数化功能。
步骤如下:
1.在本地磁盘下新建一个文本。比如:F:\test.txt 文件的内容如下:
user,passwd
user1,passwd1
user2,passwd2
2.右键点击Jmeter中需要参数化的某个请求,选择添加——配置原件——CSV Data Set Config,会添加一个CSV Data Set Config,需要设置相关的一些内容,具体如下:
图2:CSV Data Set Config设置
解释下图2的参数:
Filename:文件名。指保存信息的文件目录,可以相对或者绝对路径(比如:F:\test.txt)
Variable Names:参数名称(如:有几个参数,在这里面就写几个参数名称,每个名称中间用分隔符分割,分隔符在下面的“Delimitet”中定义,为了和文件中的“,”对于,这里也用“,”分割每个参数名,(比如:user,passwd)
Delimitet:定义分隔符,这里定义某个分隔符,则在“Variable Names”用这里定义的分隔符分割参数。
Recycle on EOF:是否循环读入,因为CSV Data Set Config一次读入一行,分割后存入若干变量中交给一个线程,如果线程数超过文本的记录行数,那么可以选择从头再次读入。
3.在需要使用变量的地方,比如在登录操作中,需要提交的表单字段包含用户名密码,我们就可以用${变量名} 的形式进行替换,例如${user}和${password}。如图3
图3:参数化设置
这样,脚本的参数化基本上完成了。如果我们要确定Jmeter有没有按照我们的预期进行工作,我们应当考虑使Jmeter提供的断言,加到Sampler 里面可以对返回的结果进行判断,例如判断HTTP返回结果里面是否含有某个字符串。我们可以根据自己的需要选择要测试的响应字段,文本,还是代码,一般选 择响应文本,然后,我们选择匹配规则,一般选择“包含”,如果要精确匹配,则可以选择“匹配”,但是选择“匹配”,因为响应的内容一般还包含其他的信息, 比如html语言标签,所以很难准确匹配。然后在在要册似乎的模式下面,添加你要响应的内容。如图
图4 :断言设置
添加好断言后,要添加一个监听器,以监听响应断言,选择添加——监听器——断言结果。
图5 :添加断言结果
添加完断言结果后,我们运行脚本来测试下参数化和断言的功能。首先先设置下线程组中的线程数,Ramp-up period,和循环次数,我这里设置为10,0,5.就是10个线程
并发,循环5次。然后点击运行-启动。我们查看断言结果的图。
图6:运行成功的断言结果
运行没有出错。全部成功。我们修改下登录参数,让登录失败,然后看下断言结果。如图
图7:响应断言失败
代码分析也无需事无巨细皆列而剖之,只要找到关键所在也就是了;又不然列一堆的声明上来,纵然有人有耐心看下去,我也没耐心写下去啊。特别关注了三 个类,Stats、MonitorPerformancePanel、MonitorGraph。分别是获取解析得到的数据、监控器面板显示和监视器上的 图像绘制。下面选取了一些关键代码来进行分析:
首先是Stats.java,下面是计算内存使用率的方法
public static int calculateMemoryLoad(Status stat) {
double load = 0;
if (stat != null) {
double total = stat.getJvm().getMemory().getTotal();
double free = stat.getJvm().getMemory().getFree();
double used = total - free;
load = (used / total);
}
return (int) (load * 100);
}
很简单吧?就是获取total值和free值,然后计算内存使用率,那么它解析的是什么东西呢?我们取了一份tomcat上的status的xml,内容如下:
<?xml version="1.0" encoding="utf-8"?><status><jvm><memory free='937000' total='5177344' max='66650112'/></jvm><connector name='http-8080'><threadInfo maxThreads="40" currentThreadCount="2" currentThreadsBusy="1" /><requestInfo maxTime="1715" processingTime="2819" requestCount="20" errorCount="2" bytesReceived="0" bytesSent="108662" /><workers><worker stage="S" requestProcessingTime="0" requestBytesSent="0" requestBytesReceived="0" remoteAddr="127.0.0.1" virtualHost="localhost" method="GET" currentUri="/manager/status" currentQueryString="XML=true" protocol="HTTP/1.1" /><worker stage="R" requestProcessingTime="0" requestBytesSent="0" requestBytesRecieved="0" remoteAddr="?" virtualHost="?" method="?" currentUri="?" currentQueryString="?" protocol="?" /></workers></connector><connector name='jk-8009'><threadInfo maxThreads="200" currentThreadCount="4" currentThreadsBusy="1" /><requestInfo maxTime="0" processingTime="0" requestCount="0" errorCount="0" bytesReceived="0" bytesSent="0" /><workers></workers></connector></status>
这乱七八糟的,谁看得清啊,不要急,保存下来命名为.xml文件,扔到ie里再看一下
其实上面那段代码所取的,就是这个xml里面的memory free和total。
这 个xml里这么多可以利用的内容,要是我们都解析出来,不就可以有很多资源数据了?有人也许会问,这些都是什么tread信息什么,又没有cpu啊,io 之类的信息,解析出来也没用;要知道,这个xml文件你自己可以生成的,里面存什么数据,你自己怎么定义都行啊,定义好了,写一个动态更新这里面的数据的 脚本或程序,再利用web去展现这个xml,jmeter不就可以取来用了?
我们再看看MonitorPerformancePanel.java
public static final String LEGEND_MEM = JMeterUtils.getResString("monitor_legend_memory_per"); //$NON-NLS-1$
public static final ImageIcon LEGEND_MEM_ICON = JMeterUtils.getImage("monitor-orange-legend.gif"); //$NON-NLS-1$
这两句就是设置监视器上显示的图例,是啥东西呢?就是这个:
标识了图线的颜色和内容标签
上面两句设置好了,要显示就要看下面这段的了:
JLabel mem = new JLabel(LEGEND_MEM);
mem.setFont(plaintext);
mem.setPreferredSize(lsize);
mem.setIcon(LEGEND_MEM_ICON);
legend.add(mem);
做过java的gui编程的朋友一定不会觉得陌生,呵呵
再下来看一下MonitorGraph.java
if (MEM) {
int mmy = (int) (height - (height * (model.getMemload() / 10000.0)));
int lastmmy = (int) (height - (height * (last.getMemload() / 10000.0)));
g.setColor(Color.orange);
g.drawLine(lastx, lastmmy, xaxis, mmy);
}
这段就是展现曲线的代码,可以产生如下的效果:
用jmeter做过tomcat监控的人一定会觉得很熟悉。不过也许会问,为啥这个图像上曲线这么多呢,jmeter不是就四条么?
呵呵,不忙,且听我慢慢道来。
我们团队WP7上基于Academic Search 的会议助手手机客 户端的alpha版本已经结束。在团队中,限于团队规模,每个人都会做点dev的事情,但是 我的最为主要的角色就是tester,以前从未做过tester,一个月的alpha版本开发下来,我在tester的岗位上也有许多的感想,我想,把它 们都记下了,希望它见证我们的成长,当然,希望能够得到大家的指点,从众人的认知领域获得我们能汲取的经验和知识。
理论上我们学到了什么?
我想,人们对于test最基本的认识,莫过于尝试使用软件,找出bug。事实上,真正做测试的时候要有很规范的流程。我简要的挑几个概念跟大家分享一下。
1)测试计划:测试计划描述测试活动的主要方面,why?what?who?when?。详细的说包含一下方面:
测试的策略和方法、测试日程安排、质量目标、资源、测试变量矩阵。
2)什么是测试变量矩阵:
简单的说,测试变量矩阵是通过考量用户类型,系统的OS,语言,浏览器类型,网络情况等各种因素,来确定测试变量数目以后列出的一个表格,测试变量矩阵是测试人员进行测试的蓝本。
3)软件测试的方法:
这里首先澄清一下,我们常说的黑箱测试和白箱测试其实并不是指的某种软件测试的方法,它们是两类软件测试设计的方法。我们OMG团队在alpha版本里主要采用的软件测试方法集中在功能测试和非功能测试。
软件测试方法,按功能测试分类,有单元测试(验证测试每个单元程序的正确性)、模块功能测试(测试每个模块的功能)、集成测试(几个相互依赖的模块的功能的测试)、场景测试(验证能否完成特定的用户场景)、系统测试和alpha测试(alpha发布在实际的用户环境中对软件测试)。而非功能测试包括负载测试,效能测试,本地化/全球化测试,兼容性测试,配置测试,易用性测试和软件安全测试等。
当然,软件测试的方法还有很多,包括代码覆盖率测试(PS:对于新手的我来说,我真不知道如何设计代码覆盖测试方法。。。求高人指点)、验收测试、回归测试、“探索式”测试等等。
作为tester有何工作感想?
首先,我想说,主要角色是tester, 尽管我做的dev的工作相对较少,但是,我不觉得自己比别人贡献的少。
很多人会有种执念,做软件开发,不做dev似乎就没有动力。其实,通过一个月的实践,我觉得,社会本就是高度分工的。tester在一个软件开发中起到的作用也是不可忽视的。很简单,如果不做各种测试,软件性能如何去评测?如何保证最后release的产品能够很好的满足用户的需求?
其次,test工作并没有想象中的那么容易。
一开始,接手tester的角色,心里想自己的工作压力应该是比较小的。事实证明,真正用心去做好一个tester,还是需要付出很多的努力。在产品的 计划阶段,tester要讨论测试计划,调研和收集用户对软件的非功能性需求,比如软件的效能,易用性等的信息,确定我们的非功能性测试标准;在开发阶 段,tester需要及时的进行BVT(Build Verification Test),及时提交bug给dev,另外,作为tester,需要想很多“探索性测试”的例子,随机的验证软件的稳定性和鲁棒性;而当进入稳定阶段后, 尤其是alpha版本发布后,tester需要收集用户的alpha试用反馈,确定beta版本的测试标准。
最后也是最重要的一点,tester应该有怎么样的素质。
做了把tester,才知道,tester不是那么好做的,当然,自己水平是那么那么的有限,所掌握的和接触的知识也是比较少的。结合我的工作体验,我发现了一下几点:
1、足够细心、耐心和信心。
首先你得相信自己有足够的创造性和好奇心,要相信自己能挑出软件的bug。然后你才有动力去尝试各种可能的case,如果没有了好奇心,打打酱油或许某 个bug就不经意间溜走了。而耐心和细心是做好任何工作的基础。tester的工作,更是这样,试想一下,某个功能或者某个用户场景,你需要尽可能多的设 想各种test case去挑剔它,其实,有时候并不是那么的有意思的事情。
2、见多识广,基础要好。
我作为一个非CS专业的tester,更是对这一点体会有嘉。tester在设计黑箱测试方法的时候还更多地依赖创造性好奇心等。然而做白箱测试,代码 的结构其实是对你透明的,能不能专业的分析代码结构,能不能敏锐的察觉代码中可能的风险或纰漏,这就是考验一个tester专业技能的时候了。另外,见多 识广很重要,tester要是能了解IT的各个方向,背景知识比较的多,对他来说,设计更好更有创造性的test case是相当有利的。
3、学习与钻研精神。
取人之长,补己之短,他山之石,可以攻玉。老祖宗都说烂了。但是,我的经历又一次检验了它。我从一开始连test plan都不知道如何下笔,到今天写下这篇日志,我觉得,这就是从学习的过程中积累下来的,尽管我刚刚接触它,我的这些文字看上去显得稚嫩而有浅显,但是,学习让我成长,我也相信,学习能让每一个都或者成功,或者成长。与君共勉。
贺炘-让
测试敏捷起来在微博上问道:刚刚了解到,大多数测试人员不按测试用例来进行测试,原因是太麻烦了,那么测试用力基本形同虚设,对于这个问题,您怎么看?
大家对此展开了讨论。
贺炘-让测试敏捷起来: 首先测试过程是需要规划的。规划的方法可以是大纲或者具体的用例,也就是用颗粒度来平衡。
徐毅-Kaveri:回复@宝贤2011:测试用例要看你具体的内容,写得太详细,那么很有可能容易过时,某些命令、操作已无法执行;也有可能是用例写得太虚,起不到指导的作用。这些都有可能是对方不按用例执行的原因,需要去弄明白。
宝贤2011:回复@徐毅-Kaveri:原来是这样,不过据说用例写得太详细了,就没有人愿意去执行,很麻烦。现在搞不清楚什么样的用例才是好用例。用例形同虚设的多呢。
徐毅-Kaveri:回复@宝贤2011: 从你的描述中可以看出,你应该是站在测试用例编写人的角度在思考问题,并未考虑用例阅读者的需要,例如用例的可读性、易理解程度?另外,我觉得用例的编写 和执行根本就不应该分开,所以,我感觉在你们的组织结构设置里应该也是存在一些问题的。
宝贤2011:回复@徐毅-Kaveri:你是 说公司的组织结构吗?如果是公司的组织结构设置应该在大多数公司都存在问题,所以这个,不应该在考虑的范围内,即使存在问题,也应该想办法克服,所以仅从 这个事情的角度来说的话,测试用例是很难写出高覆盖率又简捷的。高覆盖率和简捷是大多数包括测试用例编写者,以及执行者都希望看到的。
徐毅-Kaveri:回复@宝贤2011: 有的办法治标有的办法治本。那你就先从改进测试用例入手吧,和执行测试的人员一起来看测试用例,一起来执行测试用例,看看到底是哪些地方、哪些语句、哪些操作不好执行了,然后再修改,很简单的事情啊。
宝贤2011:回复@徐毅-Kaveri:我有很多做测试的朋友,他们也一样,用例和执行根本不在一起执行,我想知道这其中发生了什么事情。如果用例写得不够丰富,上面有关部门会觉得不够丰富,何况什么事做到事无巨细,是很烦人的事情。
VIATelecom陈波:测试用例是需要分类的。功能、交互性、性能、压力、兼容、自动化等等,在项目不同阶段来执行发挥不同作用。用例对于覆盖还是 非常有用的,执行时的粗细程度要测试人员根据项目情况来判断。测试人员的情况是有差别的,组织者需要根据大家的情况安排不同的培训,以求得更好协同工作,发挥大家最大的作用。
宝贤2011:回复@VIATelecom陈波:我认为测试应该从四个部分入手:1、界面——分页、输入格式、对不正确的数据有无验证、与设计页面是否 相符。2、数据测试——CRUD是否正确、报表、业务规则等等。3、业务测试——各基础类模块是否传递正确数据。4、流程测试。不知道您有什么看法?
VIATelecom陈波:回复@宝贤2011:光从测试本身来说,根据测试不同的产品,可以对测试做一些分类,没有问题。很多时候需要结合项目的情况来决定每个版本做哪些测试,这很重要。
软件测试方法种类繁多,记忆起来混乱,如果把软件测试方法进行分类,就会清晰很多。我参考一些书籍和网上的资料,把常用的软件测试方法列出来,让大家对软件测试行业有个总体的看法。
从测试设计方法分类
测试名称 | 测试内容 |
Black box黑盒测试 | 把软件系统当作一个“黑箱”,无法了解或使用系统的内部结构及知识。从软件的行为,而不是内部结构出发来设计测试. |
White box白盒测试 | 设计者可以看到软件系统的内部结构,并且使用软件的内部知识来指导测试数据及方法的选择。 |
Gray box. 灰盒测试 | 介于黑盒和白盒之间 |
总结:实际工作中,对系统的了解越多越好。目前大多数的测试人员都是做黑盒测试,很少有做白盒测试的。因为白盒测试对软件测试人员的要求非常高,需要有很多编程经验。做.NET程序的白盒测试你要能看得懂.NET代码。做JAVA程序的测试,需要你能看懂JAVA的代码。如果你都能看懂了,你还会做测试么
从测试是手动还是自动上分类
测试名称 | 测试内容 |
Manual Test 手动测试 | 测试人员用鼠标去手动测试 (测试GUI) |
Automation 自动化测试 | 用程序测试程序 (测试API) |
对于项目来说,手动测试和自动化测试同等重要,都是保障软件质量的方法。目前大部分的项目组都是手动测试和自动化测试相结合。因为很多测试无法做成自动化,很多复杂的业务逻辑也很难自动化,所以自动化测试无法取代手动测试。
对于软件测试人员个人发展来说,做自动化测试是个挑战,也是测试人员发展的一个方向,需要测试人员学习大量的开发知识(开发的知识真是学无止境啊)。从长远角度来看,自动化测试肯定是越来越吃香的。
而手动测试比较适合刚工作不久的人,手动测试最大的缺点就是技术含量低,单调乏味,容易废人。
总的来说,手工测试胜在测试业务逻辑,而自动化测试胜在测试底层架构。
如果被测试的程序可测试性比较好,很有必要做成自动化测试。能做自动化的尽量做成自动化,下面这些情形是可以做自动化的
1、测试存储过程。例如用C#去测试存储过程
2、测试Webservies.例如:用SoupUI工具,或者C#,Java去测试Webservies。
3、界面和业务逻辑分离的系统,比如,MVC,MVP架构,或者WPF程序。可以用测试脚本去测试这些程序的API。
从测试的目的分类
功能测试
测试的范围从小到大,从内到外,从程序开发人员(单元测试)到测试人员,到一般用户Alpha/Beta测试
测试名称 | 测试内容 |
Unit Test 单元测试 | 在最低的功能/参数上验证程序的准确性,比如测试一个函数的正确性(开发人员做的) |
Functional Test 功能测试 | 验证模块的功能 (测试人员做的) |
Integration Test 集成测试 | 验证几个互相有依赖关系的模块的功能 (测试人员做的) |
Scenario Test 场景测试 | 验证几个模块是否能完成一个用户场景 (测试人员做的) |
System Test 系统测试 | 对于整个系统功能的测试 (测试人员做的) |
alpha 测试
| 软件测试人员在真实用户环境中对软件进行全面的测试 (测试人员做的) |
Beta 测试 | 真实的用户在真实的用户环境中进行的测试, 也叫公测 (最终用户做的) |
|
测试名称 | 测试内容 | Stress test 压力测试 | 验证软件在超过负载设计的情况下仍能返回正确的结果,没有崩溃 | Load test负载测试 | 测试软件在负载情况下能否正常工作 | Performance test性能测试 | 测试软件的效能,是否提供满意的服务质量 | Accessibility test | 软件辅助功能测试-测试软件是否向残疾用户提供足够的辅助功能 | Localization/Globalization | 本地化/全球化测试 | Compatibility Test | 兼容性测试 | Configuration Test | 配置测试-测试软件在各种配置下能否正常工作 | Usability Test | 可用性测试 –测试软件是否好用 | Security Test | 软件安全性测试 | 性能测试 性能测试要求测试人员熟练性能测试工具,比如QTP,LoadRunner,Jmeter。VisualStudio也提供了很多性能测试的工具。要求测试人员对低层协议非常理解和编写脚本 性能测试非常有技术含量,很有发展前途,是软件测试人员的一个职业发展方向。 安全性测试 安全性测试的内容很广,非常有难度啊。我只接触过XSS(跨站脚本攻击)和SQL注入攻击。 安全性测试非常有技术含量,我认为也是软件测试人员的一个职业发展方向 按测试的时机和作用分类 在开发软件的过程中,不少测试起着“烽火台”的作用,它们告诉我们软件开发的流程是否畅通。 测试名称 | 测试内容 | Smoke Test | “冒烟”–如果测试不通过,则不能进行下一步工作 | Build Verification Test(BVT) | 验证构建是否通过基本测试。 | Acceptance Test | 验收测试,为了全面考核某功能/特性而做的测试 | BVT测试是一种Smoke Test,指Build生成好之后,自动运行的自动化测试脚本来检查这个Build的基本功能。如果BVT测试失败了,需要开发人员马上修改,重新生成Buil 按测试测策略分类 测试名称 | 测试内容 | Regression Test 回归测试 | 对一个新的版本,重新运行以往的测试用例,看看新版本和已知的版本相比是否有退化 (regression) | Ad hoc Test 探索性测试 | 随机进行的,探索性的测试。 | Santiy Test | 粗略的测试, 只需要执行部分的测试用例 | Regression Test 回归测试: 对软件测试人员来说就是重复测试,所以回归测试最好是自动化的,否则测试人员就要一遍又一遍地重复测试。 1、开发人员做些小改动,就需要测试人员做回归测试。确保现有的功能没有被破坏 2、Bug Fix 也需要回归测试,确保新的代码修复了Fix,也确保现有的功能没有被破坏 3、项目后期,需要做一个完整回归测试,确保所有的功能都是好的 Ad hoc Test 探索性测试: 平常我最喜欢做随机测试了,抛开test case,自己按照自己的思路,随便点点。如果测试GUI,Ad hoc能发现大量的bug。 |
非功能测试
一个软件除了基本功能之外,还有很多功能之外的特性,这些叫“Quality of Service requirement”服务质量需求。没有软件的功能,这些特性都无从表现出来,因此,我们要在软件开发的适当阶段-基本功能完成后做这些测试。
测试的角色(Test)要独立出来么 ?
独立出来的测试角色怎么才能发挥作用?
有些成功人士和成功的公司号称没必要有独立的测试角色(Test),你怎么看?
最近又看到一些关于开发人员要不要负责测试的讨论。例如:
http://www.51testing.com/html/94/n-807994.html
大多数的开发团队并不需要一个独立的测试角色。即使有一个,他的所有的开发时间比上所有的测试时间应该>20:1。
我正好在写相关的教案,也来凑个热闹。
[这篇文章的一些事例来自于我曾经和现在的团队。希望这些例子不足以影响相关人物和团队的伟大形象。任何软件团队都会犯错误,伟大的团队有勇气面对自己的错误并不断改进。]
首先,明确两个概念:
软件测试(Test):运用定义好的流程,工具去验证软件能实现预先设计的功能和特性,工作的流程和结果通常是可量化的,例如,测试用例,bugs,代码覆盖率,MTTF,软件效能的参数。[注:正因为流程和结果是可明确定义的,可量化的,很多测试工作可以自动化]
软件质量保证工作(QualityAssurance):软件团队的成员为了让软件达到事先定义的质量而进行的所有活动,包括测试工作。
对于这两个术语,不同人有不同的定义,有人认为它们是互通的,在《现代软件工程》的上下文中我尽量使用上述的定义.
测试的角色(Test)要独立出来么?
回答:首先,我相信有分工是好事,软件团队中应该有独立的测试(Testing)角色。所有人都可以参与QA的工作(报告bug什么的),但是最后要有 一个角色对QA这件事负责。不但角色要独立,而且在最后软件发布的时候,必须得到此角色的签字保证(signoff)。我在微软参与的项目都是这样做的。
在开始论证之前,先引用斯密特·亚当斯的《国富论》来暖场(我没读过这本书,直接从网上抄的)。
分工理论
亚当斯认为,分工的起源是由人的才能具有自然差异。…假定个人乐于专业化及提高生产力,经由剩余产品之交换行为,促使个人增加财富,此等过程将扩大社会 生产,促进社会繁荣,并达私利与公益之调和。他列举制针业来说明。“如果他们各自独立工作,不专习一种特殊业务,那么他们不论是谁,绝对不能一日制造二十 枚针,说不定一天连一枚也制造不出来。他们不但不能制出今日由适当分工合作而制成的数量的二百四十分之一,就连这数量的四千八百分之一,恐怕也制造不出 来。”
分工促进劳动生产力的原因有三:第一,劳动者的技巧因专业而日进;第二,由一种工作转到另一种工作,通常需损失不少时间,有了分工,就可以免除这种损失;第三,许多简化劳动和缩减劳动的机械发明,只有在分工的基础上方才可能。
我们看团队形式的职业体育比赛,各个位置的分工都很明确,拿足球来说,有专注进攻的,有专注防守的,但是在我的印象中,那些伟大的前锋大多数只管一件事-进攻。亨利(ThierryHenry)参加防守么?
当然一些球赛也有没有分工的时候,原因有好几个:
事太小,几个小孩踢个半场。
无知,小孩们刚开始玩球。
人手不够,一对一打篮球,你要参与防守么?沙滩排球,两人都是全攻全守。
如果你的软件团队做的事情和上面的情况类似,那当然不必分工。你们做的很可能不是商用软件,你的软件团队大概也不用受什么软件工程规律的束缚。
任何产业产业成熟到一定阶段的时候,独立的质量保证角色是不可避免的。团队内部有QA角色,团队外部也有独立的QA角色。
拿药品和食品来做例子,除了生产厂家自己的检测之外,这些产品还要接受行业主管部门相关机构的检测和认可(药品检验,食品检验),才能上市。在出现争议的情况下,还要第三方机构来进行测试或认证。
有人也许这样建议:
这些药品都是药厂同一批工人一边制造一边测试出来的,特别有保证!不用测了,赶紧吃了吧!
也许还有人这样建议:
这个十字坡夫妻店的农家饭都是他们自己亲手做的,很可信,咱们今晚就去吃饭住一宿吧。
我们每天经常使用的电子产品,从大彩电到电影插座,也经历了很多团队内部的和外部的测试,请随手拿过任何一个电器,你会在背面看到密密麻麻的小字,其中肯定有下列标记之一:
没有这些标记的产品电子产品,市面上很少看到。
在软件和互联网产业,目前没有这些认证,相反的,倒是有“人肉认证”:
你想申请某个著名专业网站的账户或者邮箱,但是又担心这个网站对用户信息的保护程度不够。有人说,没关系的,这个网 站的创始人也用账户,CTO,总监什么的还经常发软件安全博客,账户一定是非常安全的!这里不存在独立的质量认证,只能通过人肉(创始人/CTO/总监) 来认证产品的质量。
其实这种认证未必安全…(密码门事件)(明文密码事件)(邮箱密码漏洞)
如果有第三方的认证“此网站对用户信息的保护程度是X级,我们认证它不会明文存储用户密码…”我就放心了。在第三方认证出现之前,我希望团队内部至少有独立的QA角色,来确保软件的质量。否则我是不乐意使用这些软件/服务的。
[补充一句,互联网服务的各种认证也在发展,例如verisign公司提供的各种认证。]
独立出来的质量保证角色怎么才能发挥作用?
有了独立的质保角色之后,是不是万事大吉了?未必,分工意味着一件事要分给别人去工作。让别人做事,并且依赖别人做出的结果,这会出现一些问题。
问题:既然有专人负责,那我就不用负责了!
生活中一个常见的歪理是,既然有清洁工,那我乱扔点儿垃圾算什么,这才是他们工作啊!
尽管有专人负责QA中的测试工作,但是保证质量仍然是所有成员的职责。软件团队中的一些人往往在有意无意中忘记这一 点。最常见的现象是开发人员写好一个功能之后,迫不及待地宣布成功,然后希望测试人员去发现所有问题。如果问题在发布后才被发现,开发人员会说–测试人员 怎么搞的,这种bug都没找出来!?
某项目的某功能有重要的改进,这个改进经过研究员的研究,开发人员的设计,美工的美化,两个开发人员的配合实现,项 目管理人员的督促,测试人员的测试,最后所有人都号称做好了,上线了!为此,我约了某个目标用户给他做实地展示,几天后,大家都到齐了,开始演示。开始进 行的不错,马上最重要的killerfeature就会出来了…嗳,预想的效果怎么还没出现呢?再试试,还没有?各相关人员面面相觑,大家小声说:
“我不是把那个新模块给你了么?”
“我就是照着那个接口实现的啊…”
“我不是已经交给那啥…”
“所有的bug不是已经都搞定了么…”,
会议在尴尬中胜利结束了。
来查问题的根源,这个复杂的功能由于两个模块的接口在最后没有同步,某重要的参数被忽略了,这个功能中最出彩的部分压根就不可能工作!那负责测试的角色怎么解释“所有测试用例通过,同意发布”的呢?
这还是开发人员引以自豪的“杀手级功能”(killerfeature),那其它普通的功能是什么命运呢?
回过头来,我们可以问:
·这件事真的要通过这么多环节么?
·测试人员真的知道最最关键的地方如何测试么?
·在系统上线之后,所有为这个功能感到自豪的人是否去实地测试过呢?
一个开发人员应该负责下面“开发功能”右边的几个圆圈呢?
问题:盲目信任“专业人士”扮演的角色
每个角色的水平不一样,软件的质量往往受最差的角色的影响最大。我们团队要为某软件写一段英语介绍文字,团队成员都 是通过四六级英语考试的牛人,可他们都很谦虚,说要请一个专业的人士来写不可。于是求了一个专业人士,求了好几次(专业人士很忙的),在上市之前才得到专 业的文案,于是,copy/paste几次之后,软件就向全世界发布了.
这个文案第一句就是热情洋溢的设问句:“haveyoueverthinkabout...”随后还有几处非常明显的语法错误.这个软件吸引了不少评论文章,有旁观者说,从介绍文字的几处典型中国式语法错误来看,这个软件是由在中国的某分部搞出来的…
即使有专业人士扮演各种角色,还得有专人独立地检查验证质量。
我们回头来看,可以问两个问题:
·这件事真的要专业人士来做么?
·专业人士做完之后,谁来负责测试?
问题:为了自己角色而做绩效优化
分工之后,每个角色为了自己的绩效而优化,会出现局部最优,而全局未必最优的情况。
我们团队的另一个wp7的应用也要发布,这次专业人士又出手了,写了175个英语单词的介绍,极尽溢美之事,而且找 不到明显的语法问题!这的确是一种局部最优了。但是完全没考虑到用户在小小的手机屏幕上有多少耐心读完那么多形容词和状语从句。经过简化,我们把它减少到 78个词,勉强能放进手机的两个屏幕。
我们回头来看,可以问:
·这些事真的要交给和项目无关的专业人士来做?
·当我们给专业人士介绍需求的时候,是否花了足够的时间让对方理解我们要的是什么?
·专业人士做完之后,我们要做什么样的QA?光保证没有明显的语法错就够了?
很多年前,当COBOL还是主流商用语言之一的时候,我曾在一个在软件团队里负责测试工作。职责之一,是写各种测试用例,来保证系统的代码覆盖 率到达80%以上。做过实际项目的工程师都知道,程序里很多语句是用来处理种种异常情况的,这些情况大多数情况下不会发生。但是这些语句如果没有被覆盖的 话,这个模块的覆盖率就会下降,我就达不到80%的目标。所以我花了很多时间构造各种奇怪的测试数据,把程序中的那些犄角旮旯都尽可能覆盖掉。至于这些犄 角旮旯在实际中是否会发生,对用户的影响如何,程序是否应该这样设计,我都不太关心。只要覆盖率达到80%,老子的活就干完了!
问题:画地为牢的分工
在一个长期而复杂的项目中,我要求所有新来的成员,包括外包公司的新成员,在加入团队的时候,先找到系统当前100个数据方面的问题,并用内部 工具修复。我认为这能有效地让新人了解系统的复杂性,弱点,和维护的流程。外包公司的员工很爽快地答应了,但是我们一些专家反而有不同意见。专家认为,外 包公司的人是来做测试用例的设计,所以不必做其它事情,我们期望他们一上手就能设计出高质量的测试用例,不应该给他们那些低级的手工操作任务…
理论上这都是非常有道理,但是如果这些人如果没有亲力亲为地在这个项目中做一些具体事,他们怎么能“设计”出高质量,有实际意义的测试用例呢?
有时分工导致链条过长,信息丢失。一个开发者对自己写的程序有什么潜在问题还是很有感觉的,有些问题可以用文字表述出来(如果开发人员有耐心把文字写出来的话),有些问题是一些预感…现在都交给别人测试了,那好,让他们测吧,我也懒得说了。
分工还可能会导致一个软件的灵魂被切碎分给各个"角色",每个功能都做得很卖力,但是整体就是不太行,明显看出来是费了老大的劲给强行“集成”起来的。
问题:无明确责任的分工
在我写第一本书的时候,编辑部告诉我他们会对书稿进行初读,二读,三读等流程,每个环节要花几天时间。作为出版界的外行,我理解这些都是QA的 阶段,等过了二读的时间,我就发信去问,负责二读的专业人士找到了什么问题了?得到了语焉不详的回答…一个问题都没找到?但是从编辑部的回答来看,二读不 二读,似乎没什么影响。其实这本书的小问题还很多,在出版之后,都陆陆续续被读者报告了。
有时候出于种种考虑,人们会把一些善良但是能力有限的同事安排在一些位置上,扮演一些角色,例如“二读”什么的。或者有些角色就是由一些人占据着,但是大家对这个角色也没有什么明确的要求。这是许多问题的根源。
我们对这个角色有什么可以量化,可以核查的责任要求?
我们对“一本书的质量是X”的信心是Y,刚开始组稿的时候,X的取值范围非常大(烂书…一般…好书…年度大卖…永恒经典),信心也比较低。经过每个一个QA环节,我们都应该把X的范围缩小,把信心值Y提高。
例如:二读之后,找到了20个严重问题,100个小问题,因此我们有更大的信心认为这本书是一本烂书(如果不做改进的话)。
再入:二读之后,找到了10个小问题,确信没有更严重的问题了。因此我们有更大的信心认为这本书是一本好书。
。。。
把“书”换成“软件”,“二读”换成“测试”,同样道理。
从上面举的例子可以看到,分工之后,的确会产生很多问题。但是解决的方案是什么呢?是取消分工,让开发人员顺手做测试人员的事情,顺便把项目管理,美工,市场推广,客服都干了?显然不是。
注意我们提到了“角色”,角色是有人来扮演的,如果一人扮演了“开发”的角色,又能够来扮演“测试”的独立角色,当然很好。但是条件是她要以“独立”的心态测试,而不是想:“这代码就是我写的,哪会有什么错…”而草草了事。
那么独立的测试角色怎么才能发挥最大作用?从上面的坏现象中,我们不难总结出来。其实MSF原则都讲到了。
·充分授权和信任(Empower team members)
·各司其职,对项目共同负责(Establish clear accountability and shared responsibility)
有些成功人士和成功的公司号称没必要有独立的测试角色(Test),你怎么看?
我猜想和踢足球类似,还是那几个原因:
人太牛:
不世出的天才,例如高德纳写书的时候发现排版软件不好用,就自己写了一个。也没听说他为这个软件项目请了什么独立测试人员。对了,他不读email已经很多年,有秘书帮他处理这些事-这也是一种分工!
太小:
“我写了个小类库,全部自己测试”这当然不错。
我以前的一个优秀实习生后来一个人尝试写一些UI的控件,写得很高兴的时候说了一句“我现在软件工程的原则都不管了…”为了玩得爽,不妨打破束缚,诸法皆空,挺好。
但是顺水推舟,推广到所有情况,从而得出"程序员就应该自己测试,独立测试不必了"这样的普适结论,未免有点过。
人不够:
那就自己动手多做一些事情,也挺好。就像前面提到的,一个人扮演多个角色,只要能入戏就行。
条件特殊:
近年来,软件产业百舸争流,鱼龙混杂,在海里裸泳的弄潮儿也不少,出现了种种类型的分工合作和开发模式。不在有些情况下(例如一窝蜂模式,主治医师模式),强力的dev是可以搞定很多事情。运用之妙,存乎一心。
引起网上讨论的两篇文章在这里:
http://www.51testing.com/html/94/n-807994.html
http://www.quora.com/Is-it-true-that-Facebook-has-no-testers
其中打分最高的回答来自前雇员(Evan Priestley),他总结了Facebook这个公司为什么貌似没有全职测试人员:
a、全公司人员经常使用自己的软件产品!(如果你开发的软件是航天飞行某控制模块,你怎么能经常使用呢?)
b、使用log来分析问题可能出在哪里。(我们的一些程序员写程序都没有log,那大家看什么呢?)
c、利用用户的反馈和实时状态分析(比较过去一小时和上周同一时间的数据来判断是否有bug)
d、应用开发商给Facebook报bug。(开发商其实比较不爽,但是FB有时就是无预警地修改API,你除了赶紧报bug,还能怎么着?)
e、很多人自愿给Facebook报bug,这位贴主自称每月给他的前雇主报13,000个问题.(没错,是每月一万三千个!)
f、最后这位前雇员还加了一句:还有一个原因是,Facebook大体上也不需要搞出太高水平的软件。
当你的公司也能有a)到e)这样的文化,流程,开发商和给力的前员工,而且你的软件“大体上也不要太高质量”你的确不需要什么全职测试人员!
微软是怎么做的呢?
就像MSF原则讲的那样,有分工,有合作。
微软开发测试主要有三种角色:
·SDE: Software Design Engineer,简称dev。
·SDE/T: Software Design Engineer in Test,也写代码,但是重点在测试。
·STE: Software Test Engineer.
对于如何更有效地开发互联网应用,微软很多团队都做过不少探索。例如一些团队尝试把SDE和SDE/T合成一体。每个人都负责开发/测试/发布这一整套流程,根据我的观察,有好处,也有额外的成本。
结束
一位网友说得好:分工是社会和行业进化的结果。开发和测试其实是软件工程的两分支。不同的软件/服务需要不同方式和程度的测试。独立专业的测试等同于第三方代表客户对产品认证。
拉拉扯扯这么多话,团队/个人/角色到底应该怎么办呢?我认为,
·在初始阶段(新项目,团队进入一个新领域,人员刚进入一个项目),每个团队成员都要尽量打通各个环节,多负责,把所有事情都搞懂,培养通才。
·当项目/产业发展到一定阶段(进入阵地战的时候), 要大力提倡分工合作, 培养专才。
·把自己项目的架构和流程做好, 让所有人都能比较容易地进行 Quality Assurance 的工作。
·培养“大家都要做QA, 专人负责量化的Test, 有条件多做测试自动化”的文化。
·要明白自己项目的特点, 人员的特点, 产业的特点。避免照搬别人的做法。不要听说某某伟大的系统的开发/测试比例是多少, 就哭着喊着也要同样的比例…
思考题:
分工之后, 每人负责一小块东西, 怎么能体现出个人的独特而巨大的价值呢? 例如, 你刚到一个出版社, 领导让你做 “二读” 这份工作; 或者你刚到一个软件公司, 领导让你做 “测试” 这份工作, 你怎么能展现出你独特的价值呢?
你在某团队做测试,兢兢业业已经三年, 今天大家传说公司认为开发人员应该做测试, 所以不需要专职的测试人员了。 你怎么想? 你能否做到:
明确列出过去三年你对团队的贡献? 除了“认真执行测试用例”之外, 你对团队整体的“质量保证”还有什么独特的贡献?
有理有据地说明, 没有专职测试人员, 项目会有什么风险?
这三年的经历在你的简历怎么写出来? 你比三年前更容易找到工作么?
这三点搞不清楚的, 还是改行吧。