首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为你的 iOS App 构建分离测试

为你的 iOS App 构建分离测试

作者头像
顾翔
发布2019-12-12 12:00:19
4580
发布2019-12-12 12:00:19
举报

顾翔老师开发的bugreport2script开源了,希望大家多提建议。文件在https://github.com/xianggu625/bug2testscript,

主文件是:zentao.py 。bugreport是禅道,script是python3+selenium 3,按照规则在禅道上书写的bugreport可由zentao.py程序生成py测试脚本。

来源:http://www.51testing.com

  分离测试是为应用提供哪种方案对于给定目标表现更优决策的方法。

  我们为应用的用户以随机的方式分发变量或行为不同的方案,通过收集数据并统计分析,确定哪个方案表现的更好。

  本文旨在提供一种结构化组织构建 App 的简单方法,以便你可以在使用分离测试时能获得整洁而可扩展的代码。

  本文提供了一些技巧和示例,你可以把它当作实际应用下的指南。

 一般性问题

  使用分离测试(也称为 A/B 测试),我们拥有无限的测试可能性。但总的来说,我们可以按以下顺序对分离测试所需进行的修改进行分组:

  内容变更:仅更改指定视图中的特定部分或根据给定的测试添加或删除特定内容。

  设计变更:测试颜色、排版或布局等变化会如何影响用户的行为。

  行为变更:根据拆分组来更改按钮操作或屏幕显示的行为。

  但其中问题在于,所有这些类别中可能会出现大量重复的代码。

  我们需要为测试创建一种易于维护的代码结构,这是因为我们需要不断添加新测试或删除修改旧测试,因此需要考虑它的可扩展性。

 创建拆分离测试管理器

  我们将尝试创建一个通用解决方案并将其用于上述的变更类别。

  首先我们创建一个协议来定义拆分测试对象必须符合的规则:

protocol SplitTestProtocol {  associatedtype ValueType: Any  static var identifier: String { get }  var value: ValueType { get }  init(group: String)  }

  value 表示一个通用值,该值将由具体的分离测试对象实现。它将对应于我们为目标目标测试的颜色,字体或任何属性。

  identifier 将作为测试的唯一标识符。

  其中的 group 将代表当前正在测试的值。它可以是 a 和 b 或 red 和 green,这完全取决于为给定测试确定的值的命名。

  我们还将创建一个管理器,负责根据与测试标识符相关的数据库中存储的组获取拆分测试的值:

class SplitTestingManager {  static func getSplitValue<Value: SplitTestProtocol>(for split: Value.Type) -> Value.ValueType {  let group = UserDefaults.standard.value(forKey: split.self.identifier) as! String  return Value(group: group).value  }  }

内容变更

  假设我们正在开发阅读类 App,我们决定为用户提供免费的电子书。

  我们的营销团队决定首先通过要求用户提供以下内容来创建分离测试:

在社交媒体上分享我们的应用

  或者

订阅我们的新闻

  这两种情况都使用相同的 View Controller,但设计的一部分会随情况而改变。在我们的 View Controller 中,我们将创建一个 Content View 区域并在其中添加不同的内容。

  在这种情况下,我们需要创建两个不同的 View:一个用于社交共享,另一个用于新闻稿,并分别添加到 View Controller 的 Content View 区域内。

  首先创建一个保存 View Controller 样式的对象,并将其传递给 View Controller 的初始化器:

struct PromotionViewControllerStyle {  let contentView: String  }

  基本上,样式对象当前包含我们的 PromotionViewController 中 Content View 的 xib 名称。

  我们可以创建遵循 SplitTestProtocol 的测试对象:

class EBookPromotionSplitTest: SplitTestProtocol {  typealias ValueType = PromotionViewControllerStyle  static var identifier: String = "ebookPromotionTest"  var value: PromotionViewControllerStyle  required init(group: String) {  self.value =  group == "social" ?  PromotionViewControllerStyle.init(contentView: "\(TwitterView.self)")  : PromotionViewControllerStyle.init(contentView: "\(NewsLetterView.self)")  }  }

  现在我们可以根据我们的分离测试轻松地向我们的 View Controller 显示新闻或社交共享的内容:

@IBAction func presentNextVc(_ sender: UIButton) {  let style = SplitTestManager.getSplitValue(for: EBookPromotionSplitTest.self)  let vc = PromotionViewController(style: style)  self.present(vc, animated: true)  }

func addContentView() {  let nib = UINib(nibName: style.contentView, bundle: nil)  let view = nib.instantiate(withOwner: nil, options: nil)[0] as! UIView  contentView.addSubview(view)  view.bindFrameToSuperviewBounds()  }

设计变更

  通常,在电商 App 中,更改号召性用语的按钮设计很受欢迎,即 添加到购物车 或 购买 按钮,它们能够更加吸引用户,从而能获得更多点击。

  我们总是可以使用我们需要的任何对象进行分离管理,在这种情况下,假设我们需要一个保存购买按钮颜色值的对象:

class PurchaseButtonColorSplitTest: SplitTestProtocol {  typealias ValueType = UIColor  static var identifier: String = "purchase_button_color"  var value: ValueType  required init(group: String) {  if group == "a" {  self.value = UIColor.red  } else {  self.value = UIColor.green  }  }  }

  如下所示,我们可以简单地从我们的角度来使用它:

let color = SplitTestManager.getSplitValue(for: PurchaseButtonColorSplitTest.self)  purchaseButton.backgroundColor = color

  同样,它也可以测试任何其他属性,如字体,边距或任何其他需要根据我们的测试进行更改的属性。

行为变更

  假设我们打算将 App 中的订阅用户分成两组:

  我们既希望

打开 IAP 视图时显示折扣对话框

  也希望

显示没有任何对话框的默认视图

  我们将使用此示例的策略模式来处理我们的折扣演示。

  策略模式是一种设计模式,用于创建可互换的算法组,你可以在运行时从中选择所需的算法。

  由于我们的 SplitTestProtocol 包含一个通用值,我们可以创建将该策略作为其值保存的分离测试对象:

class DiscountSplitTest: SplitTestProtocol {  typealias ValueType = DisountStrategy  static var identifier: String = "iap_discount_type"  var value: DisountStrategy  required init(group: String) {  if group == "offer" {  value = DefaultDiscountStrategy()  }  value = NoDiscountStrategy()  }  }

  然后我们可以根据具体策略初始化并呈现我们的 View Controller:

init(discountStrategy: DisountStrategy) {  self.discountStrategy = discountStrategy  super.init(nibName: nil, bundle: nil)  }

func presentDiscoutViewController() {  let strategy = SplitTestManager.getSplitValue(for: DiscountSplitTest.self)  let viewController = DiscountViewController(discountStrategy: strategy)  self.present(viewController, animated: true)  }

  我们现在可以轻松地将我们的折扣责任传递给 DiscountStrategy 对象,并根据我们的需求进行扩展,而无需更改 View Controller 里的代码:

protocol DisountStrategy {  func presentDiscountMessage()  }  struct NoDiscountStrategy: DisountStrategy {  // 提供处理非打折的情况  }  struct DefaultDiscountStrategy: DisountStrategy {  // 提供处理打折的情况  }

override func viewDidAppear(_ animated: Bool) {  super.viewDidAppear(true)  discountStrategy.presentDiscountMessage()  }

一般性提示

  当你在进行分离测试时,请务必注意以下几点:

  始终使用 缓存 作为测试值,以使 App 在用户使用的时候保持一致。

  在一次特定测试完成后 清理 测试代码,删除你在项目中为分离测试添加的视图,字体,图像和其他任何资源。

  确保如果出现问题你可以控制并且可以 禁用 A/B 测试。

 总结

  分离测试(也称为 A/B 测试)对于我们的 App 来说是一个强大而有效的工具,但如果我们的代码设计不严谨的话,它很容易使你的代码变得一团糟。

  在本文中,我们创建了一个可以管理分离测试逻辑的通用解决方案。同时还提供了一些真实的 App 示例和实用技巧,以便你可以在给你的 iOS App 进行分离测试的时候参考。

星云测试

http://www.teststars.cc

奇林软件

http://www.kylinpet.com

联合通测

http://www.quicktesting.net

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试培训 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
测试管理
CODING 测试管理(CODING Test Management,CODING-TM)为您提供井然有序的测试协同管理工具服务,从测试用例库管理、制定测试计划,到协作完成测试任务,为测试团队提供敏捷测试工作方式,提高测试与研发团队的协同效率。提供可视化的工作视图以及数据报告,随时把控测试进度和规划。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档