Apple Xcode的工具是用于分析iOS应用程序性能的工具。 它们用于收集和显示代码调试中所需的数据。 去年,苹果
推出了 Custom Instruments。 这是扩展用于分析应用程序的标准工具集的机会。 如果现有工具还不够用,您可以自己创建新工具-它们将根据需要收集,分析和显示数据。
一年过去了,在网络上几乎没有新的公共工具和信息。 因此,我们决定纠正这种情况,并分享我们如何创建自己的自定义工具,该工具确定了单元测试隔离度较弱的原因。 它基于路标技术(我们
在上一篇文章中进行了介绍 ),使您可以快速而准确地确定测试的闪烁位置。

理论最小值
要为Xcode创建新工具,您需要了解两个理论模块。 对于那些想要自己解决问题的人,我们将立即提供必要的链接:
对于其余部分-以下是必要主题的简要摘要。
首先选择File-> New-> Project-> macOS Category-> Instruments软件包。 创建的项目包括扩展名为.instrpkg的文件,其中以xml格式声明性地声明了一个新工具。 让我们熟悉一下标记元素:
什么 | 属性 | 内容描述
|
数据模式
| 间隔模式,点模式等
| 将数据结构描述为类似于sql方案的表。 在其他标记元素中使用方案来确定模型输入和输出处的数据类型,例如在描述映射(UI)时。
|
导入数据模式
| 导入模式
| 导入现成的方案。 它允许您使用Apple定义的数据结构。
|
工具型号
| 造型师
| 将工具与.clp文件相关联,该文件中定义了工具的逻辑,并在模型的输入和输出处声明了预期的数据方案。
|
工具说明
| 乐器
| 描述数据模型并确定事件将如何在UI中显示。 使用属性create-table,create-parameter等描述数据模型。 工具图由图形属性定义,零件表由列表,叙述等定义。
|
如果我们想补充新工具的逻辑,请使用CLIPS代码创建一个.clp文件。 基本语言实体:
- “事实”是使用assert命令在系统中注册的特定事件;
- “规则”是具有特定语法的if块,其中包含执行一组动作的条件。
CLIPS本身根据传入的事实,规则的优先级和冲突解决机制来确定将激活哪些规则和顺序。
该语言支持基于基元的数据类型的创建,算术,逻辑运算和函数的使用。 以及具有类定义,发送消息,多重继承的成熟的面向对象编程(OOP)。
考虑一种语言的基本语法,该语言允许您为自定义工具创建逻辑。
1.要创建一个
fact
,请使用
assert
构造:
CLIPS> (assert (duck))
因此,我们在事实表中获得了
duck
条目,可以使用
facts
命令查看该条目:
CLIPS> (facts)
要删除事实,请使用
retract
命令:
(retract duck)
2.要创建
rule
,请使用
defrule
构造:
CLIPS> (defrule duck) — duck (animal-is duck)</i> — animal-is duck => (assert (sound-is quack))) — sound-is quack
3.要创建和使用变量,请使用以下语法(在变量名称之前带有强制性符号“?”):
?<variable-name>
4.您可以使用以下方法创建新的数据类型:
CLIPS> (deftemplate prospect (slot name (type STRING) (default ?DERIVE)) (slot assets (type SYMBOL) (default rich)) (slot age (type NUMBER) (default 80)))
因此,我们定义了一个结构,该结构具有名称前景和三个属性名称,相应类型的资产和年龄以及一个默认值。
5.算术和逻辑运算具有前缀语法。 也就是说,要添加2和3,必须使用以下构造:
CLIPS> (+ 2 3)
或比较两个变量x和y:
CLIPS> (> ?x ?y)
实际例子
在我们的项目中,我们使用
OCMock库创建存根对象。 但是,在某些情况下,mok的寿命要比为其创建的测试的寿命长,并且会影响其他测试的隔离。 结果,这导致单元测试的“闪烁”(不稳定)。 为了跟踪测试和模拟的生命周期,我们将创建自己的工具。 以下是动作算法。
步骤1.为路标事件制作标记
要检测有问题的艾灸,需要两类间隔事件:艾灸的产生和破坏时间,测试的开始和结束时间。 要获取这些事件,请转到
OCMock
库,并在
stopMocking
类的
init
和
stopMocking
方法中用
signpost
对其进行
signpost
。


接下来,转到正在研究的项目,在单元测试,
setUp
和
tearDown
进行标记:

步骤2.从Instrument Package模板创建一个新工具

首先,我们确定输入的数据类型。 为此,
.instrpkg
将
signpost
方案导入
signpost
。 现在,由
signpost
创建的事件将落入工具中:

接下来,我们确定输出中的数据类型。 在此示例中,我们将输出同步事件。 每个事件都有时间和描述。 为此,请声明方案:

步骤3.我们描述工具的逻辑
我们创建一个扩展名为
.clp
的单独文件,在其中我们使用CLIPS语言设置规则。 为了让新工具知道在哪个文件中定义了逻辑,请添加
modeler
块:

在此块中,使用
production-system
属性,使用逻辑指定文件的相对路径。 在
output
属性和
required-input
属性中
required-input
定义了输入和输出的数据方案。

步骤4.我们描述了该工具(UI)的呈现方式的细节
在
.instrpkg
文件中,
.instrpkg
仍然可以描述工具本身,即显示结果。 使用先前在
schema-ref
属性中声明的
detected-mocks-narrative
schema-ref
,为
create-table
属性中的数据创建一个表。 并设置信息输出的类型-叙述性(描述性):

步骤5.我们编写逻辑代码
让我们
.clp
文件,在其中定义专家系统的逻辑。 逻辑将如下所示:如果测试的开始时间与moka的生命间隔重叠,则我们认为该mok是从另一个测试中“走来”的,这违反了当前单元测试的隔离性。 为了最终创建一个包含感兴趣信息的事件,您需要执行以下步骤:
1.使用字段定义模拟和unitTest结构-事件的时间,事件标识符,测试的名称和mok的类。

2.我们根据
signpost
的传入事件定义将使用
mock
和单元
unitTest
类型创建事实的规则:

您可以阅读以下规则:如果在输入处获得具有所需
subsystem
,
category
,
name
和
event-type
的os-signpost类型的事实,然后使用上面定义的类型(unitTest或模拟)创建一个新事实,然后将其填充值。 这里要记住重要的一点-CLIPS是区分大小写的语言,子系统,类别,名称和事件类型的值必须与正在研究的项目代码中使用的值匹配。

来自路标事件的变量按以下方式传递:

3.我们定义了释放已完成事件的规则(它们是多余的,因为它们不影响结果)。

步骤6.定义将生成结果的规则。
您可以阅读如下规则。
如果1)有unitTest和mock;
2)在这种情况下,测试的开始要晚于现有的Moka;
3)有一个表,用于存储带有检测到的虚假叙述模式的结果;
然后4)创建新记录;
5)随时间填写;
6)...和说明。

结果,使用新工具时,我们看到以下图片:

可以
在GitHub上查看自定义工具的源代码和使用该工具的示例项目。
工具调试
调试器用于调试自定义工具。

他允许
1.根据instrpkg中的描述,参见编译后的代码。
2.查看有关在运行时工具发生什么情况的详细信息。

3.显示可以用作新工具输入的系统数据方案的完整列表和说明。

4.在控制台中执行任意命令。 例如,使用list-defrules命令显示规则列表,或使用事实命令显示事实

在CI服务器上设置
您可以从命令行运行工具-在CI服务器上执行单元测试或UI测试期间对应用程序进行概要分析。 例如,这将允许尽早捕获内存泄漏。 要分析管道中的测试,请使用以下命令:
1.具有以下属性的运行工具:
xcrun instruments -t <template_name> -l <average_duration_ms> -w <device_udid>
- 其中
template_name
是带有工具的模板的路径或模板的名称。 您可以获取命令xcrun instruments -s
; average_duration_ms
记录时间(以毫秒为单位),应大于或等于测试运行时间;device_udid
模拟器标识符。 您可以获取命令xcrun instruments -s。 必须与将在其上运行测试的模拟器的标识符匹配。
2.使用以下命令在同一模拟器上运行测试:
xcodebuild -workspace <path_to_workspace>-scheme <scheme_with_tests> -destination <device> test-without-building
- 其中
path_to_workspace
是Xcode工作空间的路径; scheme_with_tests
测试方案device
-模拟器标识符。
结果,将在工作目录中创建扩展名为.trace的报告,可以通过Instruments应用程序打开该报告,也可以通过右键单击该文件并选择Show Package Contents来打开该报告。
结论
我们研究了将路标升级为功能完善的工具的示例,并介绍了如何将其自动应用于CI服务器的“运行”,并用于解决“闪烁”(不稳定)测试的问题。
当您深入研究自定义工具的可能性时,您将更好地了解在其他情况下可以使用这些工具。 例如,它们还帮助我们了解多线程问题-何时何地使用线程安全的数据访问。
创建一个新工具非常简单。 但是最主要的是,在花了几天的时间研究机制和文档以立即创建它之后,您将能够避免尝试修复错误的不眠之夜。
资料来源
本文由iOS开发人员Anton Vlasov的@regno撰写。