Tag: 测试

Swift中基于属性的测试-使用SwiftCheck

在上一篇文章中,我们描述了一种称为基于属性的测试的测试方法。 我们不用编写示例来测试我们的代码,而是编写输出必须具有的属性。 我们可以继续编写约束该输出的属性,直到我们对我们的软件需要做什么进行准确的说明。 Swift中基于属性的测试—简介 这是Swift进行的基于属性的测试(PBT)系列的第一部分。 在这第一篇文章中,我们将… medium.com 尽管无需任何库就可以执行这种类型的测试,但是有些工具可以帮助我们简化这些任务。 在Swift中,我们可以使用SwiftCheck (一种秉承Haskell的QuickCheck精神的开源库)。 在您的项目中包括SwiftCheck就像使用CocoaPods一样容易。 只需添加pod ‘SwiftCheck’, ‘~> ‘ ,将替换为该库的最新版本。 安装好吊舱,就可以开始了! 使用SwiftCheck编写基于属性的测试 在上一篇文章中,我们使用了String串联示例。 我们可以使用SwiftCheck重写三个基于属性的测试: 让我们分解一下这些测试的结构: 我们必须通过扩展XCTestCase并添加带有test前缀的方法来创建常规的单元test 。 在每个单元测试中,我们创建一个带有String的property ,该property描述我们要测试的内容。 使用运算符<- ,我们调用forAll ,它收到一个闭包。 此闭包接受许多参数,这些参数的类型实现Arbitrary协议。 现在不用担心,该库为我们扩展了基本的Swift类型。 这个闭包的参数将是用于基于属性的测试的随机字符串(在上randomString()文章中,我们是使用randomString()创建的)。 在闭包的主体中,我们执行要测试的方法或函数。 最后,我们不需要编写断言,而是返回Testable表达式。 在我们的例子中,我们从正在执行的比较中返回一个Bool 。 运行这些测试将多次执行我们的闭包。 默认情况下,每个属性都会运行100次,尽管可以增加或减少此数目。 如您所见,使用SwiftCheck编写基于属性的测试非常容易。 在这些系列的最后一篇文章中,我们将展示如何约束这些测试的输入(有时我们可能会对输入类型的某些子集感兴趣)以及如何为我们的自定义类型提供输入。

iOS模拟器中的本地化

您关心自己的应用程序已本地化,对吗? 万岁,你! 但是,仅靠照护还不够,尤其是当您不是唯一正在使用某个应用程序的人时。 让我们通过一些简单的步骤,使在iOS Simulator中查看本地化变得更加容易。 在我说“第一要务”之前,让我们先解决一下:希望您已经在所有地方都使用了自动版式。 如果您不在,没有比现在更好的时间开始过渡了。 标签中的变长文本意味着在某些时候它们会四处移动。 也让其余布局也相应地移动。 回到表演! 一幅图片价值一千个字 第一件事:确保您的UI可以处理翻译文本比预期长得多的情况。 当然,您可以尝试一堆不同的翻译,但是一个快速的近似值是假设所有内容都是当前长度的两倍。 等待。 不,不要开始两次粘贴您的翻译。 当然,您的运行方案中有非常方便的“双倍长度伪语言”,但这不能让您用另一种语言测试双倍长度。 你为什么想这么做? 也许您的系统语言不是您应用的主要语言。 我们将以老式的方式进行处理,并带有启动参数。 编辑方案(“⌘+⇧+ <”或单击“产品,方案,编辑方案”) 选择“运行”操作,然后单击“参数”选项卡 将“ -NSDoubleLocalizedStrings YES”添加为新参数 运行该应用程序,然后点按Tappa 现在,您可以将任何一种语言加倍运行,以真正对您的UI进行压力测试。 👊 您获得了本地化,您得到了本地化,然后… 好的,您的UI可以使用样式和宽限期处理不同长度的翻译。 现在,确保您不会错过任何这些翻译。 回到计划! 编辑方案 选择“运行”操作,然后单击“选项”选项卡 选中“显示非本地化的字符串”选项 当字符串没有翻译可用时,这会将文本变成大写。 您会看到“ USERNAME”跳出来,而不是缺少诸如“ username”之类的占位符短语。 没什么吸引人的UI。 其他名字的玫瑰 所有这些模板讨论,我们甚至都没有尝试在应用程序中查看本地化的文本。 让我们修复它。 进行方案设置! 您可以始终尝试“选项”>“应用程序语言”,但这需要单击,单击,单击。 相反,让我们使用另一个方便的启动参数来指定要使用的语言。 编辑方案 选择“运行”操作,然后单击“参数”选项卡 将“ -AppleLanguages(de)”添加为新参数 要使用德语以外的其他语言,只需将“ de”替换为您选择的语言代码即可。 您可以设置一堆这样的参数并根据需要启用它们,但请记住,您不能同时使用多种语言运行应用程序。 太多的用户界面,很少的代码 您可能已经通过Interface […]

iOS的自动续订

什么是沙盒? 沙盒是一种无需创建金融交易即可测试我们的应用和应用内购买的环境。 使用App Store基础结构但不处理实际付款的测试环境。 而是返回交易,就好像付款已成功处理一样。 使用iTunes Connect创建沙箱测试器 在iTunes Connect中创建沙箱测试程序帐户,您可以使用该帐户在测试环境中运行应用程序,然后再将其提供给用户使用。 在iTunes仪表板上,单击“用户和角色”,然后单击“沙箱测试器”。 单击测试器旁边的添加按钮(+)。 输入测试人员信息,然后单击保存。 对于每个沙箱测试器,您需要收集以下信息: 名字 姓 从未用作购买iTunes或App Store内容的Apple ID或与任何现有Apple ID相关联的电子邮件地址。 考虑为每个沙盒测试器创建一个专用的电子邮件地址。 密码 秘密问答 出生日期 App Store地区 测试订阅 在沙盒环境中测试应用程序时,可自动更新的订阅持续时间会缩短。 此外,测试订阅仅在每个8小时窗口内自动续订每个帐户最多六次,然后订阅将在每个订阅期结束时自动过期。 无论应用程序是否处于活动状态,续订都会自动进行,就像App Store中的续订一样。 这种测试机制的唯一问题是无法选择测试*取消订阅*。 同样,在使用沙箱和TestFlight环境时也无法测试订阅管理。 每次续订都会向应用程序发送交易数据,交易取决于续签发生了多少次。 下一次在应用程序打开进行验证时将进行处理,这些交易会触发另一个密码提示。 此多个密码提示仅在测试中出现。 测试续订和到期 由于时间限制,请使用每月订阅进行测试 订阅每月订阅 关闭应用程式 5分钟后启动应用程序 应用程序将显示密码提示,输入密码 重复步骤2至4 6次。35分钟后,该应用现在应恢复为取消订阅状态,并允许用户再次付款。 测试还原购买 订阅每月订阅 在5分钟内删除该应用 安装应用程序并打开 点击恢复按钮 在这种情况下,应用程序应找到活动订阅以向用户解锁专业内容。 测试跨设备的还原购买 订阅每月订阅 在其他设备上安装该应用 开启应用程式 点击恢复按钮 在这种情况下,应用程序应找到活动订阅以解锁专业内容。 […]

iOS:使用Alamofire + Kakapo在Swift中模拟服务器行为和响应

在Tiendeo Mobile部门,我们一直在寻找新的方法来使我们的应用程序更具可测试性和更好的测试。 让我介绍有关数据层的基本概念。 如果您熟悉Alamofire和AlamofireObjectMapper,则我们的应用程序数据层将使用一个名为AuthenticationSessionManager的自定义Alamofire SessionManager类,该类可实现RequestAdapter和RequestRetrier协议。 我们的AuthenticationSessionManager有自己的请求方法,可以在调用Alamofire请求方法之前检查用户令牌是否有效: 首先,我们创建一个称为AuthenticationSessionManagerTest的单元测试测试类,并实现一个方法,该方法返回无效令牌,并使用Kakapo的Router类实现另外两个方法来设置拦截器,用于两个成功的API调用: 然后,我们需要配置我们的自定义SessionManager以使用Kakapo协议。 我们将创建一个方法来创建自定义URLSessionConfiguration : 并且…我们已经完成了测试的// Given部分: 总结一下:我们已经有一个配置有Kakapo和无效令牌的sessionManager 。 我们还有两个API调用可供拦截。 💪 现在我们必须实现测试的// When和// Then部分。 我们将使用sessionManager向“ _api / Fake”发出请求,该请求将被拦截。 正如我们在文章开头所看到的sessionManager , sessionManager将首先检查令牌,但是令牌将无效…… sessionManager自动向“ _api / TokenNew”请求新的令牌,该令牌也将被拦截。 当获得新令牌时,最终它将调用“ _api / Fake” ,其响应将成功。 🎊 让我们看一下代码: 这是测试的样子! 我们使用expectation来检查响应的值是否与我们为Kakapo路由器设置的值相同。 从这里开始 以此测试为样本,我们可以创建多个测试方案来测试我们的SessionManager,如下所示: 有效令牌 伪API调用成功 要么: 没有令牌 刷新令牌API调用成功 伪API调用成功 要么: 有效令牌 伪API调用响应401 等等 只是改变 //给出条件并向Kakapo的路由器添加新的响应。 希望您发现这篇文章有趣并且对您的项目有用。 任何问题或评论都将受到欢迎! […]

使用iOS项目从Jenkins Jobs提取测试结果

文件,文件,文件。 文档是大型项目中的工件,以确保符合软件开发生命周期(SDLC)。 实际上,所需的文件之一就是单元测试报告。 在这里,我将带您进行2分钟的简短导览,以设置您的詹金(Jenkin)工作,以便生成测试结果报告。 如果您不知道如何为您的项目设置詹金斯工作,则可以在这里查看我的上一篇文章。 我们将使用Jenkins的插件调用Test Results Analyzer。 这给了我们4种漂亮的测试结果可视化效果: 表 线 馅饼 酒吧 转到->配置 。 转到构建后操作 。 选择添加构建后操作->发布JUnit测试结果报告。 输入test-reports / *。xml并忽略其余字段。 (包括红色消息) 现在,触发一个构建以运行该作业,等待它执行所有测试用例,现在您可以从根文件夹中检索.xml文件。 您还将在作业的主页上看到一个新图像。 轻按一下“ 测试结果分析器”即可立即显示可视化效果! 虽然这可能不是我们可以生成的最理想的测试结果报告,但是它为我们提供了足够的基本信息,可以为利益相关者提供简要概述执行哪种测试用例的情况(假设我们已经以TDD和BDD方式很好地命名了测试用例) )。

如何在Swift中应用单一责任原则

有时,当我们学习编码时,很难理解类责任的概念。 这是因为我们的第一个项目变得难以维护,原因是我们的代码中按类包含许多行,更重要的是,它承担了许多责任。 真正了解类责任的一种好方法是考虑可伸缩性。 让我们看一个如何使用它的例子。 但是,在此之前,我想先介绍一些理论并解释为什么这个概念在软件设计中很重要。 每个类在软件项目中负有单个责任的思想,并且将责任封装在一个唯一的类中的想法有一个名称:单一责任原则 这是SOLID软件设计的5条主要原则之一,他们在面向对象编程中尝试定义一个指南,以拥有更易懂,灵活和可维护的软件。 这些原则是: 单一责任原则 开闭原则 里斯科夫替代原则 接口隔离原理 依赖倒置原则 这些概念的作者Robert C. Martin(他写了软件体系结构中最重要的书之一,即Clean Code)谈到“一类应该只有一个改变的理由” ,因此他将责任定义为更改。 例如,让我们考虑一个编译并打印报告的模块。 想象一下,可以出于两个原因而更改这种模块。 首先,报告的内容可能会改变。 其次,报告的格式可能会改变。 这两件事因不同的原因而改变。 一种实质性和一种化妆品。 单一责任原则说,问题的这两个方面实际上是两个单独的责任,因此应该放在单独的类或模块中。 耦合由于不同原因在不同时间发生变化的两件事,将是一个糟糕的设计。 使班级专注于单个关注点很重要的原因是,它使班级更加强大。 继续前面的示例,如果更改了报表编辑过程,则存在更大的危险,即如果打印代码属于同一类,则该打印代码将被破坏。 (示例摘自 Wikipedia ) 如果我们定义班级,知道他们在项目中的职责是什么,我们可以: 轻松了解其在代码各部分中的功能。 更快,更详细地修改现有逻辑。 以较少的问题查找错误或有害行为的来源。 不同类或模块中的抽象逻辑。 拆分时没有重大问题的实现,因此以后可以完全替换它们。 通过类或模块以更有效的方式定义单元测试,因此我们可以测试一小段代码,而无需测试更多的代码。 正如我之前说过的,您可以在类中考虑可扩展性以定义职责。 这就像思考是否可能在我们的项目中修改需求并在我们的体系结构中查看如何进行这些修改一样简单。 例如,如果我们看到要进行小的视图更改,则必须修改或修改业务逻辑,则我们没有正确定义项目中的职责。 让我们看一下Swift中的一个具体示例。 假设我有一个应用程序,它显示了商店中的商品列表。 到目前为止,我只有一个ItemsViewController负责该流的所有逻辑,数据和表示。 同样,当用户选择一个项目时,它也会打印日志。 您可以在https://github.com/fedejordan/SRPExample中查看代码 为此, ItemsViewController使用UITableView在列表中显示项目。 另外,我们使用一个名为ItemTableViewCell的UITableViewCell子类来显示这些元素。 但是,假设我们要更改视图,例如,使用UICollectionView. 在这种情况下会有什么问题? 视图代码与项目数据逻辑非常耦合。 如果我们更改视图,则很有可能也会修改负责该项目的类。 真正的问题在于以下几行: 让item […]

不要依赖临时状态

上一次,我们讨论了构建iOS单元测试的四个简单规则。 我真的很想把所有要做的和不要做的事情放在一起写在一篇文章中,但是阅读起来实在太大了。 所以这是硬币的另一面。 关于您应避免的所有事情的系列文章。 信不信由你,完全有可能编写弊大于利的单元测试 。 在本文中,我们将研究一种依靠临时状态来弄乱单元测试的特殊方法。 什么是临时状态? 如果在使用您的应用过程中可能发生变化,那么就定义而言,这是暂时的或偶然的。 每个应用程序都会在内存或磁盘上存储某种临时状态。 许多应用程序从服务器检索临时状态。 每次您从某个可以写入的位置访问数据时,您都在访问临时状态 。 数据会随着时间变化。 今天得到的可能与明天得到的不一样。 Facebook上的用户可能会说他今天喜欢滑雪,但是明天他会说他喜欢滑雪。 他的爱好是暂时的。 您不能依靠它们随着时间的推移而变得相同。 如果您从服务器上检索他的业余爱好数据,则无法确定会得到什么。 单元测试绝不应依赖临时状态 。 它使他们变得善变。 如果有一天运行它们,它们将提供一个结果。 改天运行它们,它们会产生不同的效果。 单元测试应该是确定性的 这样,我的意思是每次您运行它们时,它们都应始终提供一致的结果。 确定给定单元测试是成功还是失败的事情不应是可能改变的外部事实 。 它应该是您的应用程序所依赖的核心逻辑。 如果单元测试依赖于用户默认设置,本地文件或服务器的响应,则它们不再是确定性的。 这是因为它们的成功或失败不仅仅取决于逻辑本身。 结果,您将无法非常有效地将单元测试用作诊断工具。 您如何知道代码或某些临时状态是否导致给定测试通过或失败? 你不会的 可能永远是。 这种无法确定测试成功或失败原因的能力有时称为脆弱性 。 不稳定测试是由于与被测试代码不直接相关的原因而给出不同结果的测试 。 您绝对想避免这种情况。 这是片状测试的实际外观 假设您有一个应用程序,其中登录用户可以访问某些功能列表。 您可以通过以下方式实现访问授予机制。 如何修复片状单元测试 问题在于缺乏抽象。 shouldGrantAccessToFeatureWith(id 🙂需要知道用户是否已登录,可以通过直接转到用户默认值来进行登录。 如果将相同的逻辑重构为可以被子类覆盖的函数该怎么办? 在编写单元测试时,请始终问自己,该测试采用什么逻辑? 测试逻辑,然后抽象其他所有内容。 下一步是什么? 我目前正在阅读一系列文章,详细介绍在为iOS编写单元测试时应避免的一些体系结构方面的内容。 下一篇文章深入探讨了避免副作用。 目前,您可以了解我的其他一些单元测试内容 我们应该在iOS应用程序中进行哪些单元测试? […]

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

作为负责测试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编号并行测试期间将产生的最大测试运行程序数 有效的测试划分 […]

您的意见不够愚蠢吗? —一种无需模拟器即可运行测试的方法

嗨! 如您所见,这篇文章的标题由两部分组成。 “ 您的观点足够愚蠢 ”是指在项目中的类之间管理代码,这确实是一个有趣的话题,但是还有第二部分-“ 一种无需模拟器即可运行测试的方法 ”。 管理代码是非常简单的主题,您可能知道这部分的内容,但是我如何在没有模拟器的情况下运行测试? 我们不是真的需要模拟器来测试应用程序吗? 原来不是! 您的意见不够愚蠢吗? 这是一个简单的模型,将存储有关一个人的信息。 这里的问题是我们的观点对正在发生的事情了解太多! 我们如何改变它? 让我们看一下MVVM模式,它将使我们可以将这些知识转移到另一个地方。 您可以在此处找到有关架构模式的更多信息 使视图变得愚蠢是获得更易于测试的更干净代码的好方法。 现在,我们可以轻松地测试ViewModel,以查看它们是否按预期工作。 由于我们的业务逻辑与布局分离,这一切皆有可能! 一种更快运行测试的方法! 您可能已经注意到,每次为iOS应用程序运行测试目标时,也会启动一个模拟器。 一段时间后您就习惯了,没关系。 只需要更长的时间。 而且我们还是必须运行模拟器……还是我们? 为什么每次运行测试都会启动模拟器? 好吧……我们需要UIKit ,它是我们应用程序中的依赖项。 UIKit是iOS特定的库。 但是我们的逻辑代码中不再有UIKit了,对吗? 这是否意味着我们应该能够在无需启动模拟器的情况下测试应用程序逻辑? 答案是肯定的! 最近,我开始考虑将大型项目介绍给许多较小的框架。 如果我的逻辑没有紧密结合,那么这应该不是什么大问题,如果您有这种区分,那么代码编写的可能性就很高。 如果我的小框架不依赖UIKit怎么办? 我可以轻松地在不同的平台(如iOS,MacOS等)上重用它们。这也是一种可用于测试这些框架的方法。 如果可以在MacOS上使用框架,那么您也可以在那里进行测试! 这意味着您不再需要模拟器! 我们如何准备针对iOS和MacOS的框架? 在下面,您将找到有关如何创建跨平台框架的文章。 这是Anthony Colangelo的“ Xcode跨平台框架”的链接 使用逻辑创建框架之后,剩下要做的是: 创建OSX单元测试套件的目标 作为要测试的目标,请选择以MacOS为目标的框架 做完了! 通过为应用程序的业务逻辑建立单独的框架,我们获得了: 无需启动模拟器即可测试逻辑的能力 不同平台之间的可重用代码 更清晰的代码,在部分中更易于理解 结论 我相信,这种结构化代码的方式可以使您受益匪浅,并且可以使代码和测试更加简洁,而无需花费很多时间来运行。 我想与您分享的一种在没有模拟器的情况下运行测试的方法对我来说是一种“概念证明”。 我愿意在战场上尝试更多,并观察其适用性。 您如何解决这些问题? […]

iOS快照测试用例

“ iOSSnapshotTestCase” FBSSnapshotTestCase教程库Facebook脚本库uber ตัว快照测试用例มันเอาไว้ 快照快照方法renderInContext: UIView对象CALayer对象存储库(参考图像)源代码存储库中的源代码文档显示失败。 ราะ codeอเราเขียน代码ที่เกี่ยวข้องกับUIเยอะมากๆายกรณีทดสอบ(测试用例)ที่เราต้องทำเมื่อสร้าง UIView แล้ว… textราจะรู้ได้อย่างไรว่าตัวอักษร(文本)ที่ใส่เข้าไปเพียงพอในพื้นที่ที่เตรที่ที่เตยมไว้ิ่งโด ดีกับราจะรู้ได้อย่างไรว่ารูปที่เตรียมไว้พอดีกับ图像视图ที่มีให้ Viewราจะรู้ได้อย่างไรว่าสีหรือภาพของ UIView เป็นอย่างไรถ้า状态เปลี่ยนเช่น被选中,突出显示 codeาเราต้องเขียน代码iOSiOS快照测试案例ี่แหละจะมนี่แหละจะมนอน iOSSnapshotTestCase อาสามาถทำได้ Coารติดตั้งผ่านCocoaPods ให้เพิ่ม代码ในกล่องข้างล่างในPodfile target “ชื่อ target (unit) test” do use_frameworks! pod ‘iOSSnapshotTestCase’ end Objectiveาใช้ภาษา Objective-C ให้ใช้ iOSSnapshotTestCase/Core แทนซึ่งจะตัดในส่วนการรองรับภาษา Swift ออกไป อย่าลืมเปลี่ยนชื่อ目标测试นะครับ 2.บอกที่เก็บของไฟล์รูปซึ่งสามารถทำได้3แต่แนะนำให้เพิ่มเข้าไปที่schemaทั้งนี้สามารถกำหนดได้กำหนด2ปลายคือต้นฉบับ FB_REFERENCE_IMAGE_DIR ที่เก็บถ้ามีค่าไม่ตรไม่ตามฉบับ IMAGE_DIFF_DIR สร้างกรณีทดสอบแรก งไฟล์ร้างไฟล์单元测试ที่อยู่ภายใต้目标ของ单元测试โดยให้子类ตัว FBSnapshotTestCase แทนตัว XCTestCase กใช้ FBSnapshotVerifyView ยกใช้方法FBSnapshotVerifyView ในการทดสอบ recordา recordMode = true […]