跳槽高峰期,作为测试,不管是面试还是笔试,必然要被考验到的就是“测试思维”。在面试中就是体现在如下面试题中:
“说说你项目中的 xx 模块你是如何测试的?”
“给你一个购物车,你要怎么测试?”
"你说一下这个产品的登录功能有哪些测试点?"
“支付功能怎么测试?”
......
所有的这些问题其实都是在考察你的测试思维。我们在回答这类问题的时候其实是有方法可依循的。
今天这篇文章,我就拿很多同学都觉得难的一个问题“支付功能”作为案例,一起来分析一下该如何回答这类的面试题
一、测试思路
要分析测试点之前,我们先来梳理一下测试思维。总结来说,任何事物的测试思路都可以总结如下:
第一步:梳理产品的核心业务流程:明白这是个什么项目,实现了什么业务,以及是怎么实现的?
这个步骤一般是参考公司的需求文档来的,如果产品提供需求文档的同时提供了业务流程图,可以遵循流程图来梳理;如果产品没有提供流程图,就需要测试人员根据需求的理解自己画出流程图,达到梳理业务的目的。
第二步:根据流程进行模块细分,然后针对每个功能模块进行详细的测试点设计和提取。
这个单个功能的测试点提取要覆盖以下几个方面:
正常功能验证:优先覆盖正常的业务流程和功能验证,这其实也是单个功能的冒烟测试。冒烟测试先行,如果不通过,可以直接停止测试等开发修复后继续测试。
异常功能验证:为了更加贴近用户的使用产品,我们也要验证各种异常的场景,故意操作导致出错,检查系统的反馈和提示,保证用户操作失误的情况能够得到系统的友好指示。
因为有很多地方的操作都有可能会导致系统异常和报错,所以为了不漏测,我们需要找出所有可能导致异常的输入项和选项。所以就到了第三步:
第三步:针对具体功能,寻找每个输入项和步骤,从以下三个角度来分析测试点 。
1. 长度,数据类型,必填项,重复
2. 需求的约束条件 + 隐形需求
3. 功能之间的交互
这其中就需要用到一些用例的具体设计方法了,比如场景法,等价类法,边界值法,错误推测法等等
第四步:考虑非功能测试点,包括界面、易用性、兼容性、安全性、性能压力
二、支付功能的测试点
基于上面的测试思路,我们可以分析得出“支付功能”测试点如下:
梳理支付的业务流程:
点击支付---> 选择支付方式 ---> 确认金额---> 输入密码 ---> 成功支付
完成这个流程测试,也就是完成了项目的冒烟测试,然后需要测试针对流程中的每个阶段和步骤,具体分析可能导致异常的测试点,所以我们按阶段和输入项来进行划分如下:

非现金支付时代,非现金支付已经成为了生活不可或缺的一部分,我们只需要一台手机便可走遍全国各地(前提是支付宝,微信有钱)那么作为测试人员,支付测试也是非常重要的一环,那么下面我就结合一下我的工作中遇到的一些问题,总结一下常见的支付测试:
一: 支付的分类
首先,根据不同维度,通常我们可以把支付分为如下图所示的种类:

其次,一般来讲,线上支付分为两种消费模式。一种是直接支付金额,如淘宝,京东等购物网站,或是360云盘,视频会员等这种会员服务;另一种是充值购买金豆之类的虚拟币,在网站中使用虚拟币进行消费,比如游戏平台、花椒等产品!
二: 功能测试
接下来就是测试方面的工作了,首先进行的是功能测试,那么我将边界值、等类划分、错误推测,因果图等各种测试方法相结合,整理出来了一套相对
全面的测试案例,对支付功能进行测试,从而确保整个支付流程和涉及到的支付流程在任何情况下都能使用。
三: 接口测试
明确整个支付流程所需要调用的接口,分清楚商家和第三方平台的接口以及参数的请求方式,包括对接口特定参数的加密,使用异常单号模拟支付,对服务端的检验等等
四: 安全测试
支付都会涉及到金额,那么就需要考虑安全测试这个方面,支付请求的伪造,金额的恶意篡改,恶意模拟第三方接口来调用商家接口等,均是我们需要考虑清楚的问题
五: 支付流程(如下图)

六: 测试点
支付流程测试点
1、付款金额和应付金额是否一致,(比如:扫描的支付二维码,和显示的应支付金额是否一致)支付还是要走整个支付流程才行,从确认订单到最后的支付成功,任何一步都有可能有问题。
2、同一种支付方式,不同的支付入口(比如:如下图所示,支付宝有两个支付入口。即可通过扫描二维码支付,也可以通过支付宝网页支付。在测试过程中,两个入口都要覆盖到。
3、支付成功后,产品购买是否成功
(比如会员服务产品,购买后会员到期时间是否正常延迟;比如购买商品,支付成功后,订单状态是否更改,商品种类和数量是否正确等等)
4、支付成功后,用户的金额是否扣除成功
支付金额测试点
1、正常金额支付
2、金额的最小值:0.01
3、无意义的值:0元
4、最大金额:设置支付的最大金额
5、银行卡或微信等,设置每日最大消费金额或者单笔最大消费金额
6、银行卡或微信余额不足时支付
支付流程测试点
1、正常完成支付流程
2、调起订单后,取消订单
3、支付中断后,继续支付
4、支付中断后结束支付
5、单笔订单单笔支付
6、多订单合并支付
7、持续点击支付,是否会出现多次购买
支付方式测试点
1、支付宝支付
2、支付宝网页支付
3、微信支付
4、银行卡支付
优惠券或折扣(有一定的优惠)
支付中使用优惠券/折扣,应付金额和实际支付金额是否正确
优惠券/折扣是否是必选,是否可以不选择折扣
支付订单退款完成后,优惠券/折扣是否还能使用
遇到的坑:
坑一:页面显示的应付金额通过接口vip.product返回了,前端显示出来应付金额。但是,支付的二维码是通过接口vip.getPayUrl这个接口返回的,结果二维码扫出来的值和显示的应付金额不一样呀!!!最后问题是在于,vip.getPayUrl中取的是服务器缓存,导致二维码显示的金额跟前端展示的应付金额不一致。所以测试支付还是要走整个支付流程才行,从确认订单到最后的支付成功,任何一步都有可能有问题。
坑二:通过支付宝网站支付,支付成功后,页面没有跳转回原服务套餐网页。最后的原因是服务配置的return_url不正确,导致支付后,没有跳回原页面。如果测试用例覆盖不到这种场景,那么将会造成非常严重的线上事故
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel
所以我开始关注ruby,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出
给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R