crash_monkey 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/crash_monkey +10 -2
- data/crash_monkey.gemspec +2 -1
- data/lib/crash_monkey/monkey_runner.rb +2 -0
- data/lib/ui-auto-monkey/UIAutoMonkey.js +192 -215
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e14de4958e93963d8dd683171c772f110fb4d46f
|
4
|
+
data.tar.gz: 9817a004713bf1be90ca69a487a4e7d910a675b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61ee3ad3401b128f58cd2a2d813291a1fed19f0b9083cd9aed80fdc053f75c66cf924f9b67913af2017e5d542ad367ab070d283b3cb6db14e9b4c5cd9e789b9d
|
7
|
+
data.tar.gz: 004365bf7bcdd1ffdf42cea3c93f910d03c549778fd2815dc287fccd238752fae8cdfe319f2e0a8b9632c56213ecb15b0ad67612fe779b10c759df01951d0c6e
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.3
|
data/bin/crash_monkey
CHANGED
@@ -17,11 +17,19 @@ ARGV.options do |o|
|
|
17
17
|
o.on('-e extend_javascript_path', 'Extend Uiautomation Javascript for such Login scripts') {|b| opts[:extend_javascript_path] = File.expand_path(b)}
|
18
18
|
o.on('--show-config', 'Show Current Configuration JSON') {|_| opts[:show_config] = true}
|
19
19
|
o.on('--list-app', 'Show List of Installed Apps in iOS Simulator') {|_| opts[:list_app] = true}
|
20
|
-
o.on('--reset-iPhone-Simulator', 'Reset iPhone Simulator')
|
20
|
+
o.on('--reset-iPhone-Simulator', 'Reset iPhone Simulator'){|_| opts[:reset_iphone_simulator] = true}
|
21
|
+
o.on('--version', 'print crash monkey version'){|_| opts[:version] = true}
|
21
22
|
o.parse!
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
+
if opts[:version]
|
26
|
+
dirname = File.dirname(File.dirname(__FILE__))
|
27
|
+
filepath = File.join(dirname, "VERSION")
|
28
|
+
puts File.open(filepath, 'rb') { |file| file.read }
|
29
|
+
exit(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
unless opts[:app_path] || opts[:show_config] || opts[:list_app] || opts[:reset_iphone_simulator]
|
25
33
|
puts ARGV.options.help
|
26
34
|
exit(1)
|
27
35
|
end
|
data/crash_monkey.gemspec
CHANGED
@@ -5,7 +5,8 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{crash_monkey}
|
8
|
-
|
8
|
+
version_path = File.join(File.dirname(__FILE__), "VERSION")
|
9
|
+
s.version = File.read(version_path)
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
12
|
s.authors = ["Ken Morishita"]
|
@@ -25,6 +25,7 @@ module UIAutoMonkey
|
|
25
25
|
return true
|
26
26
|
elsif @options[:reset_iphone_simulator]
|
27
27
|
reset_iphone_simulator
|
28
|
+
return true
|
28
29
|
end
|
29
30
|
###########
|
30
31
|
log @options.inspect
|
@@ -137,6 +138,7 @@ module UIAutoMonkey
|
|
137
138
|
|
138
139
|
def reset_iphone_simulator
|
139
140
|
`rm -rf ~/Library/Application\ Support/iPhone\ Simulator/`
|
141
|
+
puts 'reset iPhone Simulator successful'
|
140
142
|
end
|
141
143
|
|
142
144
|
def total_test_count
|
@@ -1,7 +1,3 @@
|
|
1
|
-
/////////////////////////////////////////////////////////////////////////////////////
|
2
|
-
// ORIGINAL Copyright
|
3
|
-
/////////////////////////////////////////////////////////////////////////////////////
|
4
|
-
|
5
1
|
// Copyright (c) 2013 Jonathan Penn (http://cocoamanifest.net/)
|
6
2
|
|
7
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -22,19 +18,17 @@
|
|
22
18
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
19
|
// THE SOFTWARE.
|
24
20
|
|
25
|
-
/////////////////////////////////////////////////////////////////////////////////////
|
26
|
-
//
|
27
|
-
/////////////////////////////////////////////////////////////////////////////////////
|
28
|
-
|
29
|
-
|
30
21
|
"use strict";
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
config
|
23
|
+
function UIAutoMonkey() {
|
24
|
+
|
25
|
+
this.config = {
|
35
26
|
numberOfEvents: 1000,
|
36
27
|
delayBetweenEvents: 0.05, // In seconds
|
37
|
-
|
28
|
+
|
29
|
+
// If the following line is uncommented, then screenshots are taken
|
30
|
+
// every "n" seconds.
|
31
|
+
//screenshotInterval: 5,
|
38
32
|
|
39
33
|
// Events are triggered based on the relative weights here. The event
|
40
34
|
// with this highest number gets triggered the most.
|
@@ -43,16 +37,15 @@ var UIAutoMonkey = {
|
|
43
37
|
// definitions below.
|
44
38
|
eventWeights: {
|
45
39
|
tap: 500,
|
46
|
-
drag:
|
47
|
-
flick:
|
40
|
+
drag: 1,
|
41
|
+
flick: 1,
|
48
42
|
orientation: 1,
|
49
43
|
clickVolumeUp: 1,
|
50
44
|
clickVolumeDown: 1,
|
51
|
-
lock:
|
52
|
-
pinchClose:
|
53
|
-
pinchOpen:
|
54
|
-
shake: 1
|
55
|
-
deactivate: 3
|
45
|
+
lock: 1,
|
46
|
+
pinchClose: 10,
|
47
|
+
pinchOpen: 10,
|
48
|
+
shake: 1
|
56
49
|
},
|
57
50
|
|
58
51
|
// Probability that touch events will have these different properties
|
@@ -60,7 +53,7 @@ var UIAutoMonkey = {
|
|
60
53
|
multipleTaps: 0.05,
|
61
54
|
multipleTouches: 0.05,
|
62
55
|
longPress: 0.05
|
63
|
-
}
|
56
|
+
}
|
64
57
|
|
65
58
|
// Uncomment the following to restrict events to a rectangluar area of
|
66
59
|
// the screen
|
@@ -70,25 +63,28 @@ var UIAutoMonkey = {
|
|
70
63
|
size: {width: 100, height: 50}
|
71
64
|
}
|
72
65
|
*/
|
73
|
-
},
|
74
|
-
///////////////////////// __UIAutoMonkey Configuration End__ ///////////////////////////////
|
75
66
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
// Any event probability in the hash above corresponds to a related event
|
80
|
-
// method below. So, a "tap" probability will trigger a "tapEvent" method.
|
81
|
-
//
|
82
|
-
// If you want to add your own events, just add a probability to the hash
|
83
|
-
// above and then add a corresponding method below. Boom!
|
84
|
-
//
|
85
|
-
// Each event method can call any other method on this UIAutoMonkey object.
|
86
|
-
// All the methods at the end are helpers at your disposal and feel free to
|
87
|
-
// add your own.
|
67
|
+
};
|
68
|
+
|
69
|
+
}
|
88
70
|
|
89
|
-
|
90
|
-
|
91
|
-
|
71
|
+
// --- --- --- ---
|
72
|
+
// Event Methods
|
73
|
+
//
|
74
|
+
// Any event probability in the hash above corresponds to a related event
|
75
|
+
// method below. So, a "tap" probability will trigger a "tap" method.
|
76
|
+
//
|
77
|
+
// If you want to add your own events, just add a probability to the hash
|
78
|
+
// above and then add a corresponding method below. Boom!
|
79
|
+
//
|
80
|
+
// Each event method can call any other method on this UIAutoMonkey object.
|
81
|
+
// All the methods at the end are helpers at your disposal and feel free to
|
82
|
+
// add your own.
|
83
|
+
|
84
|
+
UIAutoMonkey.prototype.allEvents = {
|
85
|
+
tap: function() {
|
86
|
+
this.target().tapWithOptions(
|
87
|
+
{ x: this.randomX(), y: this.randomY() },
|
92
88
|
{
|
93
89
|
tapCount: this.randomTapCount(),
|
94
90
|
touchCount: this.randomTouchCount(),
|
@@ -97,19 +93,22 @@ var UIAutoMonkey = {
|
|
97
93
|
);
|
98
94
|
},
|
99
95
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
96
|
+
drag: function() {
|
97
|
+
this.target().dragFromToForDuration(
|
98
|
+
{ x: this.randomX(), y: this.randomY() },
|
99
|
+
{ x: this.randomX(), y: this.randomY() },
|
100
|
+
0.5
|
101
|
+
);
|
104
102
|
},
|
105
103
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
104
|
+
flick: function() {
|
105
|
+
this.target().flickFromTo(
|
106
|
+
{ x: this.randomX(), y: this.randomY() },
|
107
|
+
{ x: this.randomX(), y: this.randomY() }
|
108
|
+
);
|
110
109
|
},
|
111
110
|
|
112
|
-
|
111
|
+
orientation: function() {
|
113
112
|
var orientations = [
|
114
113
|
UIA_DEVICE_ORIENTATION_PORTRAIT,
|
115
114
|
UIA_DEVICE_ORIENTATION_PORTRAIT_UPSIDEDOWN,
|
@@ -123,211 +122,189 @@ var UIAutoMonkey = {
|
|
123
122
|
this.delay(0.9);
|
124
123
|
},
|
125
124
|
|
126
|
-
|
125
|
+
clickVolumeUp: function() {
|
127
126
|
this.target().clickVolumeUp();
|
128
127
|
},
|
129
128
|
|
130
|
-
|
131
|
-
this.target().
|
129
|
+
clickVolumeDown: function() {
|
130
|
+
this.target().clickVolumeUp();
|
132
131
|
},
|
133
132
|
|
134
|
-
|
133
|
+
lock: function() {
|
135
134
|
this.target().lockForDuration(Math.random() * 3);
|
136
135
|
},
|
137
136
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
137
|
+
pinchClose: function () {
|
138
|
+
this.target().pinchCloseFromToForDuration(
|
139
|
+
{ x: this.randomX(), y: this.randomY() },
|
140
|
+
{ x: this.randomX(), y: this.randomY() },
|
141
|
+
0.5
|
142
|
+
);
|
142
143
|
},
|
143
144
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
145
|
+
pinchOpen: function () {
|
146
|
+
this.target().pinchOpenFromToForDuration(
|
147
|
+
{ x: this.randomX(), y: this.randomY() },
|
148
|
+
{ x: this.randomX(), y: this.randomY() },
|
149
|
+
0.5
|
150
|
+
);
|
148
151
|
},
|
149
152
|
|
150
|
-
|
153
|
+
shake: function() {
|
151
154
|
this.target().shake();
|
152
|
-
}
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
}
|
156
|
+
};
|
157
|
+
|
158
|
+
// --- --- --- ---
|
159
|
+
// Helper methods
|
160
|
+
//
|
157
161
|
|
158
|
-
|
159
|
-
//
|
162
|
+
UIAutoMonkey.prototype.RELEASE_THE_MONKEY = function() {
|
163
|
+
// Called at the bottom of this script to, you know...
|
160
164
|
//
|
165
|
+
// RELEASE THE MONKEY!
|
161
166
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
},
|
169
|
-
|
170
|
-
deleteImage: function(dir, from, to) {
|
171
|
-
var host = this.target().host();
|
172
|
-
var files = [];
|
173
|
-
for (var i=from; i < to; i++) {
|
174
|
-
files.push(dir + "/screen-"+i + ".png");
|
175
|
-
// files.push(dir + "/action-"+i + ".png");
|
176
|
-
}
|
177
|
-
host.performTaskWithPathArgumentsTimeout("/bin/rm", files, 5);
|
178
|
-
},
|
179
|
-
|
180
|
-
RELEASE_THE_MONKEY: function() {
|
181
|
-
// Called at the bottom of this ui-auto-monkey to, you know...
|
182
|
-
//
|
183
|
-
// RELEASE THE MONKEY!
|
184
|
-
var target = this.target();
|
185
|
-
var initBundleID = target.frontMostApp().bundleID();
|
186
|
-
var results_path = this.results_path();
|
187
|
-
var result_num = this.config.result_detail_event_num;
|
188
|
-
|
189
|
-
for(var i = 0; i < this.config.numberOfEvents; i++) {
|
190
|
-
// Delete old images
|
191
|
-
if (i % 10 == 0 && i > result_num) {
|
192
|
-
this.deleteImage(results_path, i-result_num-10, i-result_num);
|
193
|
-
}
|
194
|
-
// Capture Screen Image
|
195
|
-
target.captureScreenWithName("screen-" + i);
|
196
|
-
// if another application become frontMost, exit.
|
197
|
-
var bundleID = target.frontMostApp().bundleID();
|
198
|
-
if (bundleID != initBundleID) {
|
199
|
-
UIALogger.logDebug("************************ Different Application **************: " + bundleID);
|
200
|
-
break;
|
201
|
-
}
|
202
|
-
|
203
|
-
// Send Random Event
|
204
|
-
this.triggerRandomEvent();
|
205
|
-
|
206
|
-
// Wait
|
207
|
-
this.delay();
|
208
|
-
}
|
209
|
-
},
|
167
|
+
for(var i = 0; i < this.config.numberOfEvents; i++) {
|
168
|
+
this.triggerRandomEvent();
|
169
|
+
if (this.config.screenshotInterval) this.takeScreenShotIfItIsTime();
|
170
|
+
this.delay();
|
171
|
+
}
|
172
|
+
};
|
210
173
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
174
|
+
UIAutoMonkey.prototype.triggerRandomEvent = function() {
|
175
|
+
var name = this.chooseEventName();
|
176
|
+
// Find the event method based on the name of the event
|
177
|
+
var event = this.allEvents[name];
|
178
|
+
event.apply(this);
|
179
|
+
};
|
217
180
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
181
|
+
UIAutoMonkey.prototype.target = function() {
|
182
|
+
// Return the local target.
|
183
|
+
return UIATarget.localTarget();
|
184
|
+
};
|
222
185
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
186
|
+
UIAutoMonkey.prototype.delay = function(seconds) {
|
187
|
+
// Delay the target by `seconds` (can be a fraction)
|
188
|
+
// Defaults to setting in configuration
|
189
|
+
seconds = seconds || this.config.delayBetweenEvents;
|
190
|
+
this.target().delay(seconds);
|
191
|
+
};
|
229
192
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
}
|
193
|
+
UIAutoMonkey.prototype.chooseEventName = function() {
|
194
|
+
// Randomly chooses an event name from the `eventsWeight` dictionary
|
195
|
+
// based on the given weights.
|
196
|
+
var calculatedEventWeights = [];
|
197
|
+
var totalWeight = 0;
|
198
|
+
var events = this.config.eventWeights;
|
199
|
+
for (var event in events) {
|
200
|
+
if (events.hasOwnProperty(event)) {
|
201
|
+
calculatedEventWeights.push({
|
202
|
+
weight: events[event]+totalWeight,
|
203
|
+
event: event
|
204
|
+
});
|
205
|
+
totalWeight += events[event];
|
244
206
|
}
|
207
|
+
}
|
245
208
|
|
246
|
-
|
209
|
+
var chosenWeight = Math.random() * 1000 % totalWeight;
|
247
210
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
}
|
211
|
+
for (var i = 0; i < calculatedEventWeights.length; i++) {
|
212
|
+
if (chosenWeight < calculatedEventWeights[i].weight) {
|
213
|
+
return calculatedEventWeights[i].event;
|
252
214
|
}
|
215
|
+
}
|
253
216
|
|
254
|
-
|
255
|
-
|
217
|
+
throw "No even was chosen!";
|
218
|
+
};
|
256
219
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
220
|
+
UIAutoMonkey.prototype.screenWidth = function() {
|
221
|
+
// Need to adjust by one to stay within rectangle
|
222
|
+
return this.target().rect().size.width - 1;
|
223
|
+
};
|
261
224
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
225
|
+
UIAutoMonkey.prototype.screenHeight = function() {
|
226
|
+
// Need to adjust by one to stay within rectangle
|
227
|
+
return this.target().rect().size.height - 1;
|
228
|
+
};
|
266
229
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
230
|
+
UIAutoMonkey.prototype.randomX = function() {
|
231
|
+
var min, max;
|
232
|
+
|
233
|
+
if (this.config.frame){
|
234
|
+
// Limits coordinates to given frame if set in config
|
235
|
+
min = this.config.frame.origin.x;
|
236
|
+
max = this.config.frame.size.width + min;
|
237
|
+
} else {
|
238
|
+
// Returns a random X coordinate within the screen rectangle
|
239
|
+
min = 0;
|
240
|
+
max = this.screenWidth();
|
241
|
+
}
|
279
242
|
|
280
|
-
|
281
|
-
|
243
|
+
return Math.floor(Math.random() * (max - min) + min) + 1;
|
244
|
+
};
|
282
245
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
246
|
+
UIAutoMonkey.prototype.randomY = function() {
|
247
|
+
var min, max;
|
248
|
+
|
249
|
+
if (this.config.frame){
|
250
|
+
// Limits coordinates to given frame if set in config
|
251
|
+
min = this.config.frame.origin.y;
|
252
|
+
max = this.config.frame.size.height + min;
|
253
|
+
} else {
|
254
|
+
// Returns a random Y coordinate within the screen rectangle
|
255
|
+
min = 0;
|
256
|
+
max = this.screenHeight();
|
257
|
+
}
|
295
258
|
|
296
|
-
|
297
|
-
|
259
|
+
return Math.floor(Math.random() * (max - min) + min) + 1;
|
260
|
+
};
|
298
261
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
262
|
+
UIAutoMonkey.prototype.randomTapCount = function() {
|
263
|
+
// Calculates a tap count for tap events based on touch probabilities
|
264
|
+
if (this.config.touchProbability.multipleTaps > Math.random()) {
|
265
|
+
return Math.floor(Math.random() * 10) % 3 + 1;
|
266
|
+
}
|
267
|
+
else return 1;
|
268
|
+
};
|
306
269
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
270
|
+
UIAutoMonkey.prototype.randomTouchCount = function() {
|
271
|
+
// Calculates a touch count for tap events based on touch probabilities
|
272
|
+
if (this.config.touchProbability.multipleTouches > Math.random()) {
|
273
|
+
return Math.floor(Math.random() * 10) % 3 + 1;
|
274
|
+
}
|
275
|
+
else return 1;
|
276
|
+
};
|
314
277
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
278
|
+
UIAutoMonkey.prototype.randomTapDuration = function() {
|
279
|
+
// Calculates whether or not a tap should be a long press based on
|
280
|
+
// touch probabilities
|
281
|
+
if (this.config.touchProbability.longPress > Math.random()) {
|
282
|
+
return 0.5;
|
283
|
+
}
|
284
|
+
else return 0;
|
285
|
+
};
|
323
286
|
|
324
|
-
|
325
|
-
|
326
|
-
|
287
|
+
UIAutoMonkey.prototype.randomRadians = function() {
|
288
|
+
// Returns a random radian value
|
289
|
+
return Math.random() * 10 % (3.14159 * 2);
|
290
|
+
};
|
291
|
+
|
292
|
+
UIAutoMonkey.prototype.takeScreenShotIfItIsTime = function() {
|
293
|
+
var now = (new Date()).valueOf();
|
294
|
+
if (!this._lastScreenshotTime) this._lastScreenshotTime = 0;
|
295
|
+
|
296
|
+
if (now - this._lastScreenshotTime > this.config.screenshotInterval * 1000) {
|
297
|
+
var filename = "monkey-" + (new Date()).toISOString().replace(/[:\.]+/g, "-");
|
298
|
+
this.target().captureScreenWithName(filename);
|
299
|
+
this._lastScreenshotTime = now;
|
327
300
|
}
|
328
301
|
};
|
329
302
|
|
303
|
+
// Commodity function to call RELEASE_THE_MONKEY directly on UIAutoMonkey
|
304
|
+
// if you don't need to customize your instance
|
305
|
+
UIAutoMonkey.RELEASE_THE_MONKEY = function() {
|
306
|
+
(new UIAutoMonkey()).RELEASE_THE_MONKEY();
|
307
|
+
};
|
308
|
+
|
330
309
|
UIAutoMonkey.RELEASE_THE_MONKEY();
|
331
310
|
|
332
|
-
/* Instruments uses 4-wide tab stops. */
|
333
|
-
/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 copyindent noexpandtab: */
|