众所周知,appium和selenium使用的都是客户/服务架构,它的特色是在客户端写测试指令,在服务端执行。这种架构有两大优点:
1、跨语言,可以使用任何语言编写Appium代码;
2、可以构建大型私有或公有的Appium设备云。
这种架构也存在致命的缺点:降低性能。客户/服务架构用网络传输测试指令,这必然会受到网络延迟的影响,甚至天气不好也会波及。
网络太不可靠了,总会导致意想不到的卡顿、请求失败等等。这意味着你在本地跑代码时很完美,但传输到Appium云去运行时,可能完全不同,可能导致代码高度脆弱,甚至测试失败。
最重要的是,很多人不是直接使用Appium命令,而是一些框架。那些基于Appium的封装工具(对Appium命令进行了封装,存在过度使用的情况)。
比如,我看到有测试用5~10个请求去找一个元素,仅仅为了检索元素是否可用,我觉得这个方法不好。它会让脚本在云环境上的执行时间存在巨大差异。
除了网速慢,网络延迟也是一个杀手。比如你想执行命令A,之后立刻执行命令B,基本不可能使用网络来实现这个功能(B需要延迟才能到达Appium云服务器,不可能紧接着命令A马上执行)。
于是,W3C WebDriver规范团队想出了一个办法,创造新的Actions API(把整个action chain
编码成一个API去调用),一旦action开始,链可能需要几秒或几分钟才能实际执行
(原文:even though the chain might take seconds or minutes to actually execute
once the action begins.)。
** 使用Execute Driver Script**
Appium团队已经做了同样的事情,不仅仅actions,甚至是任何Appium命令。允许在一个Appium命令中打包其它Appium命令。所有这些命令都将在Appium服务器上执行,因此不会受到网络延迟的影响。它是如何运作的?显然这很神奇!比如,我们在Java客户端中编写下面这个测试脚本:
@Test
p
ublic void testLoginNormally() { driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.findElement(MobileBy.AccessibilityId("Login Screen")).click(); driver.findElement(MobileBy.AccessibilityId("username")).sendKeys("alice"); driver.findElement(MobileBy.AccessibilityId("password")).sendKeys("mypassword"); driver.findElement(MobileBy.AccessibilityId("loginBtn")).click(); driver.findElement(By.xpath("//*[@text='Logout']")).click();}
这是一个简单的登录/注销功能。我们可以使用ExecuteDriverScript命令一次性批量运行所有这些命令:
@Test
public void testLoginWithExecute() {
driver.executeDriverScript(
"await driver.setImplicitTimeout(10000);\n" +
"await (await driver.$('~Login Screen')).click();\n" +
"await (await driver.$('~username')).setValue('alice');\n" +
"await (await driver.$('~password')).setValue('mypassword');\n" +
"await (await driver.$('~loginBtn')).click();\n" +
"await (await driver.$('//*[@text=\"Logout\"]')).click();\n");
}
这到底是怎么回事?它把Appium客户端的代码包裹到了字符串里,Appium团队讨论了许多方法,他们一致认为灵活性至关重要。
因此Execute Driver Script命令的参数是一个字符串(字符串使用起来更灵活),表示要在当前运行的Appium
session中执行的JavaScript代码。该字符串最终由Appium服务器执行。
哇哦!这么做显然会引发远程代码执行漏洞(remote code execution
vulnerability,比如在ExecuteDriverScript中输入获取账号密码,然后让服务器来执行)!所以我们需要谈谈安全问题。
首先,服务器必须指令参数才能启用Execute Driver Script
(原文:the server must be started in a special mode that allows this feature
explicitly:)
appium --allow-insecure=execute_driver_script
其次,所有代码都在NodeJS VM中运行,这意味着它无法干扰Appium主程序。
实际上,我们可以严格控制执行代码可以访问什么方法。除了driver object之外,只提供访问权限。这个driver
object是什么?它是WebdriverIO session object的一个实例。您可以WebdriverIO API和所有JavaScript语法!
这也正好解释了上面的代码,比如代码中driver.$
相当于findElement,而代码中的〜表示ID定位。您还可以在字符串中返回文本,数据甚至元素,这些结果在父脚本中也可以使用。
** 使用 Execute Driver Script**
我想了解Execute Driver
Script对测试执行时间的影响,因此我在支持此功能的Appium云提供商上进行了大量实验:HeadSpin(感谢HeadSpin)
。我的测试结果(客户端位置在Vancouver, Canada):
Server|
Using Execute
Driver?
|
Avg Test Time
|
Avg Command
Time
|
Avg Speedup
---|---|---|---|---
Localhost
|
No
|
49.12s
|
0.55s
|
Localhost
|
Yes
|
48.71s
|
0.54s
|
0.8%
Mountain
View, CA
|
No
|
72.53s
|
0.81s
|
Mountain
View, CA
|
Yes
|
43.15s
|
0.48s
|
40.5%
Tokyo,
Japan
|
No
|
102.03s
|
1.13s
|
Tokyo,
Japan
|
Yes
|
42.10s
|
0.47s
|
58.74%
** 分析**
如果在本地执行,使用Execute Driver Script
并不会带来太多改进。这也很好理解,当客户端和服务器使用相同的网络接口时,基本上没有时间丢失的延迟。但是当Appium服务器位于其他地方时,进步就特别大。
Mountain View, CA离我在Vancouver的办公室要近一些,而
Tokyo离我的办公室则远一些,数据上的差异接近30%(Tokyo的平均时间更长)。这种差异首要问题是延迟,延迟加深了client/server
model中存在的问题。比如命令很多时(每个测试有90个命令),测试时间大约30秒。
当我使用Execute Driver
Script时,所有的90个命令都包含在一个批处理中,结果显示测试时间降低。由于我只进行了一次网络调用,因地理分布引起的延迟变得可以忽略不计,将测试行为时间缩短了40-60%!当然,此功能也受其它因素影响,包括批处理调用中输入的命令数等等……我也不建议将每个命令都填充到
Execute Driver Script,这里仅演示可能的性能改进。
**
**
** 测试方法**
-
这些测试是在HeadSpin在世界各地的真实网络上运行,并且使用真实的Android设备上,这些设备位于加州山景城和日本东京。(在本地,测试则使用我自己的笔记本电脑,运行手机模拟器和Appium服务器,因此与真实设备有些不同)
-
对于每个测试条件(不同位置,是否使用Execute Driver Script),运行了15个不同的测试。
-
每个测试包括重复登录和注销5次。
-
Appium命令的总数(不计算会话开始和退出)是每次测试90个,这意味着每个测试条件总共为1,350个。
-
表中的数字会丢弃会话开始和退出时间,仅计算会话中的测试时间(如果你的时间主要集中在会话开始上,有非常少的命令,那么本篇文章对您用处不大)。
** 总结**
Execute Driver Script
是新的Appium功能,在分布式测试时尤其有用。如果云服务器或设备位于世界各地,则每个命令将花费很长时间(甚至长于服务器关闭命令)。设备越远,命令执行时间就越长。管理员可以选择打开Appium中的Execute
Driver
Script,以允许其用户批量命令,这样可以避免与服务器进行大量不必要的延迟,为用户提供了很多优势,减少了延迟成本。当然,这是一项高级功能,您只应该用它来解决具体问题!
如果您想查看项目的java代码,可以在GitHub上查看:
https://github.com/cloudgrey-
io/appiumpro/blob/master/java/src/test/java/Edition085_Execute_Driver_Script.java。
其他Appium客户端也支持这个新命令,包括WebdriverIO(所以你可以使用WebdriverIO-ception!)
非常感谢HeadSpin启用该功能并让我使用设备,因此我可以为本文收集数据。
Cheers,
Jonathan & Jonah
翻译:若桐
往期推荐
大话JMeter2|正确get参数传递和HTTP如何正确使用
- 今日互动 -
**
**
欢迎文章下方留言并分享给其他测试小伙伴哦~
小编PS:
因为很多小伙伴想深入学习性能测试。我们邀请了专注性能十多年的性能架构师高楼老师给大家带来了《高级性能测试实战训练营》,想了解的小伙伴可以添加小助手微信进行咨询哦。课程信息可点击下方蓝色字体“阅读原文”进行试听。
(别忘了 长按 加小助手微信:jasmine07222
回复“ 性能测试 ”即可入群交流哦~)
来霍格沃兹测试开发学社,学习更多软件测试与测试开发的进阶技术,知识点涵盖web自动化测试 app自动化测试、接口自动化测试、测试框架、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移、测试右移、精准测试、测试平台开发、测试管理等内容,课程技术涵盖bash、pytest、junit、selenium、appium、postman、requests、httprunner、jmeter、jenkins、docker、k8s、elk、sonarqube、jacoco、jvm-sandbox等相关技术,全面提升测试开发工程师的技术实力
QQ交流群:484590337
公众号 TestingStudio
点击获取更多信息