Tag: 质量保证

开发者工具箱

质量是我们使用工具的结果。 我们对它们越熟悉,结果就会越好(或更快)。 当然,使用最少的工具集可以取得很多成就,但是要提高生产力,我们应该始终努力掌握当前的工具,并找到可以改善工作流程的新工具。 我一直在寻找新工具,所以如果您有我不使用的工具,请告诉我。 事不宜迟,这是我的工具箱: GUI工具 1密码 保存您的密码并保存。 我使用了不同的密码管理器,但是10多年来我一直使用1Password。 短跑 曾经需要查找文档吗? 我在Dash中进行。 如果文档还不存在,我将导入它们。 这样,它们就可以脱机使用,并且所有集成(例如Xcode)都使用法变得更好。 小飞贼 想知道哪些应用程序尝试执行网络请求? 您要控制它们吗? 这是给您的工具。 我已经使用了多年了,它并没有让我失望。 网络链接调节器 作为移动开发人员,我们经常忘记,我们的应用程序未与稳定的互联网连接一起使用。 要在Macbook上复制它,我们可以使用Apples Network Link Conditioner。 只需按照您希望的方式更改网络,您的整个Mac都将具有此连接(因此,如果丢弃所有程序包以查看会发生什么情况,则在等待时无法读取reddit)。 爪子 有很多应用程序可以发送HTTP请求。 我用爪子。 使其比POSTman 更好的主要功能是链接请求。 这样,我不必每次都进行身份验证。 取而代之的是,我只运行一个命令,它执行了我需要的一切。 颤动 到目前为止,这是我最喜欢的笔记工具。 您不仅可以按集合(和子集合)对笔记进行排序,甚至还可以使用不同的单元格,这些单元格中包含代码,降价,文本等。 让它将整个注释呈现为pdf,就可以了。 里德 作为开发人员(尤其是移动开发人员),我们必须与时俱进。 通常,我们可以通过跟踪博客来做到这一点。 我通过使用Reeder来做到这一点。 这是一个汇总RSS feed的不错的小工具。 揭示 曾经有视觉缺陷吗? 是否曾与UX设计师合作? 显示是我的选择。 在一个新的代码库中,我可以启动它,查找带有错误的正确视图,找到类的名称,然后知道从哪里开始。 另一方面,借助UX设计器,我们可以坐下来实时更改属性(包括自动布局)。 真有用! 草图 每当我执行任何UI工作时,我都会在Sketch中进行。 它是如此易于使用,没有理由不这样做。 请注意,它仅是矢量,因此,如果要更改任何图像,则必须使用其他内容。 源树 […]

使用iOS ReplayKit屏幕记录您的应用程序以进行错误报告

继续探索一些不常见的iOS框架的尝试,我们将尝试研究一个有趣但不受欢迎的候选者ReplayKit 。 ReplayKit使应用程序开发人员可以在其应用程序中记录活动的视频。 您也可以使用麦克风捕捉声音。 此框架自iOS 9起可用。从iOS 10开始,此框架使您可以为视频添加面部时间记录(例如实时评论)。 您甚至可以现场直播该应用程序的屏幕录像。 在wwdc会议中,Apple主要强调使用ReplayKit从游戏内部录制/直播您的游戏。 在任何应用程序中使用ReplayKit的一种可能性是错误报告。 如果测试人员可以选择记录导致错误的流程以及对缺陷的解释,那么事情会变得很容易。 但是您将无法使用ReplayKit报告任何崩溃。 我们稍后再讨论。 让我们来看一个示例,展示如何在这种情况下使用ReplayKit 。 项目概况 我们的项目由一个视图控制器组成,该控制器在表格中显示书籍及其作者的列表。 由于没有可供浏览的详细信息屏幕,因此当您单击书本条目时,在表格视图单元格上显示选择内容毫无意义。 但是默认情况下,表格视图单元格是可选的。 这可能是我们试图报告的错误。 BookListVC :显示书籍和作者的列表。 我们完成的BookListVC看起来像这样。 设置屏幕录像机 要设置屏幕录像机,我们使用ReplayKit的RPScreenRecorder类。 var screenRecorder:RPScreenRecorder? RPPreviewViewControllerDelegate RPPreviewViewController的代表在被关闭时会收到通知。 从屏幕快照中可以看到,有两种方法可以关闭视图控制器,既可以将记录保存为照片,也可以选择不选择。 如果应通知您的视图控制器如何解雇预览视图控制器,则应使用以下委托方法。 func PreviewController(RPPreviewViewController,didFinishWithActivityTypes:Set ) 从活动类型中,您可以找出如何解雇控制器。 如果集合包含saveToCameraRoll,则记录已保存到相机胶卷中。 如果集合为空,则仅关闭预览视图控制器。 如果您不熟悉活动类型,请遍历UIActivityType并内置活动类型 。 如您所见,预览视图控制器已关闭。 当应用程序导航到预览视图控制器时,我们将隐藏包含记录指示的窗口。 一旦将其关闭,就必须显示它,因为它是主UI的一部分。 您可以在下面查看我们的应用程序的录像。 崩溃报告失败!!! 现在回到为什么无法使用ReplayKit记录崩溃的原因 。 如果应用程序崩溃,整个录制流程将中断,并且永远无法将录制内容保存到“照片”中。 同样,涉及到移至后台然后弹回应用程序中的错误也无法正确记录。 在应用程序进入后台之前和应用程序进入前台之前,您将获得记录,而不是在应用程序外部花费的时间。 如果需要更清晰的说明,则可以自由浏览源代码 。 参考文献 ReplayKit上线– WWDC 2016 […]

在公司内部同步任务

我们的iOS分支模型 团队越大,当多个人在同一个代码库上工作时,发生问题的可能性就越大。 为了保证无障碍和协作的工作流程,仅知道您的git命令并不会削减它。 因此,有必要定义一个分支模型,以适应内部流程并限制从一群同步工作的人中出现的复杂性。 在Wolox,我们的目标是使开发人员更轻松地管理分支机构,同时在将构建发送给质量保证(QA)部门进行测试时,还节省了时间。 结果? 通过实施此模型,我们的产品质量得以提高,因为质量保证可以使用更完整的方法进行测试。 史诗(用户)故事 我们在iOS部门Wolox的分支模型基于Epics(即用户故事)的概念。 存在此类概念的几种不同定义,但是在Wolox,我们将它们定义为一组任务,这些任务具有完整的功能,可以为最终用户增加价值 。 史诗只有在其包含的所有任务完成后才有意义。 质量保证(QA) 与史诗打交道的主要优点之一是简化了开发人员和测试人员的质量检查流程。 在此模型中,一旦完成,我们就会向质量检查小组发送史诗。 这样,开发人员就不必为每个任务构建一个.ipa,从而节省了时间,并且质量检查团队可以测试其全部功能及其组件之间的交互。 这简化了两端的过程,并使测试人员的工作更有效,从而提高了产品的整体质量 。 我们的分行 主 在我们的master分支中,我们找到了最新版本。 该分支应始终包含工作和可交付的代码。 开发人员 开发分支从母版分支出来。 在这里,我们可以找到质量检查已批准的史诗。 在Wolox,我们使用Scrum,因此在每个sprint结束之后,在检查了此处合并的不同史诗是否相互兼容之后,我们将此分支合并到master。 根据您的方法或项目的具体情况,一旦向客户显示进度(内部或外部),您也可以合并以掌握。 请记住,master必须始终包含正确运行的代码,因此在合并时请谨记。 史诗-{史诗名称} 每个史诗分支都包含已被代码审查且提交请求已被批准的提交。 史诗般的所有任务通过我们的代码审查流程后,便会生成.ipa并将其发送给质量检查人员。 记住要先从开发者那里重新定位! *避免合并错误的一个好技巧是拥有受保护的分支。 {epic name}-{feature name} 每个功能都从其对应的史诗分支中分支出来。 在这里,开发人员进行必要的提交以实现任务或功能。 完成后,开发人员将史诗分支作为目标分支,从而打开一个新的请求代码审查请求。 让我们玩这个… 想象一个已经有几个发行版的项目,其中的master和dev是最新的。 在下一个冲刺计划中,我们决定开发三个新功能: 查看重新设计 新视图(视图B) 实施推送通知 因此,我们将根据dev创建3个新分支: 史诗般的屏幕重新设计 史诗般的画面B 史诗般的推送通知 我们必须为每个史诗选择一个所有者,然后由他负责在存储库中创建新分支,以便团队中的每个成员都拥有相同的分支。 此人还将在必要时创建测试计划,并在史诗完成后构建.ipa并将其发送给QA测试人员。 尽管该史诗具有所有者,但这并不排除其他开发人员在功能分支中从事史诗的工作。 同样,在sprint计划中,我们可以为每个史诗定义任务,或将任务留给每个开发人员或一组开发人员。 这些将是我们的epic-screen-B分支的四个功能: screen-B-设计,我们在其中实现视图和前端 […]

如何在iOS应用中利用验收测试

与后端开发等其他领域相比,移动开发是一门新兴的学科。 由于苹果很长一段时间都不关心测试,因此社区开始进行测试的时间很晚。 最初,我们有单元测试工具,我研究过Swift中的单元测试和Objective-C中的单元测试。 进行单元测试很棒,但是顾名思义,它只是测试单元。 因此,我们继续寻找并找到了黄金大师测试。 另一个提高我们质量的好工具。 最后,我们可以确保我们的用户界面是正确的。 但是拥有正确的UI是否意味着我们的应用正在执行应做的事情? 那么,我们应该如何测试整个应用程序呢? 我们已经进行了UI测试。 太好了,我们可以确保我们的应用正确无误。 为我们的应用程序编写了一系列测试,大概两年了(包括2个iOS和Xcode更新),我们意识到: UI测试缓慢,不稳定且难以维护 这么结束了吗? 我们必须忍受这些缓慢的测试,还是可以以某种方式改进它们? 让我们看一下UI测试为什么会这样。 UI测试 速度 Apple在UI测试中的解决方案是运行两个单独的进程。 每当测试请求XCUIElement时,TestProcess都会从原始应用程序获取整个应用程序状态。 然后它将执行整个状态的搜索查询,并列出所有匹配的元素(通常只有一个,但是在找到第一个元素之后仍会继续)。 知道了所有这些步骤之后,我们就可以知道在此架构内的时间: 将AppState创建为XCTest的树 将AppState传输到TestProcess 查询整个AppState 使用Xcode 9,情况发生了一些变化。 它不是在TestProcess中执行查询,而是传输查询,而应用正在执行它。 此外,您可以使用“ .first”在树中找到第一个元素,然后立即返回。 这使UI测试更快,但是并没有我们希望的那样快。 而不是运行60分钟,他们可能需要52分钟。缓慢测试的另一个原因是动画。 您无法检查它们是否为真,因此可以选择停用它们: UIView.setAnimationsEnabled(_ enabled: Bool) 我不喜欢这种方法,因为您需要在生产代码中实现它,并且可能只有使用动画时才会出现错误。 最后,您将不得不考虑收益并决定是否要冒险。 稳定性 研究了速度问题后,为什么UI测试会出现问题? 由于测试是在自己的流程中运行的,因此我们知道它们必须同步。 但是为此,过程本身需要相互查找。 只要不是这种情况,测试就不会在您的应用程序内无故失败。 这不仅可以在测试的第一次开始时发生,而且可以在中间发生。 每当您的应用重启时,都需要找到该应用进程。 此外,有时由于意外的应用程序行为,导致测试运行不同步。 这可能只是系统对话框弹出而您不处理它,或者网络连接中出现小错误,但最终结果可能是毁灭性的。 知道我们的测试不稳定,就意味着每当运行失败时,就需要进行无休止的调试。 这可能是测试,但通常只是某种时机,(在测试内)意外行为,或者只是Xcode起作用。 但这仍然很耗时。 可维护性 在“屏幕对象”中,我们深入探讨了如何维护测试。 即使我们尝试坚持使用它们,我仍然经常看到与应用程序本身无关的代码。 .tap()之类的函数调用可防止测试松动。 用户界面的微小变化可能会杀死该屏幕上的所有测试。 […]

使用页面对象模型简化iOS UI测试

为什么还要编写测试呢? 让我们从基础开始,为什么我们甚至需要编写测试? 即使我是编写测试的坚定支持者,但我确实理解有时候由于各种原因,没有足够的时间或资源可以专门用于测试,最常见的情况是缺乏对重要功能的理解,或者换句话说,缺乏公司文化。 通常是我们开发人员必须说服我们的经理我们需要编写测试。 另一方面,有很多开发人员根本不相信编写测试,或者只是出于某种原因不喜欢编写测试。 如果您是这些开发人员或管理人员之一,我将请您仔细考虑以下事实。 在医院洗手是相当近期的做法。 直到1847年,匈牙利医生Ignaz Semmelweis才提出医护人员洗手以降低医院死亡率的想法。 他的想法与当时的科学观点和医学观点相矛盾,并被当时的医学界完全拒绝。 由于遭到拒绝和嘲笑,他感到神经衰弱,并在庇护中死亡。 医学界花了很长时间才开始将洗手作为强制性做法。 毋庸置疑,从那时起,洗手挽救了无数生命,而提到的医生是现代英雄。 杀手bug 我希望我能说,没有人为了让我们(软件开发人员)能够学习到有关编写测试的重要性的类似课程而死,但这已经与臭名昭著的计算机控制放射治疗机Therac的 “杀手臭虫”发生了-25 ,这会导致它发生故障,并给至少6名患者带来大量(有时甚至是致命的)辐射剂量。 如果以适当的方式对Therac-25的软件进行了测试,也许可以避免发生这一系列可怕的悲剧。 测试iOS应用 软件开发社区中有关自动测试的情况看起来像19世纪后期的医学界,在iOS应用程序开发社区中尤其如此。 编写任何类型的测试通常都是iOS应用开发的事后思考,特别是在较小的团队中。 实际上具有大量单元测试的某些项目通常会完全省略UI测试。 作为iOS开发人员,我们的工作与其他软件开发人员没有任何不同,我们应该像其他开发人员一样坚持经过时间验证的做法,并通过测试彻底覆盖我们的代码。 我们可以使用的某些工具可能还不如XCUITest (我在看着你! ),但这并不意味着我们不能在它们之上构建并解决眼前的问题,毕竟,这就是我们要做的正在付款。 在BUX上进行测试 当我开始在BUX工作时,我被分配给一个经验丰富的iOS开发人员团队,他们准备开始构建具有挑战性的新iOS应用程序。 团队已经使用当前的BUX应用程序设置了很高的质量标准,该应用程序已经在App Store上运行了几年,并且非常稳定,有成千上万的用户,几乎没有崩溃。 毋庸置疑,这种稳定性是严格的测试程序的产物,我们也在新应用程序的开发过程中加以应用和改进。 新应用,新挑战 我们正在构建的新应用是下一代股票交易应用。 它是从头开始设计的,其任务是抽象出股票交易的复杂性,将其带给以前从未交易过的人们,同时使用户界面尽可能直观,并为其添加独特的社交组件。 有很多重叠的实时事件,例如股票报价更新,账户余额更新,交易执行,社交事件等,它们可以在一瞬间发生并动态影响用户界面,有时一次会发生多个事件。 另外,可以从应用程序中的多个点触发很多自定义流。 我们的解决方案 为了降低复杂性,我们将应用程序分为几个模块/框架,一个包含核心业务逻辑,一个用于发出和发送http请求,另一个用于Web套接字事件观察,等等。 通过使用单元测试,测试这些框架非常简单,单元测试覆盖了它们的100%。 当要测试应用程序本身时,出现了一个大问题。 测试应用程序的某些部分非常简单,我们的逻辑控件已从其支持的视图中分离出来,因此我们能够通过使用单元测试轻松地涵盖其中的大部分内容。 另一方面,端到端测试所有UI流程并不是那么简单。 手动测试它们会花费时间,消耗人力并且容易出错。 另一方面,使用XCUITest进行自动UI测试并不是有史以来最好的开发人员体验。 有一些出色的iOS UI测试框架可用,但是我们觉得其中大多数都不适合我们,或者仅仅是一个过大的选择,因此我们决定构建自己的简单且最小的iOS UI测试框架。 我们正在尝试做的是通过控制应用程序接收的所有数据,以一种用户使用应用程序的方式来模拟应用程序的使用,但是在受控环境中。 在单元测试的情况下,通过模拟和存根实现非常简单,但是在UI测试的情况下,则变得更加复杂,因为您没有相同级别的访问应用程序代码的权限。 iOS App及其UI测试本质上是两个独立的过程,它们进行通信的唯一方法是在测试开始时通过XCUIApplication变量传递一些参数。 有一些第三方解决方案即使在应用程序和UI测试目标已经运行后也能在它们之间传递数据,但是我们认为这太过hacky和容易出错,因此我们围绕此约束构建了框架。 页面对象模型 我们的解决方案基于Page Object […]

如何在iOS测试中使用Chaos

您听说过无穷大的猴子定理吗? 内容如下: “如果您让猴子在打字机上敲击随机键,在无限的时间内,它会扑灭任何预期的书面文字” 还有其他版本使用无限数量的猴子而不是时间。 作为应用程序开发人员,我们有类似的情况。 我们的应用程序被大量以无法想象的方式使用我们的应用程序的用户使用(好吧,他们被编号了,而不是猴子,但是仍然相似。) 结果,他们将发现我们从未预料到的错误。 那么我们该怎么做呢? Netflix创造了一个新名词:混沌工程。 这样做的目的是在生产代码中引入混乱,以发现系统在出现故障时的行为。 他们发表了他们的混乱猴子,杀死了他们生命系统的实例。 我们也许可以在后端系统上使用它,但是总的来说,我们的应用程序有其自身的问题,我们不能仅仅在用户使用它们时就杀死它们;)。 所以,我们能做些什么? 单元测试 在为算法编写单元测试时,通常必须减少输入值,因为它们可能很大。 相反,我们考虑一些极端情况并进行测试。 可悲的是,这可能导致我们遗漏了一些错误。 考虑到上述在测试中添加受控混乱的想法,我们可以开始使用特定范围内的随机值。 这些值需要生成,并且我们的算法必须包含一个条件(意味着条件始终为真)。 幸运的是,我们不必自己写所有这些随机性。 SwiftCheck已创建为我们做到这一点。 让我们开始吧! 阅读以下说明时,请考虑将电子邮件作为我们的域结构: 结构电子邮件{ var local:字串 var host:字符串 var tld:字符串 } 发电机 在SwiftCheck中,您可以使用生成器来创建任意数据。 尝试生成电子邮件地址时,我们必须生成三个部分:本地,主机和TLD。 本地部分可以包括大写和小写字母,数字和某些种类的字符。 完成此操作后,我们可以构建库并以通常的方式包括它们: 迦太基建造 完成所有这些之后,我们可以添加相应的测试: 结论 即使是最优秀的开发人员,也无法预测其应用程序可能具有的所有状态。 这导致没有测试所有内容。 由于没有人是完美的,并且我们无法测试所有内容,因此我们的应用程序容易出现错误。 找到这些错误很困难,但是混沌测试可以提供帮助。 在单元测试中,我们可以在测试算法时测试各种属性。 在UI测试中,我们可以使用猴子来完成应用程序的操作,这是我们从未想到的。 听起来需要做很多工作,但是由于这可以防止生产中的重大错误,因此我认为这是值得的。 如上文所述,它甚至可以用于查找生产中的错误。 如果您感兴趣,它是UIWebView。 从iOS 9开始,似乎每个导航都会创建很多手势识别器。 过渡到其他页面时,这些页面不会被释放,因此会保留下来。 当您触摸屏幕时,所有这些动作都会使主队列超载,从而使您的应用无响应。 最后,看门狗杀死了它。 上一篇:黄金大师测试

并行测试:更早获得反馈,更快发布

作为负责测试Azimo iOS应用程序的唯一人员,我遇到了各种问题。 当我四年前开始在Azimo工作时,测试是100%手动的。 一个完整的测试周期最多可能需要两天的时间。 某些功能根本没有经过测试,更不用说在不同的设备和操作系统上了。 如今,只有15%的测试是手动的。 自动化使我们更快,更高效。 在2018年,我们99.9%的用户没有崩溃。 但是,由于我们应用程序的复杂性,整个测试周期大约需要八个小时。 这段时间的一半以上是由自动化测试占用的。 鉴于我们每周至少发布一次,因此我们需要找到一种方法来进一步缩短测试周期。 幸运的是,6月5日,一场革命来到了。 在WWDC 2018大会上,Apple宣布支持Xcode 10中的并行测试。这将我们250项自动测试的周期减少到大约55分钟,使我的生活压力减轻了很多。 在本文中,我将指导您了解并行测试的好处,因为我们在Azimo上已经体验过它们。 我将概述测试内容,机器配置方式以及遇到的问题。 我还将提供一些技巧,以帮助您充分利用并行测试。 在Xcode 9中为iOS设备引入了并行测试。从那时起,我们就能够在不同设备上并行测试不同的类。 但是,Xcode 9版本要求我们使用带有适当参数的命令行。 Xcode 10的革命性功能是自动化测试器-能够直接从Xcode级别在多个模拟器上同时运行不同的测试类,而无需人工测试。 就像启用该功能一样简单: 在这种模式下,Xcode将创建同一模拟器的多个克隆(例如,如果我们使用iPhone X模拟器,则Xcode将创建模拟的iPhone X克隆)。 这仅适用于模拟设备。 我们将在本文后面讨论物理设备上的并行测试。 好处: 简单直观的配置 更快的测试执行 更快的反馈 允许更多版本 同时检查多台设备上的应用程序服务器(请求,超时等) 无需创建其他测试目标,即可在它们之间分配测试类 与CI完美集成 缺点: 如果后端服务器/应用程序服务器不稳定,则可能发生超时(同一时间的多个请求可能会导致更长的响应) 保持模拟器稳定所需的大量处理能力 脱皮-如果发生上述任何问题 克隆相同的设备/系统配置,无法同时在几种不同的配置上进行测试(我们必须使用命令行) 假设: 使用并行测试必须满足的基本条件是测试用例的独立性。 例如: 我们不能仅在测试A完成后才开始依赖测试B 更快的执行速度或测试B的结果不会影响测试A的结果,反之亦然 有用的参数: maximum-concurrent-test-simulator-desstinations NUMBER要在同时启用并行测试 的情况下测试的模拟器目标的最大数量YES | NO覆盖方案parallel-testing-worker-count方案中的每个目标设置NUMBER确切的测试数量并行测试期间将产生的测试运行程序maximum-parallel-testing-workers编号并行测试期间将产生的最大测试运行程序数 有效的测试划分 […]

常见的iPhone错误。 适用于质量检查人员和iOS开发人员的有效指南。 第1部分

常见的iPhone错误。 适用于质量检查人员和iOS开发人员的有效指南。 第1部分 最初发布在 blog.lemberg.co.uk上 。 让我们与您分享以下两篇文章之一,它们揭示了大多数QA和iOS工作流程中通常存在的常见错误。 在本节中,我们将演示我们在项目中遇到的错误数量。 例如,四个项目充满了小错误,一般时间的30%至40%花费在找出和进一步消除这些错误上。 以下示例包含特定问题的屏幕截图。 本文的目的是帮助iOS开发人员和质量检查测试人员展示一系列常见的错误,为了使您的 项目 更加成功 ,将来必须避免这些错误 。 开发人员可以发现本文很有用,因为它有助于在质量检查人员发现它们之前就发现它们,因此既可以预防又可以节省时间。 如果您是质量检查测试人员,则可以扩大搜索范围并更快地找到这些常见的错误。 让我们仔细看看这些错误。 1.输入字段/表格 期望 如果至少有两个顺序输入字段可用,请通过点击键盘上的“ 下一步”按钮在各字段之间进行转换 填写最后一个输入字段后,“ 下一步”按钮将替换为“完成” 。 点击完成按钮关闭键盘 验证输入字段 输入字符的限制 左右边距相同 光标可见 典型问题 缺少下一个按钮,而是有“完成/返回”等,它关闭了键盘,或者在最坏的情况下根本不执行任何操作 验证缺失 输入字段中的文本可能会超出字段边界,左右边距可能会有所不同 光标丢失或透明 缺少限制 由于禁用了“下一个”按钮,因此无法转换到下一个字段 2.现场验证 期望 验证所有必填字段/复选框/下拉列表等 如果验证失败,则显示带有文本的弹出窗口,例如:“字段名称不能为空” 正确的验证顺序:逐步-在客户端和服务器端从上到下,从左到右。 典型问题 字段验证顺序不正确 验证文本不正确(同一表单中的字段不同) 来自服务器端的错误消息被忽略 3.键盘 期望 键盘隐藏有: 点击键盘上的“完成”按钮 在键盘上点击但在屏幕内 打开侧边栏(汉堡)菜单 移至其他画面 开幕日期/时间选择器 键盘没有与当前处于活动状态的输入字段重叠,因此会进行自动滚动,因此活动字段保持在键盘上方 […]

生产中的断言

后端工程师确切地知道他们的服务正在发生什么。 他们实时了解其QPS,内存占用量,错误率和CPU利用率。 如果出现严重错误,它们甚至会自动进行分页,因此他们可以快速响应。 不幸的是,iOS工程师通常只有崩溃报告以及一些产品指标。 通常,我们会在用户报告错误时或更糟地在用户发布不正确评论时了解错误。 我们可以做得更好。 断言是条件检查,可确保您的代码按预期运行。 可能,您的代码库中已经有一些。 他们检查永远不会失败的条件,如果失败,则表明代码中存在严重错误 。 但是,断言在生产中已被删除,在现实世界中没有任何影响。 在我从事的每个项目中,我都添加了一个自定义Log类型,该类型使断言报告生产中的错误。 大多数崩溃报告框架都有报告非致命错误的能力,因此实施此操作很简单。 这是使用Crashlytics的示例: 枚举 Log { 静态 函数断言 #if调试 Swift.assert(condition(),message(),file:file,line:line) #其他 如果 !condition(){ 让域= message() let error = NSError(domain:domain,code:domain.hashValue,userInfo: nil ) Crashlytics.sharedInstance()。recordError(错误) } #万一 } 静态 函数 assertFailure ( _消息: @autoclosure ()->字符串,文件:StaticString = #file ,行:UInt = #line ){ Log.assert( false ,message,file:file,line:line) } } 在DEBUG […]

iOS应用程序的自动UI测试

在充满竞争的世界中,公司希望比以往更快地发布其软件。 原因是他们很害怕。 害怕屈居第二或失去市场份额。 试图越来越快地做出决定,通常将单元测试定义为“稍后”。 开发人员无需测试即可创建大量代码,并且对此感到非常满意。 X天到了,该发布产品了。 由于该软件还不算太大,因此他们可以在发布期间进行手动测试。 这里没事! 认真地说,手动测试很棒! 问题在几个月后开始。 在某些时候,手动测试花费的时间越来越长。 您的应用变得更加复杂,并具有更多功能。 此外,您必须检查回归。 这是他们先前的质量下降开始显现的地方。 发行周期突然不需要几个小时。 相反,它需要几个星期。 每两周发布一次,然后弹出一个问题: 测试使我们无法经常发布,该怎么办? 这是一个具有多个选项的好问题。 只需忽略减少测试工作量的想法即可。 这是肯定的办法。 另一种选择是从开发人员级别开始。 让我们添加单元测试! 哎呀……既然我们忽略了它们,那么一开始,我们的代码就不是那么容易测试了……要花一些时间为单元测试添加基础。 那我们还能做什么? 在整个过程中,我们可以添加某种测试意识形态。 第一步是使用BDD进行此操作。 但是,这不会以快速而肯定的方式帮助我们。 如此众多的公司开始使用自动化的UI测试。 让计算机执行与手动测试应用程序相同的步骤。 我们可以每晚(或每次提交?)运行这些测试,这比让团队坐下来进行体力劳动要快得多。 在继续之前,让我这样说: 自动化的UI测试并不是解决问题的灵丹妙药! 但这是整个机器的齿轮。 因此,仅因为这不是您的灵丹妙药,不要完全忽略它。 iOS上有很多不同的方法。 有些是本地人,有些则更少。 让我们单独看一下。 XCUI测试 几年前,苹果公司停止了其JavaScript自动化框架,并用XCUITest代替了它。 这是Apple支持的本机库,这意味着您可以用Objective-C或Swift编写UI测试。 我必须缠住头的一件事是,您不必检查包含值的元素(标签,按钮等)。 而是,您检查屏幕上是否存在该值。 因此,在测试是否显示文本时,它看起来像这样: XCTAssert(app.staticTexts [“ Welcome”]。exists) XCUITest在其自己的进程中运行。 这既有优点,也有缺点。 它可以看到屏幕上的所有内容,但您无法检查内部应用程序的状态是什么。 这非常好,因为它可以防止开发人员犯涉及普通用户没有的知识的错误。 另一方面,处于单独的进程也意味着需要一些时间来同步应用程序状态。 这会花费时间并减慢测试速度。 此外,当执行一些需要时间的操作时,由于XCUITest无法找到请求的元素,因此可能导致错误。 要在失败之前等待一小段时间,我们可以等待元素出现: […]