无法登录的用户

0

“有用户在手机端认证失败。”

ins项目的微信群里的客户又遇到了新的问题。

“不像是网络问题,感觉是后端服务的问题。”

“用其他手机试试呢?”大鹏眉头皱了一下。

自从ins项目上线以后,团队其他成员都纷纷下了项目,只留下他这个项目经理留在一线解决问题。登录这块总是出现问题,上次就出现过一次,不过上次是机房网络原因,而这次貌似并不是。

“她用我的手机是可以登录的。”客户说。

“看来这个问题跟设备有关。”大鹏想。

这时客户发来了报错的手机截图,可以看到屏幕中间有一个提示框,上面显示“认证失败”4个字。

“志豪,帮忙看看什么情况下会出现这个错误。”大鹏呼唤了开发志豪。志豪是ins项目的前端开发,登录功能就是他实现的。

“这个错误是我们报出来的,应该是没有认证通过。”志豪已经上了新的项目,不过依然抽空支持着。“我们的前端登录组件会拿到办公App给我们的参数data和token,然后发送到认证服务进行认证,认证失败了就会报这个错。”

ins项目的手机端应用是一个Web应用。用户登录办公App后点击ins的图标,办公App就会启动WebView,打开ins手机端的URL,并在URL上带上data和token参数。data包含了用户信息,token用于对data的校验。这个URL对应的就是上文提到的前端登录组件,这个组件会把data和token发送给后端的认证服务做认证,认证服务来解析data获取用户信息并校验token。如果这一步出错了就会返回认证失败响应,而前端就会提示“认证失败”。

┌─────┐  /login?data=xxx&token=yyy   ┌───────┐  /auth?data=xxx&token=yyy   ┌──────┐
│ App │ ───────────────────────────> │ Login │ ──────────────────────────> │ Auth │
└─────┘                              └───────┘                             └──────┘

“认证服务什么情况下会返回错误呢?”大鹏追问道。

“这个要看认证服务的日志了,看看到底哪里出了问题。”志豪回答道。现在掌握的信息太少,还无法作出判断。

“下午要去机房看看了。”大鹏喃喃道。

1

在机房里大鹏看到的认证服务的日志。认证服务的日志显示,AuthService.convertHexToByte方法报错了。token应该是一段类似于34ac的十六进制的字符串,但是认证服务拿到的token却是M5开头的,这明显不是十六进制,所以在验证的时候报错了。

“看起来是有些办公App的token格式不对。”志豪猜测。

“应该和设备有关系,跟人无关。同一个人使用自己的设备就不能登录,而使用别人的手机就可以登录。”大鹏补充道。

“不同设备之间会有什么区别呢?”志豪问道。“是不是版本问题?让他们把办公App都升级到最新版本呢?”

“不能登录的设备确认是最新版本。不是版本的问题。”大鹏回答道。

“我们需要更多输入,需要熟悉办公App认证逻辑的人。”志豪提出需要外部支持。

大鹏把隔壁项目的后端TL大宝拉进了群。“大宝,ins项目移动端应用有的用户用别人的手机就可以登录,但是用自己的手机却无法登录。”隔壁项目也有移动端,也和办公App进行了集成。“你能想到大概是什么原因吗?”大鹏在微信群里贴出了convertHexToByte方法的代码。

“我这边后端确实有这个代码。”大宝看到了代码,“不过我们没有遇到无法登录的问题。”

问了一圈但没有人遇到类似的问题,所以很可能是ins项目自身的问题。大鹏又回到了刚才的推测:不同客户端的token格式不对,既然这样,是不是把token的验证这个步骤去掉,用户就可以正常登录了?

“既然验证token的时候报错了,那我去问问客户,是不是可以把token的校验逻辑去掉。去掉以后,虽然有一定安全问题,但应该可以解决用户不能登录的问题。”大鹏在微信群里说道。

“这样不好吧。”志豪说。“问题的原因并没有找到,为什么认证服务拿到的token不是预期的十六进制字符串的原因还不清楚,所以去掉token的校验并不一定就可以登录了。而且就算能登录,还会带来安全性问题,并不是一个正确的方法。”

经过一番讨论,大鹏觉得志豪说的有道理,打消了去掉校验的想法。不过问题仍然没有解决,所以他们商量了一下,决定问一下ins项目的TL张伟。张伟现在已经上了别的项目,项目刚启动,他比较忙,晚上才有时间,所以他们约在了晚上8点开个视频会议。

这个问题引起了志豪的好奇心,登录功能也是反复测试过的,怎么会一上线就遇到了问题呢?为了搞清楚原因,也为了项目顺利验收,志豪决定晚上留下来研究下这个问题。

大鹏也利用这段时间又研究一下日志。他发现认证服务收到的token貌似由两部分组成,前半部分由M5开头,显然不是十六进制,但后半部分是十六进制字符串,两部分之间由一个+符号连接。

“看来后半部分才是正确的token。”他把这个猜测告诉了志豪,“认证服务收到请求的时候token已经错了。”

“嗯,看来是这样。”志豪说道。“而且这个加号貌似有问题。”

2

晚上大鹏来到办公室,和志豪一起跟张伟开了视频会议。张伟把登录的流程完整的说明了一遍,就匆匆下线了。志豪依据张伟的讲述画出了完整的时序图:

​ 可以看到前端登录组件和认证服务之间还有一个API Gateway。

既然发给认证服务的HTTP请求就是错的,那么问题应该出现在认证服务之前的前端登录组件或者API Gateway。大鹏又查看了前端登录组件的日志,日志显示在办公App调用前端登录组件的URL里,data和token是正确的。data中包含的%2B引起了大鹏的注意,%2B之前的部分就是认证服务收到的data,而%2B后面的部分和正确token一起,被当作token传给了认证服务。

“认证服务收到的错误的token,可以分成三个部分:data的%2B之后的部分,这个加号,还有正确的token。”大鹏把这个发现告诉了志豪。“感觉我们越来越接近真相了。” 志豪点点头。“现在问题已经逐渐明确,就是有个倒霉孩子把data的后半部分混入了token。”

还可以通过搜索引擎和阅读代码获取更多信息。志豪暂时想不到合适的搜索关键字,所以他选择先从代码中收集更多信息。

由于前端登录组件收到的信息是对的,而认证服务收到的信息是错的,志豪结合时序图判断问题应该只会出现在以下3个地方:

  • 前端登录组件获取参数并调用API Gateway时
  • API Gateway解析请求时
  • API Gateway调用认证服务时

因为对于前端登录组件的代码还是很有信心的,所以志豪决定从后往前排查问题。

志豪首先检查了API Gateway调用认证服务的代码:

    @GetMapping("/authentications")
    AuthInfo getAuthInfoByDataAndToken(@RequestParam("data") String data,
                                       @RequestParam("token") String token);

由于使用了Feign,代码逻辑也非常简单,看上去没什么可能会造成data的部分混token里。

接下来检查API Gateway解析请求的代码。前端登录组件拿到data和token后,会把他俩传给API Gateway去做认证。具体的方式是把data和token放到HTTP Header里:

X-User-Login: APP $data $token

API Gateway在接收到请求后,取到HTTP Header里的值,把APP前缀去掉,然后找到第一个空格,空格前的部分保存为data,后面的部分保存为token。代码如下:

    private String[] extractAndDecodeHeader(String loginHeaderValue) {
        final String dataAndToken = loginHeaderValue.substring(APP_PREFIX.length());
        int spaceIndex = dataAndToken.indexOf(" ");
        if (spaceIndex == -1) {
            throw new BadCredentialsException();
        }
        return new String[]{dataAndToken.substring(0, spaceIndex), dataAndToken.substring(spaceIndex + 1)};
    }

这段代码有测试覆盖,CI也是过的。志豪思考了一下,得出结论:当请求正确时,这部分代码也不会出现问题;但是如果请求里的data包含了空格,那么data的后半部分就会混在token里。志豪笑了笑,他感觉抓到了线索。

data是Base64编码过的字符串,而token是十六进制对应的字符串。Base64编码后内容只会包含大小写字母、数字和+/这64个字符,十六进制字符串只会包含数字和字母A-F,所以这两者都不会包含空格。

目标继续缩小到了前端登录组件里。相关的代码如下:

import URLSearchParams from 'url-search-params';

const searchParams = new URLSearchParams(search);
const [data, token] = [ searchParams.get('data'), searchParams.get('token') ];

...

return `APP ${data} ${token}`;

这里用到的url-search-params是一个npm包。这段代码分别取到data和token参数,然后用空格作为分隔符,和APP前缀拼在一起返回。

如果URLSearchParams把%2B经过URL解码成空格,那么${data} ${token}就是$data的前半部分$data的后半部分$token,所以API Gateway就会把$data的前半部分当作data$data的后半部分$token当作token传给认证服务,那么认证服务就会在校验token的时候报错,这正好和问题出现时的现象一致。而且也解释了为什么认证服务拿到的错误的token里会包含加号。

如果一个参数要放到URL的query string里,那么这个参数需要经过URL编码。比如在谷歌搜索hello world,结果页的URL则是https://www.google.com/search?q=hello+world。空格会被编码成+,而+会被编码成%2B。相对的,在获取到URL后,需要经过URL解码才能拿到正确的参数。URLSearchParams就是一个可以用来进行URL解码的工具。在日志里看到一般都是URL,所以参数都是编码过的。

看上去一步步接近真相了,志豪有些兴奋。他写了一段简单的测试代码:new URLSearchParams('q=%2B').get('q')。如果结果为+,则是正确的,不会产生问题;如果结果是空格,就是错误的,就会造成无法登录的问题,就意味着原因找到了。

志豪在Node.js环境测试,结果发现返回的是+。“嗯,是正确的。”志豪自言自语道。“还有其他情况吗?对了,url-search-paramsURLSearchParams API的polyfill,所以如果浏览器原生支持URLSearchParams API,那就会使用原生的URLSearchParams API,而不是npm包。”

polyfill允许Web开发人员使用某HTML API,即使浏览器并不支持它。通常ployfill先检查浏览器是否支持了该API,如果支持了则直接使用,否则使用ployfill的实现。

“是不是在原生支持URLSearchParams API的浏览器里有问题?”志豪又打开了Chrome开发者工具的控制台面板,在里面进行了测试。结果也是+。这个结果说明,Chrome已经原生支持了URLSearchParams API,而且原生的URLSearchParams API也是正确的。

志豪摇了摇头,问题仍未确认。

3

“到底在什么情况下才会出现问题这个呢?”志豪思考着。

“这个问题跟设备有关。”大鹏也突然想到了什么。“我去问问无法登录的设备的型号。”

大鹏赶快给客户打了电话,得到的回复是,两部出问题的手机都是iPhone,而且iOS版本分别是10.3.2和10.3.3。

志豪感到眼前一亮:“莫非是iOS 10.3有问题?如果这个假设成立,那么iOS 10.3应该用的不是polyfill,所以它应该是原生支持URLSearchParams API的。”志豪想着。

志豪搜索了一下,找到了MDN的URLSearchParams文档(历史版本),发现浏览器兼容性部分里显示Safari Mobile并不支持URLSearchParams API。

“难道这个推理是错的?”逐渐清晰的真相又模糊起来。“不过还是用iOS模拟器试一下吧。”志豪打开了Xcode,发现只安装了默认的iOS 11模拟器,于是在设置里找到了iOS 10.3.1模拟器,开始下载。

趁着下载的时间,志豪测试了iOS 11,结果同样是+。“看来MDN上写错了,还想骗我。”志豪嘴角翘了起来。

经过十几分钟等待,iOS 10.3.1模拟器终于下载好了。志豪速度测试了一下。 结果是空格!

“终于把你这个倒霉孩子找出来了!”志豪情不自禁的欢呼起来。“终于找到你了。”

4

志豪不放心的又查了一下兼容性,发现在MDN中文版的URLSearchParamsW3cubeDocs赫然显示Safari Mobile从10.3开始原生支持URLSearchParams API。嗯,果然是MDN出错了。

iOS从10.3开始原生支持URLSearchParams API,但也许因为是第一次支持,这个版本有点问题,随后的iOS 11修复了这个问题。

“我刚用iOS 10.2试了一下,返回的是加号啊。”大鹏在一旁也没有闲着。

“那就对了,10.2并不原生支持URLSearchParams API,用的是polyfill,所以也没有问题。”志豪利用刚找到的真相完美的解释了这个问题。

5

不知不觉已经快11点了,志豪和大鹏准备回家,却发现6部电梯都停止了服务,两个人只好爬楼梯。

“没想到浓眉大眼的iOS也有这种坑。”志豪一边下楼一边感慨道。

“是啊,让我们好找啊。”大鹏一边喘气一边说。“话说这个问题有办法避免吗?”

“之前可能还真没办法预料到。如果URLSearchParams API文档里能说明iOS 10.3的问题就好了,但我刚才搜索了一圈,并没有发现有人在讨论这个问题。”志豪回想着。“应该做点什么,不要让它再祸害其他人了。”

“写篇博客?”大鹏提议。

“不仅如此,还应该把这个问题更新到MDN上。”志豪说。“以后的人也许就可以避开这个坑了。”

(完)


更多精彩洞见,请关注微信公众号:思特沃克

Share

识别领域事件

随着微服务架构的兴起,微服务设计与拆分的的最佳实践DDD已然成为大家讨论与实践的热点,整个行业都在探索如何用DDD建模来实现微服务设计。事件风暴作为最接地气的实践,在不同的项目中野蛮生长,不断演进,今天已经渐渐成熟。作为事件风暴的灵魂——领域事件,值得我们投入更多的精力去设计与打磨。

领域事件是用特定方式(已发生的时态)表达发生在问题域中的重要事情,是领域通用语言(UL)的一部分。为了方便理解这个概念,这里举一个宠物的例子:如果做为宠物主人,你的问题域是如何养好一只猫,那么是不是已经打了疫苗,给宠物饲喂食物等将成为你关注的事情,领域事件会有:疫苗已注射,猫粮已饲喂等。如果你是宠物医生,问题域是如何治好宠物的病,关注的事情是宠物的身体构成,准确的诊断宠物病情,对症下药,领域事件会有:病情已确诊,药方已开治。虽说二者关注的都是宠物,在不同的问题域下领域事件是不同的。

DDD的提出者和圈内的大师先后提到领域事件在领域建模中的价值,前沿实践者们已经开始应用领域事件来表达业务全景。在DDD建模过程中,以领域事件为线索逐步得到领域模型已经成为了主流的实践,即:事件风暴。

事件风暴是以更专注的方式发现与提取领域事件,并将以领域事件为中心的概念模型逐渐演化成以聚合为中心的领域模型,以快速可落地的方式实现了DDD建模。

对于高质量的事件风暴,首先要解决识别领域事件的问题,理想的情况下领域专家和研发团队一起参加事件风暴,从业务的视角去分析涉众关心的领域事件,短时间内高度可视化交流,集中思考,快速发散收敛形成所有参与者一致认可的领域事件集合。我在多个项目上实现事件风暴后,总结了一些坑和应对办法,供大家参考:

1. 组织没有领域专家

对问题域有深刻见解的主题专家称为领域专家,在大多数组织中没有这个角色,当DDD建模需要领域专家支持时,组织往往找业务部门的业务人员,BA,产品经理或在这个领域有多年开发经验的DEV来充当。

这些一线业务人员和开发团队都清楚有什么功能,但往往不清楚为什么有这些功能。举个例子:如果我们的问题是打开一瓶红酒,你去调研每天都会打开酒瓶的waiter, 给你的答案是:开瓶器。但换做领域专家的视角来看,会回归问题的本质,如果我们希望打开酒瓶,需要把瓶塞移除,移除瓶塞的方式有多种,包括推,撬与拉拽,对于拉拽可能基于吸力或螺旋拉拽,下面右图的开瓶器只不过是螺旋拉拽的一种解决方案。领域专家应该对问题域及其中的各种可行方案有更深入的理解。

在辅导团队的过程中,为了弥补这部分视角的缺失,往往会在事件风暴之前,组织业务愿景和场景分析,与被指派的业务干系人对齐业务愿景,一起分析业务场景背后的问题域,找到问题域的本质后再展开事件风暴。

2. 面向复杂业务系统的事件风暴

高效事件风暴的规模推荐5-8人,超过8人的事件风暴就会出现讨论时间过长,部分成员参与度不高,业务之间的相关度弱等问题。在一个以支付中台为主题的事件风暴中,对于电商商城的支付与理财产品的支付相关性就很弱,各自关心的是自己的业务,让这两组人在一起讨论,在得到同样产出的情况下,会花费双倍的时间。

在处理复杂问题时,一个有效又好用的方法就是分而治之,对于复杂系统的事件风暴也是同样如此。在业务干系人达到一定规模后,将业务干系人分成多组,组织多轮事件风暴,迭代演进领域模型也是一种不错的选择。

分组的基本原则应以业务线为线索,如果目标系统的业务干系人在同一个业务主线上,每一组人代表业务主线上的一个环节 (如下图),这种情况按照业务结点进行分组即可。对于业务相对简单的结点,可以将其与相临结点合并组织事件风暴。

当目标系统是多条业务线上的某几个公共结点,一般业务中台会出现这种情况,如支付中台要为不同的业务部门(保险,商城,还信用卡等)提供支付服务,如下图中的虚线部分。这类业务往往结点之间的边界并没有那么清楚,系统做什么与不做什么只有在梳理完整条业务线才能确认下来,这种情况按每条业务线分组展开事件风暴,然后针对多组产出结果进行统一业务概念抽象,建立系统边界内的统一事件流。

3. 业务代表或领域专家用自己的语言表达业务

事件风暴的第一个环节是让参与者头脑风暴,各自找出业务干系人关注的领域事件,对于业务干系人来讲,往往不适应把自己理解的业务按领域事件的方式表达出来,他们看到一串领域事件,也不觉得这种表达方式比传统方式直观,在这种情况下,我们就需要考虑如何引导业务共同输出领域事件。留心领域专家在表达需求过程中的一些模式:

1. 当…
2. 如果发生…
3. 当…的时候请通知我
4. 发生…时

通过模式中的关键字转换成领域事件,按时间顺序排序后,基于商业模式与价值定位与领域专家讨论领域事件,以统一的语言与统一的业务视角修正并验证领域事件。高质量的领域事件定义自然是清楚的,是可以找到问题域中的某个actor是关注它的,通过讲述领域事件是可以体现商业价值的。

4. 事件风暴可能识别不出来所有领域事件

通过事件风暴可以快速把整个问题域主线梳理出来,这样的产出是相当的高效和有价值,但对于正在尝试用事件风暴成果代替传统交付物的组织,往往会质疑事件风暴是否可以发现所有领域事件。

试考虑一个投资者,为一座摩天大楼的建造提供资金,投资者未必对建造过程的细节感兴趣,材料的选择及各种工程细节会议对于建造者来说是很重要的活动,对于投资者来讲,感兴趣的是良好的投资回报,保护投资免受风险,较为务实的投资者会设立明确的里程碑,每个里程碑通过后再做下一次注资。例如,在项目开始时,提供适量资金进行建筑设计工作。当建造事宜被批准时,再为项目提供较多的资金以进行设计工作。在设计通过评审通过后,才拔给更大量的资金,以便建造者破土动工。梳理得到事件如下:

系统建模同理,我们不关注所有事件,仅关注对干系人解决特定问题有价值的事件,并且这个特定问题应该已经在项目初期,业务愿景梳理的过程中在组织内达成了共识,就像上述投资者关注的问题一样清楚,在业务场景梳理与事件风暴的过程中,不断还原具体过程,以确保识别出的活动或事件真正可以解决业务问题。所以在事件风暴的过程中,并不需要担心是不是找出所有领域事件,只要真正解决了业务问题就好了。

另外,当开始采用新的方法论时,实践过程与角度都有差别,旧有体系的交付物不适用是常有的情况,重点关注的新的方法会不会以更简洁的方式解决实际问题。在存疑的风险处,活学活用新方法的交付物能够让组织更顺利的落地,当然必要的开发过程与交付物改进也是需要的,即可以更高效的完成设计工作,也能够让团队更专注在问题上。

总结

有人说微服务的设计与拆分是一门艺术,经验性的成份占了很大比重。当我们准备基于经验来做微服务的设计决策时,结合业务愿景,找出问题域内所有业务干系人真正关心的领域事件,展开完整的事件风暴,循序渐进的让场景变得更加具体,让经验与艺术在生动的问题域之中得到最大的发挥。

另一方面,有效地识别领域事件,既统一了语言,又助力在模型中体现出业务价值部分,为设计关注业务价值的领域模型打下了坚实的基础。


更多精彩洞见,请关注微信公众号:思特沃克

Share

数字化时代的软件测试

数字经济高速推动着一个无情的市场,所有利益相关者通过设备和应用网络进行交互,一个微观时刻足以让市场领导者摆脱优雅。 这种对速度的痴迷能否淡化质量定性方法?《World Quality Report 2017-1028》带你来一探究竟。

Quality Report

现代QA和测试部门重点关注的领域

敏捷和DevOps已经成为数字化转型的重要工具,同时,质量保障和测试工作也随之发生变化:

  • 中央治理和控制减少,团队选择方法和技术的自由度增大;
  • 部署速度提高和应用程序日益复杂化,软件错误和故障的风险增加;
  • 软件质量对品牌的影响巨大,但这已经不是最高优先级的目标,日趋成熟的尽早质量保障实践可以帮助纠正品牌和形象方面的缺陷;
  • 最终用户的满意度和安全性是最重要的两个方面,要确保应用程序的功能和非功能质量,同时需要找到成本和风险的平衡点。

调查结果表明,现代QA和测试部门需要重点关注的领域是以下三个方面:

1. 智能测试自动化和智能分析

智能测试自动化和智能分析将成为支持测试的关键,因为它们可以实现智能决策,快速验证和自动调整测试套件。测试自动化的范围从简单地将测试活动(计划、设计和执行)自动化发展到自动化测试环境和测试数据配置。

然而,调查结果显示目前自动化还处于不足的状态,尽管从自动化中获益的组织数量在增加,但产生的价值没有根本变化,测试自动化水平仍然很低(低于20%)。

速度将推动更智能的自动化需求,需要找到提高自动化水平的方法。

2. 智能测试平台

智能测试平台需要应对测试环境、数据和虚拟化日益增长的挑战。真正的智能测试平台的远景超越了生命周期自动化,需要实现自动配置的完全自我感知和自适应环境,以及支持自动化测试数据生成和测试数据管理。

测试环境、测试数据和虚拟化是三大挑战,同时也为自动化提供了巨大的机会。结合智能生命周期的自动化,将使QA和测试进入下一个演进阶段,称之为智能QA,这已经成为行业重要的关键成功因素。

3. 适应敏捷开发流程的QA和测试部门

组织需要关注的第三个领域是适应敏捷开发流程的QA和测试部门。在敏捷和DevOps模型中,测试从中心部门转移到分散的团队。未来的测试组织需要将灵活性与效率和重用性相结合,提供测试环境、测试数据、测试专业知识和技能的测试中心将分散到各种业务线的IT团队。

FIGURE 1

QA和测试的现状与挑战

从调查结果,总结出以下关于质量和测试现状的发现:

1. 回归对应用程序质量的关注,表明在敏捷环境的新上下文里,测试已经成熟

面对开发和测试环境的复杂性以及数字化转型的速度,关注点正在回归到整体产品质量上来,这是一个进步的迹象:

  • 参与这次调查的受访者中QA和测试人员明显多于其他角色,由2016年的37%上升到2017年的41%;
  • 2016年被引用最多的目标是在上线前发现缺陷,这个数字从40%下降到2017年的28%;
  • 最终用户满意度从39%下降到34%。

客户体验和增强的安全性处于IT战略的前两位。从2016年到2017年,增强安全性需求从65%大幅下降到35%。 IT成本优化进入今年IT战略的前三位,证明QA和测试能够应对过去几年的快速变化。

其他一些对IT战略意义重大的领域包括对业务需求的响应、实施软件即服务以及实施敏捷和DevOps。敏捷和DevOps实施需求的减少幅度超过一半,从38%的受访者减少到17%,这表明这些开发方法正变得越来越主流。

2. 测试自动化正在通向智慧、智能和认知QA之路

自动化尚处于待开发阶段,测试活动的平均自动化水平约为16%。自动化产生的价值在很大程度上没有变化。测试自动化不仅应该复制现有的手动测试过程,38%至42%的组织将认知自动化、机器学习、自我修复和预测分析视为测试自动化未来的有前途的新兴技术。

智能解决方案是DevOps、移动和物联网中的新趋势。通过增加智能自动化,企业适应快速变化的业务环境能力将得到增强。

Test Automation

3. 敏捷开发中测试的挑战不断增加

  • 99%的受访者在敏捷开发测试中面临某种挑战
  • 46%的受访者认为缺乏数据和环境是最严峻的挑战,这比2016年的43%有所提高
  • 在敏捷迭代中重复使用或重复测试的难度排在第二位,由2016年的40%增加到了45%
  • 挑战数量下降的唯一领域是:难以确定测试的重点以及测试团队在计划或初始阶段的早期参与。

测试和测试环境的自动化将帮助组织解决敏捷和DevOps开发模式给测试所带来的大部分挑战。 这些智能测试解决方案使得质量保障的速度能够适应日益复杂的集成IT环境。

4. QA组织不断演进以满足双峰要求

2017年,集中式的测试组织和分散式模型之间的分配更加均衡。在许多组织中,以前的卓越测试中心(TCoE,Test Center of Excellence)已经过渡到更加灵活的测试卓越中心(TEC,Test Excellence Center),其重点在于支持和赋能,而不是实际执行测试活动。

瀑布式开发仍将在未来很长时间内实施,形成与敏捷和DevOps混合的局面。例如,组织选择定位软件开发测试工程师(SDET)的位置时,其中敏捷Scrum和TCoE分别是36%和47%。

5. 环境和数据仍然是QA和测试的难点

调查结果显示有73%的组织采用云环境、15%的组织采用容器化来执行测试,使得测试的生命周期缩短。然而,仍有50%上下的受访者分别表示在测试环境管理、测试环境利用率、适用于敏捷开发的开发和测试环境,以及早期进行集成的环境方面存在挑战。

在测试数据管理方面,分别有超过50%的受访者存在以下挑战:管理测试数据集的规模、创建和维护合成测试数据、遵守与测试数据相关规定。

Test Environment Management

6. 测试预算下降,但预计会再次上升

专门用于质量保证和测试的IT总支出的比例为26%,它已经从2016年的31%和2015年的35%下降。

但是,随着组织采用敏捷和DevOps来支持数字化转型,未来两年质量保证和测试预算将会增加,企业必须确保IT应用程序的数量和复杂性,以及随之而来的QA平台解决方案的质量。

推荐的应对策略

1. 提高智能测试自动化水平

自动化是满足日益增长的数字化转型测试需求的关键,建议组织制定一个中心战略,确定企业首选的测试工具,确定自动化计划的战略业务目标,并确定衡量结果的指标。

同时,引入基于分析的自动化解决方案,向智能化QA和智能化测试自动化转变,以确保能跟上数字化转型的速度,做到持续的发展。

2. QA和测试部门转型以支持敏捷开发和DevOps团队

首先是组织结构方面的转变,QA需要与Dev和Ops团队一起,构建集成的DevTest平台,以实现持续的测试自动化。

测试人员专业技能也需要有所改变,要加强开发、分析和业务流程方面的技术专长,以适应敏捷和DevOps模式。

3. 投资智能测试和质量保障平台

在日益复杂的IT环境下,智能测试平台有助于企业做好质量保障工作。

  • 将智能分析和机器人解决方案引入测试流程和平台;
  • 提高容器化和虚拟化解决方案的水平和使用;
  • 投资于测试数据生成解决方案,以提供更多更好的符合所有法规的合成测试数据;
  • 将容器化环境,虚拟化服务和自动化测试数据集成到一个共同的可访问流程和平台中,组织可以围绕所有测试活动制定一致的方法;
  • 采用持续监测,预测分析和机器学习工具,利用生产环境数据,提供基于业务风险和实际问题定义测试策略。

平台战略

4. 定义企业级测试平台战略

开源和服务化解决方案给质量保障和测试工具的选择带来了灵活性,但是,跨多个存储库数据连接和交换导致企业级质量状态缺乏透明度。

企业可以实施单一平台战略,指定一些技术为主要选择工具,或者创建最佳工具策略,可以涉及来自不同供应商的多种工具解决方案。

5. 定义企业级QA分析战略

前面提到过智能分析是重点关注的领域之一。为了从智能QA(智能测试自动化和智能测试平台)的投资中获得最佳回报,建议组织确定企业范围的QA分析策略。

这种质量保证分析策略决定了应该部署分析和认知解决方案的目标和领域,定义了跨QA操作的智能技术路线图。质量保证分析战略应与整体组织战略相联系,并应描述其如何实现整个组织目标。

:以上内容和图片均摘自《World Quality Report 2017-1028》,更多详细内容请参考原文。


更多精彩洞见,请关注微信公众号思特沃克

Share

银行移动产品从团队敏捷走向产品敏捷

中国银行业的数字化转型刚刚拉开帷幕,移动产品成为了中国银行业的新战场。为在新战场占有一席之地,各家银行开始纷纷尝试自己移动产品的敏捷转型,更有甚者开始重新组建IT团队,用敏捷的方式重做原有的手机银行产品。

但这些转型往往在6-12个月后显示出明显的疲态。基本的实践都已经导入了,团队似乎已经“敏捷”了,但产品的响应速度并没有变快多少(想法的提出到上线的时长),产品的线上月活也没有显著的提升。那么敏捷转型到此就结束了吗,敏捷转型的下一步我们又该做什么?这篇文章作者将以多个实际案例出发,为大家揭晓银行业的移动产品如何从团队敏捷走向真正的产品敏捷。

团队敏捷是必要的,它是产品敏捷的必经之路

银行移动产品的敏捷转型很难一蹴而就,团队已经适应了“慢节奏”,习惯了阶段式的开发方式,敏捷的导入,无疑是一场变革。大规模的灌入标准化实践,最后的结果只会是“有形无实”,就像办公室中贴满五颜六色便签纸的白板,最后都沦为装饰品(数周也不更新)。

团队敏捷作为敏捷转型的第一步,以了解团队、分析痛点为前提,定制化的导入实践,让团队从传统向敏捷的开始转变。转型团队敏捷聚焦IT研发团队内部,包含产品、研发、测试人员,目标是:

  • 打造出一支敏捷迭代运作的IT研发团队
  • 建立团队级的敏捷流程及工程方法
  • 以及初步形成内部改进的种子力量

以50人的手机银行团队为例(4个全功能团队),团队敏捷从开始转型到稳定运作会持续4-8个月的时间。具体的转型过程就不在这里多做论述了。如果您的团队已经满足了以上的3个目标,那么恭喜您,您的团队已经迈出了敏捷转型的第一步。

产品敏捷的目标

“创业像开车,而不是发射火箭” ——埃里克 莱斯(精益创业的作者)

做产品也是一样。环境变化太快,产品很难像发射火箭一样,经过长时间缜密准备再发射验证。产品要像开车一样,有一个前进的方向,之后在行驶过程中根据外界的变化快速做出调整并验证,产品敏捷的目标也将聚焦于此。

  1. 帮助产品构建像“开车”一样,可以根据外界变化做出快速响应的能力;
  2. 在产品演进的过程中,帮助产品选择相对正确的“行驶”方向,帮助产品实现“弯道超车”。

很显然,团队敏捷,主要聚焦于研发团队内部的改进,对以上两点的影响并不大,更像是敏捷的萌芽和生长阶段。产品敏捷是以上述两点为目标,端到端(想法的产生到功能的上线)的分析及改进整个产品的实施过程,像是敏捷的开花结果。

走向产品敏捷的三个关键点

一、构建产品快速响应的能力

产品TTM(Time To Market)的长短体现了产品的响应能力的高低。以TTM的持续缩短为目标,是整体转型的关注点从“资源效率”到“流动效率”的改变,分析“流动单元”在产品端到端的实施过程中的流动情况,找到瓶颈点并加以改进,来持续提升“流动效率”,是转型的关键,主要分为3个步骤:

  1. 分析并定义产品端到端的实施过程;
  2. TTM的相关数据采集;
  3. 基于VSM的持续改进。

步骤1:分析并定义产品端到端的实施过程

团队敏捷中我们聚焦IT研发团队内部的迭代运作,在产品敏捷,我们需要以版本为维度,以需求为“流动单元”去梳理并定义端到端的研发过程,关键点是将产品版本与研发迭代融合

如下图,以某金融产品按月发版,研发双周迭代为例。需求分为Epic,Story两个层级,Epic为解决一个用户问题,Story为实现Epic的功能拆分。在版本迭代,我们关注的是Epic的流动(一个版本会包含多个Epic),从想法的提出,到最终的上线。在团队迭代来研发产品,我们关注于Story的流动,从Sprint Backlog的确认,到功能的持续交付(SIT环境)。端到端的实施过程覆盖了所有活动、产出件及流程流转,每一项都有自己独特的意义,每个产品的运作方式都有可能不同,重点是加强各个角色间的协作,使得团队适应该种运作方式,可以稳定的运作。

(某金融产品 产品端到端实施过程)

步骤2:TTM相关数据的采集

数据采集的前提实施过程梳理清晰且团队稳定运作。根据实施过程,我们可以清晰的得出Epic和Story的两条价值流,如下图。TTM是每个Epic从概念到上线的平均时间(如果Epic都是运营类的小需求,建议做合并成一个Epic)。当然Story的大小我们是可控的,Story的产生到集成测试完成的时间我们也要关注。

(某金融产品 Epic、Story的价值流)

数据不是通过WorkShop的问问答答就能得出的,需要借助电子工具的辅助,做准确的分析。首先作者对于电子工具的态度是:工具是辅助运作,而不能影响运作,不能出现由于电子工具的限制而改变运作结构。电子工具的目的是便于过程管理及可视化。

作者推荐的工具是Jira,Jira的优势在于可以通过配置实现高度的定制化,以及开放API数据接口(商用版)。作者建议抛开Jira中大部分的预定义好的模板及元素,根据现有的运作方式,做深度的定制(例如Story元素的重新定制)。从Jira中“问题属性”、“字段”、“界面”、“工作流”、“权限”等的自定义,到Jira Agile中的“看板”,“阶段”,“移动规则”等自定义。由于是相对于底层的定制,所以配置起来比较复杂,这里要保持开放的心态。

如下图,根据运作方式,在关键节点引入Jira做管理,并且根据运作方式,确定Jira的使用规则。

(某金融产品 配合运作方式的Jira使用)

在上线了2-3个版本后,我们就可以尝试做数据的采集及分析,Jira提供了方便的API接口供我们提取数据,要注意数据清洗及公式的配置,最后得出每个版本的TTM时长。

步骤3:基于VSM的持续改进

我们使用的实践是精益中的VSM(Value Stream Mapping)价值流图,来做持续的改进。通过Jira中的数据,建立Epic和Story的价值流图。以Story为例,如下图,数字为Story在该阶段的平均停留时长(天),按照迭代做分组。分析数据找到可能的问题点,很明显前4个迭代“待联调”和“测试中”的用时很长,之后去做该阶段的原因分析并尝试改进,再分析新的数据(第5个迭代的数据提升),以做到团队的持续改进。

当然了这里面的问题点是多样的,组织、需求、管理、技术等因素都可能成为问题的原因,这里的重点是找到核心问题,拿着数据证明去尝试解决,最终也可通过VSM也来体现我们的转型成果,这也是真实的量化的数据。

(某金融产品 前5个迭代,Story的VSM)

电子Dashboard。持续的Excel取数很难做到实时。尝试做电子Dashboard,做到价值流实时可视化,便于信息的透明化及持续改进,为提高产品的响应力打下坚实的基础,详见下图。

(某金融产品 价值流Dashboard)

到此阶段,您的团队已经有一套端到端的稳定运作方式及电子管理平台,可视化的VSM来体现问题点及成果展示。剩下的就是大胆去做瓶颈的原因分析及改进,来持续的提升产品的响应能力。

二、帮助产品实现“弯道超车”

金融科技企业对中国银行业的冲击是巨大的。多家传统银行直面差距,定义自己的移动产品策略是“追赶”,产品经理的惯性思维,“XXX有这项功能,做了这项优化,我们的产品要把它加上”。当然了如果落后,追赶固然没错,但在追赶的过程中我们也要制定赶超的策略。

金融需求无处不在,衣食住行娱每个细分场景都有金融需求出现,对于传统银行,信誉,数据、网点、存量用户等都是自有的优势。那么结合用户的需求与自身的优势实现金融产品创新,才是“弯道超车”的关键

利用设计思维的方法来获取、定义及实现用户的需求。扭转业务、产品、研发等角色的本位思维,从提出需求走向了解用户痛点,从实现需求走向为用户创造价值。

(设计思维的双钻模型)

建立产品内部的创新机制,抛开传统银行自身的限制,鼓励全员创新。如下图,从一个创新想法,到MVP的制作验证,最快只需要3周的时间。立项通过的想法进行2-3个月的孵化验证,最终有望形成新的商业产品。过程中给予创新者创新教练、团队资源的专项支持,内部创新的同时也在培养团队产品思维,提升团队的产品能力。

(某银行的内部的创新机制)

三、培养内部教练队伍

这个是敏捷转型的基础,需要进行管理、技术、产品、创新等内部教练的梯队建设。组织中缺少的是经验积累及专有人才,而不是流程规范。之后作者会以专文来讲述企业内部教练的体系建设。

总结

在移动金融产品的新战场上,银行的移动产品需要从“发芽生长”的团队敏捷,走向“开花结果”的产品敏捷。

三个关键点助力产品迈向产品敏捷:

  1. 通过产品开发过程端到端的梳理与定义,电子工具的引入,基于VSM的持续改进,来持续缩短产品的TTM,构建产品快速响应的能力;
  2. 使用设计思维打造产品,并建立产品内部的创新机制,来实现金融创新,帮助产品实现“弯道超车”;
  3. 建立企业内部的教练体系,注重人才培养及积累经验,来推动敏捷的发展,促使产品持续进步。

最后,希望中国银行企业把如今市场中的不确定性,看做是产品的新机遇。对于这种新机遇的驾驭的能力,将成为产品优胜劣汰的关键。


更多精彩洞见,请关注微信公众号:思特沃克

Share

最好的样子 | 女性

知乎上有这样一个帖子:女性最好的样子应该是什么样的?吸引了很多人来贡献答案,众多的答案中有一个让我印象特别深刻:

我不年轻了,但是仍然觉得自己在最好的样子。生活是一场马拉松,跑到后面还不泄气才是真赢家。

对于这个问题,不同的人可能会有不同的答案,我自己也有深深的体会。

01 从运营管理到一线业务,开启最好的状态

18年初,我离开了中国区的管理团队,到业务的一线做了一名项目经理。

在管理团队的 6 年里,我做过人力资源管理,组建了资源协调团队,带领过内部IT项目团队,还做过全球能力变革项目的发起者和项目带头人,按照这个道路走下去,我的职业发展可能会和组织管理或者全球的某块业务相关。

但是我突然回到了一个很小的项目团队,这个决定让很多人不解,仿佛看到了一个长跑的人,已经跑出了很远,突然折返回来,回到了 6 年前的那个起点。

别人不解的背后其实是我思索很久的决定,在管理团队的最后两年里,尤其是休完产假回来后,有时候感觉自己迷茫找不到方向,有时候做起事来力不从心,尝试过一些调整后,仍然找不到持续的热情。

可能又到了做出重大改变的时候了。

如此重大的改变,最常规的做法是换个环境,换家公司,开启全新的职业发展阶段,但 6 年前的经验告诉我,既然能从一名测试工程师做人力资源总监,也可以从运营管理转做一线业务,这是一家支持变化的公司,所以我不需要换环境,所有的经验和技能都能在组织内部迁移。

和6年前不一样的是,这次我是主动出击,去找一些人聊我的想法,听取他们的建议,这也是我在这家公司待了10年多最深刻的一个收获,我们要对自己的需求负责,然后积极寻求别人的建议,和6 年前一样的是,我从别人那里得到了很多诚恳的建议和支持。

很多时候,想法有了,但离行动还会差一段距离,那距离便是决心和勇气。

年初的时候,中国区的管理团队决定做一次调整,根据新的业务形态重新规划团队结构,同时也吸纳一些新鲜血液,按照常规,有人加入,就要有人离开,听上去是一个带点伤感的决议,但在心里,我竟然有些期待。

因为这个决议能帮我鼓起勇气迈出这一步。

但我的内心是不安的,在管理团队待的 6 年多的时间里,业务领域的方法和技术迭代了好几次,业务和客户的复杂度也高了很多,我当时的担忧多于兴奋。

《少有人走的路》里面有这样一句话:“勇气是,尽管你感觉害怕,但仍能迎难而上;尽管你感觉痛苦,但仍能直接面对。”

那个时候,除了往前走,我没有给自己留任何退路。

后来,在四个月的时间里,我服务过三个客户,每个客户的挑战都不一样,项目上遇到的难题,合作的同事,解决问题的方法也都不一样;四个多月的时间,我没有过一个完整的周末,瘦了很多,体重比生孩子之前还要轻(也很欣喜);四个多月的时间,我产出了38篇文章,相当于一个周两篇,大多来自于项目和工作的感悟。

有一次和同事聊天,那个时候第一个项目刚结束,我们有相同的感慨,想想项目不过持续了两个月,但回想项目开始的那天,仿佛那是很久以前的事情。

因为两个月的时间里,我们经历了太多的事情,我们学到了很多的东西,每个人也都不是项目开始时的自己了。

现在想来,自己也很庆幸当初做的那个决定,尽管一线的工作很辛苦,但我的状态很好,也充满兴奋。

02 面对现实,接受自己的力所不能及

一线的很多项目在客户现场,这也就注定了出差是常态。

有一次晚上加完班十点多,在回酒店的出租车上,有位同事分享自己的感慨:女性在职场,要想拼,一定要在生孩子之前完成,否则会有太多的牵挂和力不从心。

她是一位刚休完产假回归职场的母亲,和我们所有人一样加班、熬夜、出差。

对她的感慨,我深有体会。

第一个项目出差前,我做了一些安排,把家里的小朋友送回到了老家,项目中期赶上五一假期,所以回老家把他接回北京。

我一直记得分别一个多月后他见到我的样子,眼睛里带着点惊恐,也闪烁着兴奋,他奔向我,既想亲近又掩饰不住陌生。

把他带回北京后,我很快又出差了,因为晚上经常加班,所以几天才视频一次,先生告诉我,每次听见楼道里有响声,或者快递员敲门,他总是欢快地喊着“妈妈”去开门,但每次都是失望而归。

每当脑海中想起他失望的样子,心里就泛起一阵阵心酸。

人生到了这个阶段,我们有太多的责任和承诺,对工作,对家庭,甚至对社会,我们一边希望自己可以做尽可能多的事情,一边往往会为做不到事事尽善尽美而自责,愧疚,甚至灰心。

曾经和一位来自全球知名咨询公司的客户聊起女性在职场的发展,她说她所在的公司,非常重视也支持女性在职场的发展,但是一旦当了母亲,大部分女性仍然会选择离开,哪怕再喜欢那份工作,也不得不放弃,因为无法平衡的工作和家庭。

在这个男女平等还没有完全到来的社会,在职场,面对同样的工作,同样的职位,很多女性需要比男性付出更多的努力去证明自己的能力,需要表现出更多比男性对工作的重视,来证明自己不会被家庭所拖累。

我很欣赏这样的女性,也深知她们在追求事业成功的背后必然做出了很多迫不得已的决定。

看过这样一句话:知道自己力量的界限,这本身就是一种能力,要用一生去探索。

对我来讲,错过了小朋友成长的一些瞬间,也没有办法时刻陪伴着他,但我选择做一个和他一起成长的母亲,他学习走路,学习说话,慢慢长大,我学会面对现实,尽力而为的同时,接受自己的力所不能及。

03 之所以努力,是不想让自己那么快的老去

9月份,我会再次回到学校,去读MBA学位,这意味在接下来的两年,平时忙工作,周末忙学业,那将会是很大的挑战。

我有这个想法其实已有很多年,但是一直没有去行动,有时觉得是太忙,抽不出时间准备,有时又在思考即使学业有成,会有什么价值,在日复一日的犹豫里,我错过了最好的年纪。

记得几年前和一位职场前辈聊天,具体聊什么已经记不清了,隐约还在脑海留下一些词,事业追求、人生梦想,财富自由,中年危机。

那个时候还完全不知道这些词是什么意思,也觉得离他描述的那种场景很遥远。

转眼间,似乎自己就到了那个尴尬的年纪,对家庭有承诺,对工作有责任,自我成长越来越奢侈也渐渐成为前行的瓶颈。

有时候会在夜里突然醒来,感觉自己还有好多东西不懂,好多事情未做,惊出一身冷汗。

真的有种感觉,年龄越长,自己越无知,经历的越多,想学的也就越多。

还记得MBA面试的时候,主面试官问了我这样一个问题:对很多女性来说,有了孩子之后,兼顾工作与家庭已经非常困难,你已经不具备年龄优势,为什么在这个时候还选择来上学?

是一个很好的问题,他问出了很多女性在这个时期的无奈,可能每个人都有自己的原因。

我看着两鬓斑白的主面试官,他眼神凌厉,应该拿着这个问题问过很多和我经历相似的人,在他那云淡风轻的表情下已经有无数个答案了吧。

我说:以前我觉得一个人老去的标志是老成持重,沉稳避世,现在觉得是不敢让自己置身不熟悉的境地,放弃了学习,我只是不想让自己那么快的老去。

面试通过后,又顺利通过了笔试,等我真正接触到我的那批准同学,才发现,和我经历相似的女性不在少数。

我为能结识她们加入她们而欣喜。

前几天有同学在群里提问:我们这么努力,是为了什么?

很多同学出来分享自己的想法,有位同学说,人生一切努力的价值,就是为了成为美好的一部分。

颇有感触,我们之所以不停努力,或许就是为了发现美好,并且不遗余力的让自己成为这个世界美好的一部分。


最近在看吴军的《见识》,里面提到牛津大学圣埃德蒙(13世纪的坎特伯雷大主教)的一句话:“ Study as if you were to live forever, live as if you were to die tomorrow”,翻译成中文也许是“终身学习,向死而生”。

作为女性,如何保持最好的样子,这算是另外一种诠释了。


更多精彩洞见,请关注微信公众号:思特沃克

Share