通过instruments针对IOS压力测试研究总结
2015-03-17 18:46
393 查看
运行环境:
1,环境iMac OS X 10.9.5
2,工具Xcode Version 6.1 (6A1052c)
3,签约证书(开发者提供)
4,iphone设备(系统IOS6、IOS7、IOS8.1)
UI AUtoMonkey是一款非常简单的IOS压力测试工具。通过它,你可以向ios设备发送滑动、拖动、旋转、甚至锁屏和解锁指令。原文github地址:https://github.com/jonathanpenn/ui-auto-monkey
首先,使用xcode打开你的ios项目,从“Product”菜单中选择“Profile”(或者直接快捷键Command+i),这样就可以构建ios项目,并启动工具模板选择器。
下一步,在选择器中选择“UI Automation”。当我们创建了自动化模板后,就可以测试app的性能了。
在Scripts面板中,点击“Editor Log”,在下拉列表中选择“Script”,点击“Add”按钮,在下拉列表中选择”Create”,就可以新建一个js脚本。
将UIAutoMonkey.js这个文件的内容粘贴到新建的js脚本中(或者可以直接将UIAutoMonkey.jsimport进去。
此时,我们可以直接点击播放按钮,来执行这段脚本,monkey测试就开始了。
源码:"use strict";
function UIAutoMonkey() {
this.config = {
numberOfEvents: 1000, //产生随机事件的个数
delayBetweenEvents: 0.05, // 事件之间的延迟时间
// If the following line is uncommented, then screenshots are taken
// every "n" seconds.
//screenshotInterval: 5,
// Events are triggered based on the relative weights here. The event
// with this highest number gets triggered the most.
//
// If you want to add your own "events", check out the event method
// definitions below.
eventWeights: { //每个事件的触发几率,如果tab事件的值为100、orientation事件的值为1,那么tab事件触发的几率就是orientation的100倍。
tap: 500,
drag: 1, //拖
flick: 1, //轻击
orientation: 1, //定位
clickVolumeUp: 1,
clickVolumeDown: 1,
lock: 1,
pinchClose: 10, //捏
pinchOpen: 10,
shake: 1 //动摇
},
// Probability that touch events will have these different properties
touchProbability: { //控制着不同种类的tab事件
multipleTaps: 0.05,
multipleTouches: 0.05,
longPress: 0.05
}
// Uncomment the following to restrict events to a rectangluar area of
// the screen
/*
frame: {
origin: {x: 0, y: 0},
size: {width: 320, height: 480}
}
*/
};
}
// Event Methods
// Any event probability in the hash above corresponds to a related event
// method below. So, a "tap" probability will trigger a "tap" method.
//
// If you want to add your own events, just add a probability to the hash
// above and then add a corresponding method below. Boom!
// Each event method can call any other method on this UIAutoMonkey object.
// All the methods at the end are helpers at your disposal and feel free to
// add your own.
UIAutoMonkey.prototype.allEvents = {
tap: function() {
this.target().tapWithOptions(
{ x: this.randomX(), y: this.randomY() },
{
tapCount: this.randomTapCount(),
touchCount: this.randomTouchCount(),
duration: this.randomTapDuration()
}
);
},
drag: function() {
this.target().dragFromToForDuration(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() },
0.5
);
},
flick: function() {
this.target().flickFromTo(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() }
);
},
orientation: function() {
var orientations = [
UIA_DEVICE_ORIENTATION_PORTRAIT,
UIA_DEVICE_ORIENTATION_PORTRAIT_UPSIDEDOWN,
UIA_DEVICE_ORIENTATION_LANDSCAPELEFT,
UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT
];
var i = Math.floor(Math.random() * 10) % orientations.length;
var newOrientation = orientations[i];
this.target().setDeviceOrientation(newOrientation);
this.delay(0.9);
},
clickVolumeUp: function() {
this.target().clickVolumeUp();
},
clickVolumeDown: function() {
this.target().clickVolumeUp();
},
lock: function() {
this.target().lockForDuration(Math.random() * 3);
},
pinchClose: function () {
this.target().pinchCloseFromToForDuration(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() },
0.5
);
},
pinchOpen: function () {
this.target().pinchOpenFromToForDuration(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() },
0.5
);
},
shake: function() { //摇
this.target().shake();
}
};
// --- --- --- ---
// Helper methods
UIAutoMonkey.prototype.RELEASE_THE_MONKEY = function() {
// Called at the bottom of this script to, you know...
//
// RELEASE THE MONKEY!
for(var i = 0; i < this.config.numberOfEvents; i++) {
this.triggerRandomEvent();
if (this.config.screenshotInterval) this.takeScreenShotIfItIsTime();
this.delay();
}
};
UIAutoMonkey.prototype.triggerRandomEvent = function() {
var name = this.chooseEventName();
// Find the event method based on the name of the event
var event = this.allEvents[name];
event.apply(this);
};
UIAutoMonkey.prototype.target = function() {
// Return the local target.
return UIATarget.localTarget();
};
UIAutoMonkey.prototype.delay = function(seconds) {
// Delay the target by `seconds` (can be a fraction)
// Defaults to setting in configuration
seconds = seconds || this.config.delayBetweenEvents;
this.target().delay(seconds);
};
UIAutoMonkey.prototype.chooseEventName = function() {
// Randomly chooses an event name from the `eventsWeight` dictionary
// based on the given weights.
var calculatedEventWeights = [];
var totalWeight = 0;
var events = this.config.eventWeights;
for (var event in events) {
if (events.hasOwnProperty(event)) {
calculatedEventWeights.push({
weight: events[event]+totalWeight,
event: event
});
totalWeight += events[event];
}
}
var chosenWeight = Math.random() * 1000 % totalWeight;
for (var i = 0; i < calculatedEventWeights.length; i++) {
if (chosenWeight < calculatedEventWeights[i].weight) {
return calculatedEventWeights[i].event;
}
}
throw "No even was chosen!";
};
UIAutoMonkey.prototype.screenWidth = function() {
// Need to adjust by one to stay within rectangle
return this.target().rect().size.width - 1;
};
UIAutoMonkey.prototype.screenHeight = function() {
// Need to adjust by one to stay within rectangle
return this.target().rect().size.height - 1;
};
UIAutoMonkey.prototype.randomX = function() {
var min, max;
if (this.config.frame){
// Limits coordinates to given frame if set in config
min = this.config.frame.origin.x;
max = this.config.frame.size.width + min;
} else {
// Returns a random X coordinate within the screen rectangle
min = 0;
max = this.screenWidth();
}
return Math.floor(Math.random() * (max - min) + min) + 1;
};
UIAutoMonkey.prototype.randomY = function() {
var min, max;
if (this.config.frame){
// Limits coordinates to given frame if set in config
min = this.config.frame.origin.y;
max = this.config.frame.size.height + min;
} else {
// Returns a random Y coordinate within the screen rectangle
min = 0;
max = this.screenHeight();
}
return Math.floor(Math.random() * (max - min) + min) + 1;
};
UIAutoMonkey.prototype.randomTapCount = function() {
// Calculates a tap count for tap events based on touch probabilities
if (this.config.touchProbability.multipleTaps > Math.random()) {
return Math.floor(Math.random() * 10) % 3 + 1;
}
else return 1;
};
UIAutoMonkey.prototype.randomTouchCount = function() {
// Calculates a touch count for tap events based on touch probabilities
if (this.config.touchProbability.multipleTouches > Math.random()) {
return Math.floor(Math.random() * 10) % 3 + 1;
}
else return 1;
};
UIAutoMonkey.prototype.randomTapDuration = function() {
// Calculates whether or not a tap should be a long press based on
// touch probabilities
if (this.config.touchProbability.longPress > Math.random()) {
return 0.5;
}
else return 0;
};
UIAutoMonkey.prototype.randomRadians = function() {
// Returns a random radian value
return Math.random() * 10 % (3.14159 * 2);
};
UIAutoMonkey.prototype.takeScreenShotIfItIsTime = function() {
var now = (new Date()).valueOf();
if (!this._lastScreenshotTime) this._lastScreenshotTime = 0;
if (now - this._lastScreenshotTime > this.config.screenshotInterval * 1000) {
var filename = "monkey-" + (new Date()).toISOString().replace(/[:\.]+/g, "-");
this.target().captureScreenWithName(filename);
this._lastScreenshotTime = now;
}
};
// Commodity function to call RELEASE_THE_MONKEY directly on UIAutoMonkey
// if you don't need to customize your instance
UIAutoMonkey.RELEASE_THE_MONKEY = function() {
(new UIAutoMonkey()).RELEASE_THE_MONKEY();
};
UIAutoMonkey.RELEASE_THE_MONKEY();
Note: The Automation instrument works only with apps that have been code signed with a development provisioning profile when they are built in Xcode. Apps signed with a distribution provisioning profile cannot be controlled
with the UI Automation programming interface. However, because scripts run outside your app, the app version you are testing can be the same one you submit to the App Store, as long as you rebuild it with the distribution profile.
Important: Simulated actions may not prevent your test device from auto-locking. To ensure that auto-locking does not happen, before running tests on a device, you should set the Auto-Lock setting to Never.
iOS 8 Enhancement: iOS 8 includes a new Enable UI Automation preference under Settings > Developer, which allows third-party developers finer control of when their devices are available to perform automation. For physical
iOS devices, this setting is off by default and must be enabled prior to performing any UI Automation. In the simulator, the setting is enabled by default.
更多Instruments用法参考:
https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UsingtheAutomationInstrument/UsingtheAutomationInstrument.html#//apple_ref/doc/uid/TP40004652-CH20-SW1
Contact
Jonathan Penn
http://cocoamanifest.net
License
UIAutoMonkeyis available under the MIT license. See the LICENSE file for more info.
1,环境iMac OS X 10.9.5
2,工具Xcode Version 6.1 (6A1052c)
3,签约证书(开发者提供)
4,iphone设备(系统IOS6、IOS7、IOS8.1)
UI AUtoMonkey是一款非常简单的IOS压力测试工具。通过它,你可以向ios设备发送滑动、拖动、旋转、甚至锁屏和解锁指令。原文github地址:https://github.com/jonathanpenn/ui-auto-monkey
首先,使用xcode打开你的ios项目,从“Product”菜单中选择“Profile”(或者直接快捷键Command+i),这样就可以构建ios项目,并启动工具模板选择器。
下一步,在选择器中选择“UI Automation”。当我们创建了自动化模板后,就可以测试app的性能了。
在Scripts面板中,点击“Editor Log”,在下拉列表中选择“Script”,点击“Add”按钮,在下拉列表中选择”Create”,就可以新建一个js脚本。
将UIAutoMonkey.js这个文件的内容粘贴到新建的js脚本中(或者可以直接将UIAutoMonkey.jsimport进去。
此时,我们可以直接点击播放按钮,来执行这段脚本,monkey测试就开始了。
源码:"use strict";
function UIAutoMonkey() {
this.config = {
numberOfEvents: 1000, //产生随机事件的个数
delayBetweenEvents: 0.05, // 事件之间的延迟时间
// If the following line is uncommented, then screenshots are taken
// every "n" seconds.
//screenshotInterval: 5,
// Events are triggered based on the relative weights here. The event
// with this highest number gets triggered the most.
//
// If you want to add your own "events", check out the event method
// definitions below.
eventWeights: { //每个事件的触发几率,如果tab事件的值为100、orientation事件的值为1,那么tab事件触发的几率就是orientation的100倍。
tap: 500,
drag: 1, //拖
flick: 1, //轻击
orientation: 1, //定位
clickVolumeUp: 1,
clickVolumeDown: 1,
lock: 1,
pinchClose: 10, //捏
pinchOpen: 10,
shake: 1 //动摇
},
// Probability that touch events will have these different properties
touchProbability: { //控制着不同种类的tab事件
multipleTaps: 0.05,
multipleTouches: 0.05,
longPress: 0.05
}
// Uncomment the following to restrict events to a rectangluar area of
// the screen
/*
frame: {
origin: {x: 0, y: 0},
size: {width: 320, height: 480}
}
*/
};
}
// Event Methods
// Any event probability in the hash above corresponds to a related event
// method below. So, a "tap" probability will trigger a "tap" method.
//
// If you want to add your own events, just add a probability to the hash
// above and then add a corresponding method below. Boom!
// Each event method can call any other method on this UIAutoMonkey object.
// All the methods at the end are helpers at your disposal and feel free to
// add your own.
UIAutoMonkey.prototype.allEvents = {
tap: function() {
this.target().tapWithOptions(
{ x: this.randomX(), y: this.randomY() },
{
tapCount: this.randomTapCount(),
touchCount: this.randomTouchCount(),
duration: this.randomTapDuration()
}
);
},
drag: function() {
this.target().dragFromToForDuration(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() },
0.5
);
},
flick: function() {
this.target().flickFromTo(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() }
);
},
orientation: function() {
var orientations = [
UIA_DEVICE_ORIENTATION_PORTRAIT,
UIA_DEVICE_ORIENTATION_PORTRAIT_UPSIDEDOWN,
UIA_DEVICE_ORIENTATION_LANDSCAPELEFT,
UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT
];
var i = Math.floor(Math.random() * 10) % orientations.length;
var newOrientation = orientations[i];
this.target().setDeviceOrientation(newOrientation);
this.delay(0.9);
},
clickVolumeUp: function() {
this.target().clickVolumeUp();
},
clickVolumeDown: function() {
this.target().clickVolumeUp();
},
lock: function() {
this.target().lockForDuration(Math.random() * 3);
},
pinchClose: function () {
this.target().pinchCloseFromToForDuration(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() },
0.5
);
},
pinchOpen: function () {
this.target().pinchOpenFromToForDuration(
{ x: this.randomX(), y: this.randomY() },
{ x: this.randomX(), y: this.randomY() },
0.5
);
},
shake: function() { //摇
this.target().shake();
}
};
// --- --- --- ---
// Helper methods
UIAutoMonkey.prototype.RELEASE_THE_MONKEY = function() {
// Called at the bottom of this script to, you know...
//
// RELEASE THE MONKEY!
for(var i = 0; i < this.config.numberOfEvents; i++) {
this.triggerRandomEvent();
if (this.config.screenshotInterval) this.takeScreenShotIfItIsTime();
this.delay();
}
};
UIAutoMonkey.prototype.triggerRandomEvent = function() {
var name = this.chooseEventName();
// Find the event method based on the name of the event
var event = this.allEvents[name];
event.apply(this);
};
UIAutoMonkey.prototype.target = function() {
// Return the local target.
return UIATarget.localTarget();
};
UIAutoMonkey.prototype.delay = function(seconds) {
// Delay the target by `seconds` (can be a fraction)
// Defaults to setting in configuration
seconds = seconds || this.config.delayBetweenEvents;
this.target().delay(seconds);
};
UIAutoMonkey.prototype.chooseEventName = function() {
// Randomly chooses an event name from the `eventsWeight` dictionary
// based on the given weights.
var calculatedEventWeights = [];
var totalWeight = 0;
var events = this.config.eventWeights;
for (var event in events) {
if (events.hasOwnProperty(event)) {
calculatedEventWeights.push({
weight: events[event]+totalWeight,
event: event
});
totalWeight += events[event];
}
}
var chosenWeight = Math.random() * 1000 % totalWeight;
for (var i = 0; i < calculatedEventWeights.length; i++) {
if (chosenWeight < calculatedEventWeights[i].weight) {
return calculatedEventWeights[i].event;
}
}
throw "No even was chosen!";
};
UIAutoMonkey.prototype.screenWidth = function() {
// Need to adjust by one to stay within rectangle
return this.target().rect().size.width - 1;
};
UIAutoMonkey.prototype.screenHeight = function() {
// Need to adjust by one to stay within rectangle
return this.target().rect().size.height - 1;
};
UIAutoMonkey.prototype.randomX = function() {
var min, max;
if (this.config.frame){
// Limits coordinates to given frame if set in config
min = this.config.frame.origin.x;
max = this.config.frame.size.width + min;
} else {
// Returns a random X coordinate within the screen rectangle
min = 0;
max = this.screenWidth();
}
return Math.floor(Math.random() * (max - min) + min) + 1;
};
UIAutoMonkey.prototype.randomY = function() {
var min, max;
if (this.config.frame){
// Limits coordinates to given frame if set in config
min = this.config.frame.origin.y;
max = this.config.frame.size.height + min;
} else {
// Returns a random Y coordinate within the screen rectangle
min = 0;
max = this.screenHeight();
}
return Math.floor(Math.random() * (max - min) + min) + 1;
};
UIAutoMonkey.prototype.randomTapCount = function() {
// Calculates a tap count for tap events based on touch probabilities
if (this.config.touchProbability.multipleTaps > Math.random()) {
return Math.floor(Math.random() * 10) % 3 + 1;
}
else return 1;
};
UIAutoMonkey.prototype.randomTouchCount = function() {
// Calculates a touch count for tap events based on touch probabilities
if (this.config.touchProbability.multipleTouches > Math.random()) {
return Math.floor(Math.random() * 10) % 3 + 1;
}
else return 1;
};
UIAutoMonkey.prototype.randomTapDuration = function() {
// Calculates whether or not a tap should be a long press based on
// touch probabilities
if (this.config.touchProbability.longPress > Math.random()) {
return 0.5;
}
else return 0;
};
UIAutoMonkey.prototype.randomRadians = function() {
// Returns a random radian value
return Math.random() * 10 % (3.14159 * 2);
};
UIAutoMonkey.prototype.takeScreenShotIfItIsTime = function() {
var now = (new Date()).valueOf();
if (!this._lastScreenshotTime) this._lastScreenshotTime = 0;
if (now - this._lastScreenshotTime > this.config.screenshotInterval * 1000) {
var filename = "monkey-" + (new Date()).toISOString().replace(/[:\.]+/g, "-");
this.target().captureScreenWithName(filename);
this._lastScreenshotTime = now;
}
};
// Commodity function to call RELEASE_THE_MONKEY directly on UIAutoMonkey
// if you don't need to customize your instance
UIAutoMonkey.RELEASE_THE_MONKEY = function() {
(new UIAutoMonkey()).RELEASE_THE_MONKEY();
};
UIAutoMonkey.RELEASE_THE_MONKEY();
Note: The Automation instrument works only with apps that have been code signed with a development provisioning profile when they are built in Xcode. Apps signed with a distribution provisioning profile cannot be controlled
with the UI Automation programming interface. However, because scripts run outside your app, the app version you are testing can be the same one you submit to the App Store, as long as you rebuild it with the distribution profile.
Important: Simulated actions may not prevent your test device from auto-locking. To ensure that auto-locking does not happen, before running tests on a device, you should set the Auto-Lock setting to Never.
iOS 8 Enhancement: iOS 8 includes a new Enable UI Automation preference under Settings > Developer, which allows third-party developers finer control of when their devices are available to perform automation. For physical
iOS devices, this setting is off by default and must be enabled prior to performing any UI Automation. In the simulator, the setting is enabled by default.
更多Instruments用法参考:
https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UsingtheAutomationInstrument/UsingtheAutomationInstrument.html#//apple_ref/doc/uid/TP40004652-CH20-SW1
Contact
Jonathan Penn
http://cocoamanifest.net
License
UIAutoMonkeyis available under the MIT license. See the LICENSE file for more info.
相关文章推荐
- 使用java语言通过appium工具测试ios应用一些问题总结
- 【iOS测试系列】instruments工具的使用(二)- 通过Time Profiler
- 【iOS测试系列】instruments工具的使用(一)- 通过leaks分析内存泄露
- 如何理解、使用Android LogCat以及通过Monkey进行压力测试
- 测试配比时间研究[这是2周前起草的一个临时文档,目前已经通过评审发布]
- mini6410基于linux2.6.36内核通过NFS启动根文件系统总结(五内核测试 二 VFS: Cannot open root device "ubi0:FriendlyARM-root" )
- [易飞9.0]任务中心无法通过1000+压力测试?
- 使用 Load Runner 对web服务器压力测试总结
- 针对jpeg codec的FPGA测试总结
- LoadRunner压力测试心得总结
- 游戏服务器压力测试总结
- Tomcat6.0.18-压力测试总结
- BDD课题研究之测试思想和方法总结(二)
- 如何理解、使用Android LogCat以及通过Monkey进行压力测试
- gc野马通过压力测试(只有1K单位的容量,gc作用明显)
- mini6410基于linux2.6.36内核通过NFS启动根文件系统总结(五 内核测试 一 unrecognized/unsupported machine ID (r1=0x000009d8)
- 性能测试,负载测试,压力测试以及容量测试的联系与区别--网搜及总结
- xocde4.2和instruments通过wifi调试和测试的方法
- mini6410基于linux2.6.36内核通过NFS启动根文件系统总结(五 内核测试 三 通过bootargs设置根文件系统的启动位置)
- BDD课题研究之测试思想和方法总结(三)