许多移动的和Web应用程序测试人员普遍存在的一个错误是认为大多数测试只需要观察和与用户界面(UI)本身的交互。另一方面,当我们开始看到甚至操纵幕后发生的事情时,更具体地说,我们的应用程序正在向后端服务发送数据和从应用程序发送数据的HTTP调用,我们的应用程序如何整体运行的黑盒子变得更加透明。这不仅使我们能够更多地了解我们的应用程序是如何工作的,而且还让我们看到了一系列全新的测试可能性。
我们可以更多地了解我们的应用程序如何与其后端Web服务交互的一种方法是查看我们的应用程序本身的源代码。当用户采取某个操作、加载页面或发生其他事件时,我们可以查看正在进行哪些调用。我们可以看到有关应用程序如何处理这些调用的头或有效载荷的细节。完美的方法,对吧?好吧,别这么快。如果你像很多测试人员一样读了最后几句话,你可能会想到以下事情之一:
- “源代码?嗯,听起来有点太专业了,我把源代码留给开发人员吧,谢谢。”
- “源代码?哈哈我只希望不要花太长时间来学习,我没有时间来实际测试这个东西。如果我这周工作晚一点......”
- “源代码?我能搞定的。事实上,我自己也是一个开发人员,所以我很容易理解这些东西。我只希望我不要因为看得太低而错过任何东西。“
如果有一个工具可以让我们真正看到和编辑你的应用发送和接收的HTTP调用,那不是很好吗?这将开启一系列全新的可能性...
- 在我们与任何开发人员讨论所观察到的问题之前,我们可以更好地确定我们所看到的缺陷实际上是植根于何处。例如,假设我们正在测试一个iOS应用程序,该应用程序显示用户获得的某些成就。我们早上来到办公室,下载应用程序的最新开发版本,注意到成就没有显示。在最新的应用程序构建中是否存在回归?我们是否应该假设情况就是这样,然后去和iOS开发人员谈谈?
关于缺陷可能原因的信息越多,你浪费的时间就越少,你作为一个专业测试人员的技能就越高。这在获得开发伙伴的尊重方面大有帮助。更不用说,这些额外的信息甚至可能会指向其他问题,否则你不会发现。
,为什么不首先查看应用程序进行的成就REST服务调用的结果呢?成绩信息是否在回复中返回?有回复吗?根据这一点,我们将能够更好地确定我们是否应该与后端开发人员,iOS开发人员或其他人一起跟进。
- 我们可以介入并操纵请求和响应,以查看我们的应用如何对不同的后端行为做出反应。在最后一个示例中,假设问题根源于后端。嗯,我们还需要继续在前端测试移动的应用。我们是否要等待服务被修复和部署,从而延迟我们的测试,并可能延迟发现移动的应用程序中的其他缺陷?相反,为什么不设置一个断点并重写响应以使其正确,或者甚至将整个响应映射到本地文件,以便我们可以继续测试呢?
- 我们可以模拟不同的网络连接质量和速度。我们的应用程序在有损3G连接上的行为方式是否与在为我们技术办公室的开发人员团队提供服务的150+ Mbps Wi-Fi连接上的行为方式相同?你会惊讶地发现,你可以通过节流你的网络连接到一些更符合只有一个或两个酒吧在地下室的停车场。
幸运的是,有这样一个工具。如果你没有真正阅读这篇文章的标题,它就被称为查尔斯代理。
这里是如何开始.
创建Charles Proxy
第一步:
我们首先需要下载并安装最新版本的Charles。安装后,我们需要采取一些设置步骤来启动和运行。为了这篇文章,我将详细介绍macOS和iOS上的设置和使用步骤,但一般概念也适用于其他操作系统。
第二步:
从应用程序文件夹启动Charles。您将看到下面的消息出现,您可以在其中授予权限,然后输入您的系统用户密码进行确认。
第三步:
我们需要在运行Charles的计算机以及我们的移动终端上安装Charles根证书。这将允许我们访问通过Charles代理的SSL流量。
下载Charles根证书并将其导入macOS上的密钥串,方法是选择帮助SSL代理安装Charles根证书。正如你所看到的,这个证书在默认情况下是不受信任的,所以我们需要做一些修改。
双击Charles证书的名称以打开证书详细信息窗口。展开“信任”部分,然后从"使用此证书时:“下拉列表中选择”始终信任“。关闭证书详细信息窗口并再次输入密码以确认更改。您现在应该看到Charles证书被标记为受信任。
第四步:
如果您使用的是物理iOS设备...
为了设置我们的移动终端,我们首先需要知道我们的计算机的本地IP地址。在Charles中,选择Help Local IP Address以显示此信息。 您的本地IP地址也可以在Apple系统偏好设置...网络下找到。
现在我们知道了计算机的本地IP地址,我们需要将移动终端连接到同一网络,然后在设备上设置适当的代理设置。一旦两台设备都连接到同一个网络,点击iOS设置Wi-Fi中所连接网络的信息按钮,打开一个页面,其中包含有关网络连接的更多详细信息。在HTTP PROXY下选择Configure Proxy Manual,然后输入您在服务器字段中找到的本地IP地址和8888端口。点击保存以应用更改。
8888是Charles的默认端口。如果出现冲突,您可以在Charles中的“代理代理设置”下更改此设置。
设置好后,我们需要在移动终端上安装Charles根证书。为此,请在移动终端上启动iOS Safari并导航到chls.pro/ssl。Charles证书将下载到设备,并将您带到iOS设置中的配置文件设备管理页面以安装证书。点击右上角的“安装”,然后按照提示在设备上安装证书。完成后,点击完成以返回iOS Safari。
如果您运行的是iOS 10或更高版本,则还需要为设备上的Charles根证书启用证书信任设置。这可以通过导航到iOS设置常规关于证书信任设置并切换要启用的Charles Proxy根证书的选择器来完成。
在移动终端上安装Charles根证书的过程中,我们会在Charles中看到以下消息:
这是为了允许设备允许在我们的计算机上使用Charles作为代理。单击允许。
如果您使用iOS模拟器...
Charles为iOS模拟器提供了一个非常简单的根证书安装过程。要安装,只需导航到帮助SSL代理在iOS模拟器中安装Charles根证书。点击OK,就是这样!
如果你错过了.确认消息指出,如果模拟器交通没有出现在查尔斯,请尝试运行查尔斯之前,你运行模拟器。
现在我们已经安装了证书,让我们启用SSL代理,这样我们就可以看到关于HTTPS流量的所有细节。
第五步:
要启用SSL代理,请导航到Proxy SSL Proxying Settings.并确保选中Enable SSL Proxying复选框。此时,我还建议阅读对话框的描述,并单击左下角的帮助问号以获取更多信息。这里有些重要的东西你不想错过。
我们将选择为所有位置启用SSL代理,方法是单击添加,在主机字段中输入单个字符(*),将端口留空,然后单击确定。完成后,我们的SSL代理设置应该如下所示:
第六步:
让我们快速设置几个更多的东西,这将使我们在查尔斯的生活更容易。从菜单栏中选择查看序列。这将允许我们在调用时按顺序查看调用。接下来,选择Charles Preferences.,选择Viewers选项卡,选择联合收割机请求和响应,并将Time下拉列表设置为毫秒。
我建议您稍后花一些时间熟悉这些选项(包括Structure视图),并使用最适合您的选项。
点击OK返回到Charles主窗口,开始测试!
观察HTTP请求和响应
Charles Proxy的基本功能围绕着我们的应用程序或网站与为其提供信息的后端服务之间的HTTP请求和响应。为了这篇文章的目的,我将使用Under Armour的UA商店应用程序。现在是一个很好的时机来提一下,我与Under Armour没有任何关系,选择他们的应用程序只是为了展示我们可以用Charles Proxy做什么。我建议你沿着,并探索下面的每一个例子,使用自己的应用程序,你可以。
现在,我们已经正确设置了Charles,让我们启动我们的应用程序,执行一些操作,并注意我们在会话窗口中看到的流量。
对于本例,我们将导航到UA Shop的搜索功能并搜索“Socks”。正如你在下面看到的,在查尔斯发生了很多事情,所以让我们解开这个.
- 我们可以看到搜索的端点是
www.underarmour.com/v0.0/product/US/search?q=Socks&facets=1242,1227
。这看起来像是一个非常简单的GET调用,使用我们的搜索词作为查询参数来调用搜索端点。
每当我看到输入从搜索字段之类的东西传递到查询字符串时,我喜欢检查各种输入。包含需要在URL中正确编码的字符的搜索项,如&(),部分或全部由正则表达式组成的搜索项等,都容易被应用程序错误处理。Charles让我们看看到底传递了哪些查询参数,这样我们就可以轻松地测试这些不同的场景。
- 到目前为止,所有来自我们的设备和计算机的网络流量都在我们的Charles会话中导致了很多不必要的噪音。为了减少这种情况,我们将使用Filter字段。使用如图所示的设置,我们将只看到Host或Path中包含
www.underarmour.com
的流量。
选择Filter字段右侧的Settings,允许我们启用Filter uses regex设置,从而为我们提供了更多的控制。如果您只在外部设备上进行测试,而不是在与Charles运行在同一台计算机上的Web浏览器中进行测试,则可以通过取消选中“代理”菜单下的macOS代理...来进一步减少会话噪音。最终,您可能会发现需要清除整个会话。这可以通过选择文件菜单下的清除会话来完成。
- 要查看对搜索的JSON响应,我们将选择Response和JSON Text选项卡。滚动浏览这个JSON响应,我们可以开始查看响应主体中的某些值如何对应于UI中的元素。这可以在下面我从响应正文和附带的屏幕截图中选择的JSON属性中看到。
"totalCount": 129
...
"content": {
"name": "UA Charged Cotton® 2.0 No Show Socks – 6-Pack",
"shortName": "UA Charged Cotton® 2.0 No Show 6-Pack",
"bullets": [],
"categoryName": "Men’s Sock"
}
...
"priceRange": {
"base": {
"min": 19.99,
"max": 19.99
},
"msrp": {
"min": 19.99,
"max": 19.99
},
"currency": "USD"
}
...
现在我们已经能够查看HTTP请求和响应,甚至已经看到了JSON响应中的一些属性如何映射到UI中的元素,现在是时候利用Charles中的一些工具来实际修改正在发送和接收的请求和响应了。
修改HTTP请求和响应
让我们来确定一下,我们已经有了一个基本的心理模型,当我们通过查尔斯学习的时候,发生了什么。该请求将由我们在移动的应用程序中发起的某些事件或操作触发,通过Charles作为我们的代理发送,并由后端接收。然后由创建响应的后端服务进行处理。这个响应最终会被发送回应用程序,一路上沿着经过查尔斯。
断点
查尔斯有能力为呼叫设置断点。我们可以选择在请求上设置断点(即在应用程序发送请求之后,但在后端接收请求之前),在响应上设置断点(即在后端发送响应之后,但在应用程序接收响应之前),或者两者兼而有之。
我们首先需要一个例子来说明Charles中的断点是如何工作的。我们的示例不需要那么复杂,但是一旦您理解了断点是如何工作的,就要在您自己的真实场景中寻找它们可以满足您的测试需求的机会。
假设我们想要为调用设置一个断点,该调用在我们一直使用的UAShop应用程序中执行搜索。我们将使用此断点以几种不同的方式更改响应中的"totalCount":129
。
我们将通过导航到代理断点设置.来创建断点,选择启用断点复选框,单击添加,然后输入有关要为其设置断点的调用的信息。
同样,搜索调用(特别是“Socks”)的URL是https://www.underarmour.com/v0.0/product/US/search?q=Socks&facets=1242,1227
,因此我们的断点设置如下所示:
- 请注意,有些字段故意留空。任何空字段都将与传递的任何值匹配。例如,上图中的断点设置将仅适用于搜索“袜子”,因为这是在查询字段中指定的。但是,如果将Query字段留空,则此断点将应用于任何项目的搜索调用,因为断点将与
www.underarmour.com
的Host和/v0.0/product/US/search
的Path匹配,但不考虑使用了什么方案、协议、端口或查询。 - 通配符(*)在这里和Charles中的许多其他工具中也得到支持。例如,如果Under Armour要推出此服务的v1.0版本,并且我们正在测试应用程序的多个版本(有些使用v0.0,有些使用v1.0),但不想创建多个断点,我们可以输入路径
/v*/product/US/search
,无论调用v0.0还是v1.0,断点都会应用。 - 我们还将断点设置为仅应用于响应。在本例中,我们不想更改请求的任何内容,因此我们不会浪费时间在那里设置断点。我们将让请求不间断地通过Charles以由后端处理,然后使用断点介入并在移动的应用程序接收到响应之前更改响应。
当调用被执行并且断点被调用时,我们将立即在Charles中看到Breakpoints视图。从这里,选择Edit Response选项卡,从下面的选项卡栏中选择JSON,双击totalCount旁边的值以插入我们自己的值175,然后单击Execute。
快看!我们的新值175显示在UI中。
现在让我们重复我们的搜索,这次将原始值129(整数)重写为“129”(字符串)。
好了UI元素现在显示为SHOWING 0 RESULTS,因为我们将“129”作为字符串而不是整数传入。这告诉我们,移动的应用程序只支持该值作为整数返回。
断点提示:
在Charles中创建断点的一种更快捷的方法要求在当前会话中至少进行过一次调用。如果是这种情况,请在会话视图中右键单击调用,并从出现的上下文菜单中选择Breakpoints。这将在该特定端点的请求和响应上创建断点。然后,可以根据需要从代理断点设置中编辑此设置....
何时不使用断点:
- 如果您在单个请求或响应中有很多更改要做,那么它们可能需要太长时间才能完成,导致应用程序响应时就像调用超时一样。
- 如果您需要对连续发生的许多调用进行编辑(例如,如果您正在修改每个调用的URL中的头值或API版本,而不管正在调用的特定端点),则必须为每个调用手动进行这些更改将非常低效。
如果是这两种情况,我们可以使用其他工具来更有效地修改Charles中的请求。
重写工具
重写工具可用于预先定义对一个或多个调用的更改,并在运行时应用这些更改。在下一个示例中,让我们看看UA Shop如何响应对搜索请求的503 Service Unavailable响应。
创建一组
我们首先需要定义重写规则。导航到Tools Rewrite.并选择Enable Rewrite复选框。单击添加创建新规则集,并在名称字段中输入503 Service Unavailable以重命名该集。
将位置定义
接下来,我们需要定义调用规则的位置或调用。我们只希望在调用搜索端点时将响应重写为503 Service Unavailable。因此,我们将通过单击Location列表下的Add并在Host字段中输入www.underarmour.com
和在Path字段中输入/v*/product/US/search
来输入仅与搜索端点匹配的位置。正如您所看到的,我们可以根据需要使用通配符和空字段。
单击确定关闭编辑位置窗口。
创建规则
现在我们已经定义了位置,我们需要通过单击“规则”列表下的“添加”按钮来定义规则本身。单击类型下拉列表并记下您可以创建的所有重写规则类型。我鼓励你花一些时间去尝试这些类型的每一个,只是为了感受一下查尔斯的能力。请记住,您可以创建多个重写规则,一次应用!我发现这是Charles中最强大的功能之一,因为它允许我测试否则无法测试的场景。
现在,让我们选择一种响应状态。然后,在Match section Value字段中,我们将输入“200 OK”(不带引号),在Replace section Value字段中,我们将输入“503 Service Unavailable”,最后选择Replace All。
一旦您的重写规则看起来像上面的规则,单击OK。
因为我们不想将原始响应正文传递给应用程序(对于503响应来说,这是不现实的),所以让我们在此集合中创建另一个规则,用一些静态文本替换响应正文。通常情况下,会有一个预定义的响应主体,将返回特定的响应状态。您应该能够从后端开发人员或DevOps团队中的某个人那里获得此响应主体。但是现在,我们将只使用静态文本“Service Unavailable”。
再次在“规则”列表下单击“添加”。从“类型”下拉列表中选择“正文”,然后仅选择“响应”复选框。将Match部分保留为空,这样整个响应正文(无论内容是什么)都将被替换。在Value字段的Replace部分中,输入“ServiceUnavailable”(同样,没有引号)并选择Replace All。
如果您的重写规则与上面的规则类似,请再次单击OK。
我们创建了一个重写规则,每当调用搜索端点时都会调用该规则,将通常为200 OK的响应状态重写为503 Service Unavailable,并将响应正文替换为“Service Unavailable”。
单击Apply/OK,让我们通过执行另一个搜索来尝试一下。
你看看!我们在应用程序中看到一个由503响应触发的通用错误消息,并且可以在Charles中看到我们的响应主体也被替换了。
地图本地
操纵任何调用的响应体的另一种方法是使用Map Local工具。这允许我们提前准备一个响应体,然后在执行请求时简单地指示Charles使用该文件来响应我们的调用。虽然这是一个预先准备的工作,但这在执行过程中为我们节省了很多时间,而不是使用断点,并且允许对响应主体进行比重写工具更复杂的更改。
重要的是要记住,当使用Map Local时,调用永远不会到达应用程序的后端,因此我们不能期望数据处于相同的状态。例如,假设我们为向购物车添加商品时执行的调用启用了Map Local。当采取该操作时,Charles将从我们的本地文件中为本地应用提供响应,但请求实际上永远不会到达后端。因此,当我们在应用程序中导航到我们的购物车时,该项目将不会在那里。如果在测试的环境中出现问题,最好使用重写工具重写响应体。
创建JSON响应体
让我们从搜索请求的标准JSON响应开始。我们将首先关闭所有断点并重写前面示例中的规则,然后执行另一个搜索请求。接下来,让我们复制整个JSON响应主体并将其粘贴到文本编辑器中的新文件中。在我们的文本编辑器中,我们将对JSON响应中的几个值进行一些更改,这些值可以在UI中轻松识别。这次我们将totalCount
设置为190,并将第一个结果的priceRange.base.min
和priceRange.base.max
值更改为17.99。我可以告诉从其他产品在搜索结果中,改变价值观,以这种方式将显示第一个产品作为正在销售。我们将响应保存到桌面(或其他容易找到的位置),文件名为search.json
。
现在我们已经创建了自定义JSON响应,让我们在Charles中创建Map Local设置,它将允许我们使用这个JSON文件。
地图本地设置
导航到“工具”“地图本地.”并选择“启用地图本地”复选框。单击添加,再次输入正确的主机和路径,以及正确的协议、端口和查询(如有必要)。在Local path字段旁边,单击Choose并选择您刚刚创建的search.json
文件。
单击确定,然后单击确定,关闭地图本地设置。让我们执行另一个对搜索端点的调用,看看它是如何工作的。
这就是了!我们可以看到新的totalCount反映在SHOWING 190 RESULTS元素中,并且第一个产品的销售价格为17.99美元。
网络节流
除了观察和修改请求和响应中的各种元素外,Charles在模拟各种类型的网络连接(也称为网络节流)方面也非常有用。
对于测试人员来说,这可能是一个非常有价值的工具,因为这将使您能够模拟应用程序的各个用户在真实的世界中可能体验到的网络条件。如果您的应用在使用快速Wi-Fi连接的办公室中进行测试时表现良好,这是一回事,但在慢速或不可靠的网络中,它是否会表现出相同的行为?
在Charles中节流您的网络非常简单。导航到Tools Throttle Settings.并选择Enable Throttling复选框。
请注意,您确实可以选择为选定位置启用节流,但出于本示例的目的,我们将为所有网络流量启用全局节流。从“Throttle preset”下拉列表中选择一个预设,然后单击“OK”。就这么简单!
如果您不熟悉节流阀设置中使用的术语,我建议您研究一下这些术语的含义,并尝试以不同的方式设置这些术语。这将允许您根据最适合您的测试的网络设置创建自己的测试表。
最后...
虽然前面的例子很简单,甚至可能与现实世界的场景相距甚远,但我希望你能看到Charles Proxy中的工具在适当的环境中应用时是多么强大,我鼓励你继续探索如何在自己的测试中利用它们。