运营活动测试总结-从代码层次分析,提高工作效率

运营活动有很多种类,主流的营销方式是发红包+发推送消息。当用户行为达到某个点时,有获得活动红包的机会。所以,为了达到最优营销效果并防止用户过度消费,运营活动就会设置一些活动资格的领取条件。
正因为有诸多的限制条件,导致后台配置有很多项。为了验证这些配置项及其组合是否生效,测试人员需要花费一些时间了解需求、了解配置项的操作。对于这种发红包或推送的功能测试,其间会涉及到消息发送、消息传递、消息消费的过程,也经常会遇到实际现象没有达到预期效果的问题。有时候会遇到不知道去哪 找问题的原因,服务器log按什么关键字匹配查找,是环境问题还是代码问题呢......这些情况总会导致测试进度block,工作效率降低。
以运营活动【新用户注册登录送红包】为例,总结一下自己的测试经验:
一、熟悉需求
-新用户:首次安装客户端的用户(即该活动资格对某个用户来说只有一次获得机会)
-后台管理系统需要配置的配置项:
key: newUserRegisterTime  value: 30  备注:新用户注册时间。
key: newUserRegisterActivitySwitch  value: on  备注:活动开关
key: newUserRegisterChannelConfig  value: channel1,channel2,... 备注:需要发放优惠券的用户渠道,多个渠道以“,”间隔
key: newUserRegisterCouponConfig_channel  value: cs1:1,cs2:2,cs3:3 备注:单独某个渠道的红包方案

二、分析代码进行测试验证
1、根据代码分支 f_170308_xj_newUserCoupon查看代码修改部分
常规方法是在git上找到这个分支,看代码修改记录,如下图所示,会看到很多diff记录。由于该开发分支有代码merge操作,无法明确与需求相关联的代码,所以进一步筛选。


输入开发同学的名字进一步 筛选代码:



找到这个需求的业务功能代码:UserLoginController.java、SendNewUserCouponRunnable.java、NewUserCouponHandler.java
在UserLoginController.java里找到这个功能的代码入口:

2、阅读代码逻辑,理清功能需求,排解疑问
在测试过程中往往会遇到需求不明确,或者需求变更导致代码实现与原需求不一致的地方。 单单从黑盒测试角度出发,测试过程中就难免会产生一些疑惑。
开发提测说明里描述了一些后台配置项,但是不清楚某些配置项的含义、作用,就不知道怎么验证。
For example-->根据提测邮件描述:【key: newUserRegisterTime  value: 30 备注:新用户注册时间。】
newUserRegisterTime:
-新用户第一次注册登录后,保持登录客户端这个状态的持续时间?
-用户现在登录客户端的时间,距离第一次注册登录客户端的时间间隔?
-这个时间设置有什么作用?
阅读代码解惑:


时间限制字段timeLimit=当前时间-Identity表create_time的时间(用户第一次登录时间)。
运营活动通常是在某个特定的一段时间内的用户行为点营销,所以就会涉及到时限。不超过这个时限,用户的行为被认为是有资格的。
本次需求,当用户首次登录未能获得红包(场景:新用户用已经获得过红包的设备注册登录),在不超过时限范围内再次登录时仍被认为是新用户,就有资格获得活动红包(当然也是没有其他限制条件,符合资格要求),超过时限就不是新用户,就没有资格了。
这个需求只是描述了新用户注册登录可以领到红包。对于用户来说,为了更可能多地获得红包,就会用多个账号注册登录。那么测试过程中就会考虑到测试多个账号注册登录的情况:
-用账号account1获得了红包后,再换另一个账号account2是否就可以继续获得?
针对这个疑问,黑盒测试中会进行如下操作来得到答案:
-同一个设备上,换成账号account2登录,看是否有收到红包?
-没有收到,会产生疑问:是环境配置的问题,还是其他限制问题?
-然后就开始排查是否是环境问题(查看测试环境是否其他人改变,被改变了然后重新发布环境...)
-环境ok,是什么条件限制了?
-然后也会想到换设备测试,换了另一个设备用账号account2登录,能收到红包...
如果存在这些疑问进行测试的话,总有剪不断理还乱的感觉。特别是涉及到环境配置相关的问题,总会耽误一些时间。
改变测试方式,从阅读代码入手。
根据这段代码,大致可以猜出限制条件: channel、userName、deviceId、ip。


看了代码后觉得刚才的疑问有迹可循了,就可以进行如下验证:
-新账号注册登录后,看Identity表里是否正常插入记录
-账号account1退出登录,仍用设备a登录,不可再获得
-卸载重装,仍用账号account1在设备a登录,不可再获得
-账号account1在设备b登录,不可再获得
-新账号account2用设备a登录,不可再获得
-新账号account2用设备b登录,可以获得

综合上述2点,再次从需求分析总结测试中应该注意的点:
-运营活动通常会有防刷的规则:已领取过资格的用户不能再领取,多找角度验证;活动通常有时限性,超过时限后没有资格。
-延伸思考:通过某个url链接入口获得红包这样的运营活动,要考虑下,该url是否可以手动拼凑后获得红包,防止用户恶意刷单。
-延伸思考:活动入口页面在异常情况下(活动超时或失效)或空状态下的页面内容显示问题(有时候运营同学可能缺乏对这种情况下的考虑)。

3、代码log分析,帮助定位问题,查找测试点,提升测试覆盖率
① 定位运营活动需求的入口代码,通过判断日志服务器是否有相应的log正常输出,判断环境配置是否OK
For example-->线程启动时的log


② 添加各个配置,按照需求生效场景操作客户端,通过判断日志服务器是否有相应的log正常输出,验证活动的配置项是否生效
For example-->配置项里活动开关的log


For example-->配置项定义新老用户的log


③ 红包配置项的生效验证
定位到处理红包方案配置的代码


分析代码,红包方案配置是按照渠道配置生效(NEW_USER_REGISTER_COUPON_CONFIG + "_"+ channel)。
但是需要注意一点,有个默认值:NEW_USER_REGISTER_COUPON_CONFIG,不配置+ "_"+ channel的情况。
所以需要验证【NEW_USER_REGISTER_COUPON_CONFIG + "_"+ channel】之外的渠道的新用户所获得到的红包是什么样的,是否是按照NEW_USER_REGISTER_COUPON_CONFIG这个配置生效了。
本次需求提测说明里没有提及到这个红包方案的总配置。所以有时候 开发的提测说明里 可能会略去某些配置项的默认值说明,需要自己去代码里查找,然后测试验证。
活动生效与否,还取决于配置方案是否正确。
For example--> 红包配置方案正确性的校验代码


验证在配置方案错误的情况下,是否有log提示。当更改为正确配置的情况下,活动是否生效。
总结:
- 日志信息是帮助定位问题,提升测试效率的有效手段!
- 在某些代码里没有开发添加的log时,可以自己打测试log:把开发的代码分支合并到自己的test分支上,添加log代码,然后push到远端服务器,重新发布环境后验证。

三、深入分析代码问题
上面主要是讲述了通过代码分析协助进行测试验证工作。
1、代码走查定位问题
如果能够深入理解代码,通过代码走查定位到问题,相比执行功能测试也能提升工作效率。
For example--> 本次需求测试过程中遇到的一个bug,活动资格限制条件中的渠道配置 NEW_USER_REGISTER_CHANNEL_CONFIG ,取值可配置成“userChannel1,userChannel2,...”。


当用户渠道为“userChannel”时,会被channelConfig.contains(“userChannel”)判断为True。
本来是不在允许获得活动资格范围内的用户,由于代码里字符串匹配错误的问题,也能获得活动红包,造成一定的损失。
正确代码逻辑:


在上述配置下,如果设计了测试该功能点的用例,利用黑盒测试方法也能找到bug,但会花费一些时间;但是如果没有这样的测试用例,则难以发现问题。

总结:
-通过代码走查方法定位到问题,就会较快速地定位出问题,提升工作效率。
-注意代码中条件判断语句的条件取值,分清楚什么情况下会return,什么情况下继续走下面的代码逻辑。
-测试过程中,可以编写一些简单的测试方法验证条件取值。

2、分析代码性能问题
流程能走通,配置能生效,说明代码功能没有问题。
但值得思考的是,运营活动过程中,通常会有大用户量并发向服务器发请求的情况,那么可以深入分析下代码是否有性能上的问题。
本次需求中客户端是通过登录接口向服务器发送请求。那么在有效时段内,符合条件的新用户只要操作登录接口都会向服务器发送消息。
当服务器收到消息后,就进入handle方法处理。调用check()时,就会读取数据库进行校验用户和设备是否为新用户。


思考到几点:
① 若timeLimit很大时,这段时间只要操作登录接口都会向服务器发送消息,服务器就要长时间的响应客户端的请求,对服务器有性能影响。
② 调用check()时,通过读取数据库数据检验用户和设备就会有性能消耗。
③ 线上环境,大用户量并发向服务器发送请求也会对服务器造成压力。
④ 如果有用户恶意请求登录接口,也会对服务器造成压力。
⑤ 延伸思考:向服务器发送消息的接口,是否是用户使用频率较高的接口(比如首页商品列表接口,在手动刷新首页、参与成功跳转、tab切换到首页这些操作都会调起这个接口,使用频率较高),在时限范围内发请求的频率高也会对服务器造成压力。
⑥ 延伸思考:有些比较重要的配置,是否有阈值限制,防止配置错了导致服务器性能问题。
基于这些疑问,要跟开发确认好,代码是否对服务器的性能有影响,是否需要优化,sql是否修改,修改的sql需要DBA审核。

3、log.info()方法分析
代码里的log.info()是我们排查问题,了解系统状况的重要线索。在程序开发的过程中,我们需要很多的日志协分析程序问题;但在生产环境中,没有那么多的空间存储丰富的日志,而且日志量太大对于问题排查反而是累赘。测试人员在代码审查的时候,也需关注下代码里的log,是否有多余的log。也需要关注下,开发人员是否去掉了一些有价值的log(特别是涉及到第三方的调用,请求报文和返回报文的log)。避免为了控制日志输出数量,没有记录重要log,导致在遇到问题时不容易定位。

四、测试环境问题思考
在测试过程中为了保证功能生效,都会保持测试环境不被改变。如果遇到各项配置正确、条件符合、但功能不生效的问题,通常会归咎于环境问题。然后就会重新发布环境。但是线上环境,用户的操作不受生产环境牵制。在某些特殊情况下,比如服务器正在处理用户客户端发送的请求时,生产环境服务器被重启(比如其他需求发布上线,服务器重启)或者第三方环境的网络超时等等,可能会导致响应延迟甚至丢失。导致用户没有及时收到活动红包甚至没有收到红包。
对于环境引起的这种问题,很难在测试环境中发现。
对于一些运营活动,用户是通过活动入口页面参与活动。当满足资格的用户参与活动后没有收到红包,或者无法正常访问活动入口页面,这样的问题就会影响用户体验。 当遇到类似需求的测试时, 要考虑需求设计是否合理,是否有对应的补偿机制给遇到问题的用户提供对应的活动补偿;代码设计是否合理,是否能够较好地保证系统之间消息传递的健壮性,不会轻易出错。

五、了解系统架构,提升技术水平
系统架构采用分布式消息系统 EasyMQ,是高性能、高吞吐量的消息中间件,能够实现集群的高容错性和高吞吐量。
消息系统要保证消息有序传递、多条消息并行处理。
消息有序指的是可以按照消息的发送顺序来消费。例如:一笔订单产生了 3 条消息,分别是订单创建、订单付款、订单完成。消费时,要按照顺序依次消费才有意义。与此同时多笔订单之间又是可以并行消费的。
为了实现消息的顺序发送,并解决多条消息并行处理的问题,服务器端用生产者和消费者处理客户端的请求。
producer集群:消息发送端(生产者),每个producer都需要属于一个group,发送消息的时候会指定topic。
consumer集群:消息的消费者,遍历consumer下的所有topic,然后根据topic订阅所有的消息;获取同一topic和 consumer group 下的所有 consumer; 然后根据具体的分配策略来分配消费队列。分配的策略包含:平均分配、消费端配置等。消费者的作用不仅是处理发送者的消息,也能够实现负载均衡。
在集群消息的配置下,集群内各个服务平均分配消息,当其中一台consumer宕机,分配给它的消息会继续分配给其它的consumer。

For example--> 本次需求中生产者和消费者的代码示例:

总结:
了解了系统架构原理,就会更清晰地明白测试过程中需要注意的测试点:
① 一个应用尽可能用一个topic。
② 消息发送成功或者失败,要打印消息日志
③ 对于消息不可丢失的应用,务必要有消息重发机制。例如:消息发送失败,存储到数据库,能有定时程序尝试重发或者人工触发重发。
④ 尽量使用批量方式消费方式,可以很大程度上提高消费吞吐量。
⑤ 优化每条消息消费过程,避免影响服务器性能。 
从需求入手,熟悉需求,看懂代码,定位log,了解系统架构,掌握了这些技能,对测试工作的开展、测试效率的提升有很大的帮助! 
这篇总结只是结合工作中的所思所想写的分析思路,具体问题还需具体分析。希望对测试工作有帮助。

本文来自网易实践者社区,经作者张亚楠授权发布。