目录 start
目录 end
|2018-07-08| 码云 | CSDN | OSChina
测试
基础知识
测试类别
单元测试
- [ ] 单元测试, 集成测试
【A/B测试】
对照实验,也叫随机实验和 A/B测试 参考来源:知乎问题 | 相关三方平台
A/B测试其实是一种“先验”的实验体系,属于预测型结论,与“后验”的归纳性结论差别巨大。A/B测试的目的在于通过科学的实验设计、采样样本代表性、流量分割与小流量测试等方式来获得具有代表性的实验结论,并确信该结论在推广到全部流量可信。
说句题外话,大量的大数据公司都在尝试通过“后验”结论进行未来行为预测,个人觉得然并卵,主要是因为数据不全、脏数据、随机事件、建模人为因素等等影响,方向无比正确,现实无比残酷
A/B测试的应用场景
- A/B测试这种方法论的应用非常广泛,这里讨论在Web产品、移动产品、数字广告优化领域的应用。应用场景由小到大可以可以分为:
- 元素/控件层面
- 功能层面
- 产品层面
- 公司层面
元素/控件层面
灰度发布 和 A/B测试:重要页面的修改和流程上的调优,通过灰度发布到1%或者5%的用户,看其实际对用户的数据影响(访问时间增加、留存提高、下单率提高等),决定此修改到底是100%发布还是被砍掉 Google: 每个月从上百个A/B测试中找到十几个有效方案,月营收提升2%左右,10亿美元的规模 广告位左移一个像素带来X%的增收,左移两个像素带来Y%的亏损 任何产品改动需要A/B测试才能上线 Facebook: 6个月内所有版本完全线上灰度发布,通过不断进行用户流量分割的方式进行实验,获得无Bug口碑
灰度发布就是,先把一部分线上的业务分流到新系统上, 然后看情况, 再判断是否全部上线
功能层面
无论是推荐算法还是定价策略 为了简单理解,说个定价策略,如上图。 一个价格包含这个几个因素:
1.价格区间:
用我最朴素的理解,人类是喜欢折扣的不理性动物:人们明显更乐意花45折买一个价值900块钱的东西而不是花67折买一个价值600块的东西,尽管东西一样,最终价格一样都是400块。
所以你看电商广告都是打折配合几个垫背的低价来卖。。。2.价格精度:
以前去超市经常能发现2.99元或者8.99,现在都变成2.32或者4.23,这是弄啥嘞?
这里面太多心理学与营销的东西就不说了,在某些情况下,即使几分钱的价格变化对用户转化的影响是巨大的,比如一个东西原来卖400元,那现在改成399还是401可能对总营收的影响并不巨大,但是配合用户转化率的变化,可能营收的差异就天差地别了。3.价格周期:
伴随着产品迭代、促销等等因素影响,什么时候降价是对自己最有利的策略,完全可以A/B测试来解决
产品层面
A/B测试在产品层面的应用主要是通过“灰度发布”来实现的。 就目前移动端的产品来说,iOS的应用商店审核期是个大大大坑,任何BUG打补丁还得再来一遍,也就意味着补丁的审核期内用户带着BUG使用,这个太致命了,用户的获取成本高的吓人,因为这个流失太不值得了,基于A/B测试的灰度发布更重要的不是优化,而是保护性发布,先通过小流量的实际用户测试,有BUG或者新版本体验不好,可以立即回滚到老版本,简单有效。
公司层面
A/B测试其实也是谷歌管理方法论,具体文章请参考:
- Google 的产品策略:两边下注 &version=11020113&pass_ticket=N7rowGeMgSIo27M2UKuWi1JsLuQ2wgA2f6hPaARrza5teBqjdjGkx5S6hAcmdLxo)
相关问题
辛普森悖论(Simpson's Paradox)亦有人译为辛普森诡论,为英国统计学家E.H.辛普森(E.H.Simpson)于1951年提出的悖论,即在某个条件下的两组数据,分别讨论时都会满足某种性质,可是一旦合并考虑,却可能导致相反的结论。
相关:辛普森悖论:诡异的男女比例
大多数的产品或功能上线前都会进行测试,实际上很多的测试行为并不科学,特别是很多定向的用户测试经常会有这个弊端,简单来说,如果新上线的一个功能,所有的研发工程师都说好,那是不是意味着所有的用户都觉得好?很多情况下是否定的。当然这个例子比较简单,实际上很多A/B测试方法并没有考虑到这个问题,以至于最后得出的结论跟实际情况差异巨大。 要解决这个问题,对采样、聚类、流量分割等要求非常的高,这也是为什么A/B测试工具不能像很多统计工具一样,埋个点看数据,再根据数据反推业务逻辑,而是要充分与业务结合,从一开始就应该考虑业务策略,让用户去选择适合其口味的产品。 现在的创业者面临着前所未有的竞争压力,好的想法与用户接受的想法有着各种不可逾越的鸿沟。特别是伴随着激烈的竞争,谁能领先一步可能就变成了赢者通吃的局面。
相关专栏: [A/B]那些年,我们追过的AB Testing (一) | [A/B]那些年,我们追过的AB Testing (二)从“People you may know”到growth hacking
【冒烟测试】
冒烟测试源自硬件行业,对一个硬件或者硬件组件改动后,直接给设备加电,看看设备会不会冒烟,没冒烟,就表示待测组件是通过了测试。
目的是确认软件基本功能正常,可以进行后续的正式测试工作。
TDD 测试驱动开发
Java程序员修炼之道 测试驱动开发章节
TDD带来的好处
- 更清晰的代码 只写需要的代码
- 更好的设计 有些开发人员管TDD叫测试驱动的设计
- 更出色的灵活性 TDD会鼓励按接口编码
- 更快速的反馈 不会直到系统上线才知道bug的存在
红 - 绿 - 重构循环
- 先编写不能通过测试的红色代码,就是一个简单的思路编写
然后修改,让测试通过,然后完善设计,进行重构编写,又进入红绿阶段,然后再重构
重构是为了通过测试你写的快速实现,重构减轻自己和别人的技术债务(临时凑合出来的设计或代码将来会付出更多的工作)
- 有了通过测试, 就可以放心的重构,应该实现的业务逻辑就不可能会被忽视
多个测试用例 为了覆盖更多情况
- 按照TDD风格,就应该为之前编写的测试用例,进行多路径全覆盖,这个测试依然是红绿重构循环。
深入思考 红 绿 重构循环
- 失败测试(红)
- 一些开发人员喜欢编写编译失败的测试,喜欢等到绿色步骤才提供实现代码
- 也有一些开发人员喜欢先把测试调用的方法签名写出来,这样虽然编译能通过,但还是失败
- 通过测试
- 这一步应该尽量少写代码,只要能测试通过即可。
- 重构
- 许多地方需要重构,一般是: 去掉硬编码的变量,
- 或把大方法拆分,对于面向对象来说应该遵循 SOLID 原则 解释SOLID原则
- 可以把通用的设置和拆卸代码提取出来。可以重命名测试,以便于更准确地反应他的意图,根据静态分析工具例如
CheckStyle
FindBugs
- 应该尽可能的遵守单个测试循环的开发模型,不要同时开多个测试循环,一堆红色
什么是TDD
百度百科词条, 简单来讲就是红绿循环, 红 绿 红...
TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。
TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。
- 个人理解:引用Mockito框架中的 "when thenReturn" and "when thenThrow“ 由预定输入,运行方法或模块后,需要返回预定的数据或者抛出预定的异常,这就是已经写好了测试
- 然后根据测试原型,去思考真正的功能代码的实现,当代码实现后,能够通过之前写的测试就代表着一个方法或模块的开发成功,然后开发下一个
- 要想做到这样的地步,首先基础的环境要思考好,耦合的问题要明确,确定公共模块之后,再一个个的TDD进行开发。一个很好的思想,不用担心你之后的改动会让代码变得丑陋不堪
优点:在任意一个开发节点都可以拿出一个可以使用,含少量bug并具一定功能和能够发布的产品。
缺点:增加代码量。测试代码是系统代码的两倍或更多,但是同时节省了调试程序及挑错时间。
单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。
比如对函数abs(),我们可以编写出以下几个测试用例:
输入正数,比如1、1.2、0.99,期待返回值与输入相同;
输入负数,比如-1、-1.2、-0.99,期待返回值与输入相反;
输入0,期待返回0;
输入非数值类型,比如None、[]、{},期待抛出TypeError。
把上面的测试用例放到一个测试模块里,就是一个完整的单元测试。
TDD实践
测试技术
测试替身
泛指任何出于测试目的的替换真实对象的假冒对象,为了解决测试代码的依赖项问题。
四种方式: 虚设,伪装,存根,模拟
虚设对象
- 他是用来填充参数列表,填补那些总也不会用的必填域。大多数情况下,甚至可以传入null,就是把需要的参数虚拟出来
- 只是为了避免NPE,让代码能跑起来
存根对象
- 用来代替真实环境对象,需要有做出相同响应的对象,就是存根对象
- 将一些外部类或三方资源,写一个类,以及对应的方法,来提供测试运行
伪装替身
- 伪装替身,可以看作是存根的升级。他做的工作几乎是和生产代码是一样的,单位了满足测试需求也会使用便捷的方式
- 例如 内存数据库HSQLDB 的使用,
模拟对象
- 存根对象的调用通常会返回形同的结果。所以不能模拟任何与状态有关的行为,模拟对象就能够更好的胜任
- 在准备要用的模拟对象时,告诉他会有哪些调用,以及对应的相应,模拟会和DI结合更好。可以用一个虚拟的对象,这个对象完全按照已知方式行动
- 模拟类库:Mockito官网
- 调用mock()方法创建模拟对象,并将模拟目标类型的class对象作为参数传进去。
- 然后要把模拟对象需要的行为记录下来,通过 when方法表明要记录哪些方法的行为,然后用thenReturn方法指定期望结果。