Translate:Scrum中QA角色经验分享

Scrum是软件开发的敏捷方法。它以2到4周为一个迭代开发出有价值的商业功能。Scrum团队有两个明显特征:他们是多面手(例如:他们具备完成工作所必须的所有技能);他们是自管理的(例如:团队不断探索如何把工作做的最好的方法)。通过过去两年在Scrum团队中近2年的QA角色的不断实践,认识到Scrum中的QA不仅仅是编写测试用例和汇报缺陷那么简单。

对比传统瀑布模型的项目中的同步活动,Scrum期望开发活动根据实际需要的顺序来执行,例如异步。这点有悖传统,让许多客户、开发和业务关系人等新手产生疑惑 “如何在代码还没有完成之前进行有效的测试?” 本文重点解释了QA如何执行敏捷测试以及Scrum团队中QA角色的重要性。我将通过本文分享在我对Scrum团队中QA角色及职责的认识。

不仅是编写测试用例

传统瀑布模型的项目中,QA介入的时机往往是在代码全部完成后的项目收尾阶段。这些项目中,QA拿到一份需求文档和已经完成的代码,然后开始编写和执行测试用例以检查应用程序是否符合需求文档。然而,Scrum中的QA角色不再仅仅是执行测试用例和汇报缺陷。

在Scrum团队中,QA分析师和其他团队成员一起参与或担当大量职责。他们从项目一开始就介入,并且与业务分析者和开发者密切联系。在Scrum中,QA不是一个单独的测试应用程序的团队。取而代之的是,Scrum团队是一个业务分析师、开发者、QA一起协同工作的综合团队。除了编写用例,QA还帮助产品负责人(PO)编写接受用例,相当于承担产品负责人代理的角色。当产品负责人没有时间时,QA作为代理保持团队持续前进。QA和产品负责人通过提出问题和质疑假设进行互动交流,最终澄清业务需求。

参加评估用户故事(Story)

QA分析师一般很擅长根据用户需求创建测试用例场景。在识别和捕捉复杂和否定的用例上也很卓越。事实上,在这点上,QA往往比开发做的好,因为开发往往关注用户故事的好的方面。在版本和周期计划会议中评估用户故事时邀请QA参与能让团队不再仅仅思考好的方面,有利于产生一个综合好坏情况的客观真实的评估。评估是一个很难的事情,让所有人都参与评估是很好的实践。

有利于保持视角和目标明确

当团队执行测试和其他稳定产品的活动时,QA需要掌控计划、组织或让整个团队投入到测试工作中,并且像Scrum Master(SM)那样保持成员处于积极状态。很少有开发者喜欢做测试任务。QA需要和Scrum Master一起让测试对整个测试团队可见且目标明确。从而保持开发者或其他成员的积极性。有时一些测试场景的构建需要开发或其他团队成员的帮助,这样容易创新。力争让测试活动有趣,例如用刺激的测试场景、出人意料的测试数据和带有娱乐意味的竞争。总之,做任何事情,只要有助于团队乐于加入测试工作即可。

与客户和开发者紧密合作

QA的主要职责之一是将他们的测试结果反馈给产品负责人或收集他们的反馈。QA和产品负责人紧密合作,帮助他们制定详细的用户故事验收标准。随着团队在每个迭代中的深入了解,QA也可以帮助产品负责人修改或增强用户故事以更好地反映真实的需求。

偶尔,QA分析师还充当产品负责人代理。这种情况下,QA和开发者将坐在一起,作为一个团队一起工作以提高产品质量。QA可以和开发者结对来写单元测试,讨论验收标准。合作的工作越多,需求也越清楚。一起工作带来的清晰需求将减少编码过程中经常遇到的各种问题或疑惑,从而给有效提高开发效率、节约开发和QA的时间。

根据团队每个人的需求和实际情况,整个团队将成为一体,都会协助测试。这样的实践平衡了团队和工作完成必须的共同职责,早期测试反馈和持续增长的质量下,它将使项目进展更快。

提供快速反馈

传统瀑布模型团队不断重复的“构建-测试-修复”周期徒增了大量额外工作量,浪费了大量时间。在Scrum中,QA和开发者在整个项目中一起工作,让活动变得更简单。在开发过程中,开发者能直接咨询QA验收标准或从用户视角任何功能上的期待行为。这让测试和缺陷修复更简单。

自动化回归测试

自动化测试常被誉为测试者最好的朋友,因为它可重复执行且执行一致,能得到更好的软件功能的测试覆盖率。在2到4周一个迭代的Scrum项目中这点尤为正确。因为QA大体都没有太多时间去测试应用程序。在2周的迭代中,QA必须完成迭代中所有新功能的功能点测试的同时还要完成对先前实现功能的测试。正因如此,这种职责提高了每个迭代中使用可用的自动化实践以减少QA压力的重要性。

当团队执行持续集成时,自动化测试在快速反馈上大有用途。每发布一个软件新版本,可以执行自动化测试并快速提供反馈以反映是否新老功能都正常工作。而没有自动化测试,就必须手工执行所有的测试,不仅单调,而且容易犯错。自动化测试能更早的发现缺陷,让QA有更多时间去探索新功能的一些特殊用例。通过自动化测试,QA可以更快更有效地完成测试工作。

参与发布准备演示

在每个迭代结束时,团队需要召开一个迭代审阅会议来向项目责任人和其他有兴趣的关系人展示这个迭代完成的用户故事。迭代审阅会议是团队中的“良药”,可以有效激发他们去尽可能完成更多用户故事。

在2到4周的小迭代中,为了让用户故事按时完成,团队中的每个人都必须沉浸在自己的工作。开发者关注实现用户故事和修复缺陷,QA关注用例编写、澄清产品责任人的问题、自动化之前迭代的测试。较短的迭代周期意味着开发没有多少时间去获知用户故事要求的全部功能。这样,开发一般要询问QA以更好的理解用户故事。因为QA知道完整的功能及每个需求和验收标准。在迭代审阅会议上,让QA演示项目和解答业务上的问题是很好的实践。这也让开发者更专注于处理技术层面的问题。

分析用户需求

QA是Scrum团队中产品负责人代理。他们擅长从用户视角理解业务需求。因为他们经常被问到用户如何使用项目。QA根据他们的测试经验给产品负责人提供反馈,帮助他们更好的从用户视角理解项目。

完善“完成定义”

对于敏捷团队,清晰的完成定义(DOD)是很重要的。“完成定义”是团队定义完成标准的简单列表,是在用户故事认定为完成必须要完成的事情。完成定义一般包括完成代码、执行功能和回归测试、获得产品负责人的认可。一个简单的完成定义可能包括如下项目:

  1. 代码完成
  2. 单元测试完成
  3. 功能和UI测试完成
  4. 产品负责人认可

定义“完成定义” 不是QA一个人的责任,QA的责任往往在于监管团队完成定义和每个完成的用户故事必须满足“完成定义”的基线要求。一个高效的敏捷团队在启动每个用户故事前都要审阅“完成定义”从而使团队每个人都了解目标。“完成定义”不是一层不变的,可能会根据Scrum的需要不断演变。“完成定义”既可以是迭代级的也可以是发布级的。

用测试策略规范测试

由于Scrum团队中没有测试领导甚至测试专家。构建测试计划或执行测试策略就存在问题。Scrum认为需要准备足够的文档去支持团队随时提出的需求。正因为此,需要准备足够的高层次测试策略的文档和计划来指导团队。因为没有QA领导在团队中,QA一般自己来制定测试策略。

测试者和分析者角色融合

测试者和分析者角色融合在敏捷团队中很常见,业务分析师的角色一般是负责创建和维护迭代和产品的Backlog、从业务角度分析用户故事、根据产品负责人要求划分用户故事优先级。而QA角色一般负责为每个故事定义或完善验收标准,确保之前完成的功能没有老的问题。QA测试每个用户故事,从终端用户视角验证定义的验收标准是否已经达到,他们也根据业务来分析用户故事。所以QA和业务分析师的角色责任、必备技能、总体目标有很多重合地方。

一般,在项目开始之时,敏捷团队从产品负责人那里拿到用户故事和提前定义的项目范围。在敏捷模式下,鼓励团队成员提出改善终端用户体验的新功能或改变已有功能,也鼓励团队一旦发现技术依赖或发现换一种实现将更有效而改变backlog中用户故事优先级和顺序。无论是定义需求、分析用户故事、定义和澄清验收标准、编写接受性验证用例或和用户紧密合作,对于小的团队,测试者和分析者的角色融为一体有很多优点,但也存在一些缺点,最大的顾虑是没有测试者或分析者能够投入过多精力来完全尽责。

结论

除了编写用例和汇报缺陷,QA在Scrum团队中承担更多的职责。他们是团队的重要组成部分,并且从项目一开始就参与其中。

过去两年在Scrum团队当QA分析师让我有了一个非常棒的体验,同时也获得了很多学习机会。我担当了很多不同的角色和职责,包括QA分析师、产品责任人代理、帮助开发写单元测试、确保团队的质量意识和跟踪问题和软件缺陷。总之,这些体验让我获得了很多 不错的技能,同时让我学习了如何做好不同的角色。更重要的是它告诉我如何去问问题而不再是仅仅遵循文档,也教会了我去做任何有助团队成功的事情。

关于作者

Priyanka Hasija:是Xebia IT Architects的一名测试咨询师,从事IT业已两年。期间,她对敏捷原则有了深刻理解并有机会在一些敏捷项目中成功应用。在Xebia工作期间,Priyanka不仅积累了手工测试经验,也积累了采用Jmeter、Selenium等工具进行自动化测试的经验。她是一名热情的博主,曾写下不少测试文章,主题涉及Jmeter、Selenium、SoapUI和探索性测试。另外,她在2011的Agile Tour-Hyderabad会议中参与主持一个主题。

查看英文原文My Experience as a QA in Scrum

Open source: common-remote-pool

Apache common object pool can help user to manager resource, but if use it , you will find you can only share resources in one machine,not between multi-process or multi-machine. So we use the object pool to constructor one web service to provide distributed pool to share resources between multiple machines. The web common remote pool provide one default implement which can add any json string to pool and borrow json resource from it.What’s more, the resource object factory’s class can be uploaded into the web service. In short, the project is restful style web object pool for global access.

http://code.google.com/p/common-remote-pool/

How to initial it

1. mvn tomcat7:run to start the webservice;

2. If you need define your implement, you should upload your resource factory class , if you have no need, omit this step.

How to use it

http request style

  • borrow the object from pool
 	Request:
 	        GET http://localhost:8080/common-remote-pool/service/object/borrow

 

Response: has resource response code:200 response body: json example: {“domain”:”10.224.64.225″,”user”:”6731″}

Response: no resource response code:404

 

  • return resource to pool
 	Request:
 		POST http://localhost:8080/common-remote-pool/service/object/return                 
                body: json
 		example:{"domain":"10.224.64.225","user":"6731"}

 

Response: response code:204

  • get borrowed resouce number
 	Request:
 		GET http://localhost:8080/common-remote-pool/service/object/active

 

Response: response code:200 response body: number

  • add resource to pool
 	Request:
 		POST http://localhost:8080/common-remote-pool/service/object/add

 

body: json example: {“domain”:”10.224.64.225″,”user”:”6731″} or [{“domain”:”10.224.64.225″,”user”:”6731″},{“domain”:”10.224.64.13″,”user”:”6732″}]

Response: response code:200

  • flush all resource
 	Request:
 		GET http://localhost:8080/common-remote-pool/service/object/drain

 

Response: response code:200

  • get idle resource number
 	Request:
 		GET http://localhost:8080/common-remote-pool/service/object/idle

 

Response: response code:200 response body: number

  • get pools resource amount info
 	Request:
 		GET http://localhost:8080/common-remote-pool/service/object/idle

 

Response: response code:200 response body: {“idleNumber”:3,”borrowedNumber”:3,”totalNumber”:6}

  • query current enabled resource factory
 	Request:
 		GET http://localhost:8080/common-remote-pool/service/object/getFactory

 

Response: response code:200 response content: such as com.googlecode.common.remote.pool.resource.DefaultResourceFactory

  • list all resource in pool
 	Request:
 		GET http://localhost:8080/common-remote-pool/service/object/list

 

Response: response code:200 response content: “no any resource” or {file=1.txt, owner=jiafu}:2014-04-28 14:29:34

client style

The client’s code amount is so small that you can copy the code directly.

 

        com.googlecode.common.remote.pool.client.CommonRemotePoolClient.CommonRemotePoolClient(String)
        com.googlecode.common.remote.pool.client.CommonRemotePoolClient.borrowObject(Class<T>)
        com.googlecode.common.remote.pool.client.CommonRemotePoolClient.returnObject(Object)
        com.googlecode.common.remote.pool.client.CommonRemotePoolClient.addObject(Object...)

Dependence:

        <dependency>
          <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-jackson-provider</artifactId>
          <version>2.3.1.GA</version>
        </dependency>
        <dependency>
          <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-client</artifactId>
          <version>3.0.2.Final</version>
        </dependency>

How to manage resource

you can manage resource by default implement.