1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
//
// GMPhotoTest.m
// GMPhobos
//
// Created by Thierry on 16/1/28.
// Copyright © 2016年 licong. All rights reserved.
//
#import <XCTest/XCTest.h>
#import <GMPhobos/Phobos.h>
#import "GMPhobosController.h"
#import <GMCache/GMCache.h>
NSString *const MockAppName = @"gengmei_test";
NSString *const MockChannelId = @"AppStore";
NSString *const MockEventId = @"eventId";
NSString *const MockUserId = @"1";
NSString *const MockCityId = @"beijing";
@interface GMPhotoTest : XCTestCase
@end
///[NSThread sleepForTimeInterval:0.2]; 因为是异步处理数据,所以需要延迟获取,进行单元测试
@implementation GMPhotoTest
- (void)setUp {
[super setUp];
[Phobos clientWithAppName:MockAppName channelId:MockChannelId];
Phobos.sharedClient.serverAPI = @"http://log.test.igengmei.com/log/collect";
Phobos.sharedClient.logEnabled = NO; // 调试打Log模式,看情况开启
Phobos.sharedClient.signingType = PhobosSigningTypeDebug;
Phobos.sharedClient.userId = @"";
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
[Phobos removeAllNormalPhobosData];
[Phobos removeAllImmediatelyPhobosData];
}
/**
* @brief 测试有用户ID的时候,埋点事件是否正确
*
* @since <#version number#>
*/
- (void)testClientWithUserId{
[Phobos removeAllNormalPhobosData];
[Phobos.sharedClient setUserId:MockUserId];
[Phobos.sharedClient setCurrentCityId:MockCityId];
[Phobos track:MockEventId];
[NSThread sleepForTimeInterval:0.2];
NSArray *array = [Phobos normalPhobosDataForServerAPI];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array objectAtIndex:0];
[self verfiyDict:dict];
XCTAssertTrue([[dict objectForKey:@"user_id"] isEqualToString:MockUserId] , @"Invalid user_id value");
}
/**
* @brief 测试发送不带参数事件成功 (由之前的实例方法变成类方法)
*
* @since <#version number#>
*/
- (void)testTrackEventWithoutAttr{
[Phobos track:MockEventId];
[NSThread sleepForTimeInterval:0.2];
NSArray *array = [Phobos normalPhobosDataForServerAPI];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array objectAtIndex:0];
[self verfiyDict:dict];
}
/**
* @brief 测试发送带参数事件成功
*
* @since <#version number#>
*/
- (void)testTrackEventWithAttr{
NSDictionary *attr = @{@"attr":@"track_attr"};
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
NSArray *array = [Phobos normalPhobosDataForServerAPI];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array objectAtIndex:0];
[self verfiyDict:dict];
//验证Param的值是否正确
NSString *value = [[dict valueForKey:@"params"] valueForKey:@"attr"];
XCTAssertTrue([value isEqualToString:@"track_attr"], @"Invalid event attributes");
}
/**
* @brief 测试立即发送带参数事件成功
*
* @since <#version number#>
*/
- (void)testTrackEventWithAttrAndSendNow{
[Phobos removeAllNormalPhobosData];
// Given
NSDictionary *attr = @{@"attr":@"track_attr"};
// When
[Phobos track:MockEventId attributes:attr sendNow:YES];
// Then
XCTAssertTrue([Phobos normalPhobosCount] == 0, @"array should be empty");
}
/**
* @brief 测试立即发送带参数事件成功,不应该清除不立即发送的埋点
*
* @since 1.1.4
*/
- (void)testTrackEventWithAttrAndSendNowDonotClearNormal {
// Given
NSDictionary *attr = @{@"attr":@"track_attr"};
NSDictionary *sendNowAttr = @{@"attr":@"track_attr_send_now"};
// When
[Phobos track:MockEventId attributes:attr sendNow:NO];
// When
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
XCTAssertTrue([Phobos normalPhobosCount] != 0, @"array shouldn't be empty");
}
/**
* @brief 测试二次立即发送带参数事件成功,不应该重复发送上一条
*
* @since 1.1.4
*/
- (void)testTrackEventWithDoubleAttrAndSendNow {
NSDictionary *attr = @{@"attr":@"track_attr"};
[Phobos track:MockEventId attributes:attr sendNow:YES];
// 因为实时埋点是异步删除,所以这个位置暂时延时取数据,待优化 TODO
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSArray *array = [Phobos immediatelyPhobosForServerAPI];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr sendNow:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSArray *array = [Phobos immediatelyPhobosForServerAPI];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr sendNow:YES];
array = [Phobos normalPhobosDataForServerAPI];
XCTAssertTrue([Phobos normalPhobosCount] == 0, @"array shouldn't be empty");
});
});
}
/**
* @brief 测试不立即发送带参数事件成功后,数据会被清除
*
* @since 1.1.4
*/
- (void)testTrackEventWithDoubleAttrAndNoSendNow {
[Phobos removeAllNormalPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
//
[NSThread sleepForTimeInterval:0.2];
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 1, @"array shouldn't be empty");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
for (int i = 0; i < 50; i++) {
[Phobos track:MockEventId attributes:attr];
}
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 1, @"array shouldn't be empty");
[NSThread sleepForTimeInterval:0.2];
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 2, @"array shouldn't be empty");
}
/**
* @brief 测试不实时和实时穿插 1
*
* @since 1.1.4
*/
- (void)testTrackEventWithSendNowAndNoSendNowOne {
[Phobos removeAllNormalPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
NSDictionary *sendNowAttr = @{@"attr":@"track_attr_send_now"};
for (int i = 0; i < 30; i++) {
[Phobos track:MockEventId attributes:attr];
}
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 30, @"array shouldn't be empty");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 30, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 30, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 30, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 31, @"array shouldn't be empty");
}
/**
* @brief 测试不实时和实时穿插 2
*
* @since 1.1.4
*/
- (void)testTrackEventWithSendNowAndNoSendNowTwo {
[Phobos removeAllNormalPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
NSDictionary *sendNowAttr = @{@"attr":@"track_attr_send_now"};
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 1, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 2, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 2, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 3, @"array shouldn't be empty");
}
/**
* @brief 测试不实时和实时穿插 3
*
* @since 1.1.4
*/
- (void)testTrackEventWithSendNowAndNoSendNowThree {
[Phobos removeAllNormalPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
//
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 1, @"array shouldn't be empty");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
for (int i = 0; i < 50; i++) {
[Phobos track:MockEventId attributes:attr];
}
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 1, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 2, @"array shouldn't be empty");
}
- (void)verfiyDict:(NSDictionary *)dict{
NSArray *keys = [dict allKeys];
XCTAssertTrue([keys containsObject:@"type"], @"Missing type");
XCTAssertTrue([keys containsObject:@"app"], @"Missing app");
XCTAssertTrue([keys containsObject:@"version"], @"Missing version");
XCTAssertTrue([keys containsObject:@"device"], @"Missing device");
XCTAssertTrue([keys containsObject:@"user_id"], @"Missing user_id");
XCTAssertTrue([keys containsObject:@"create_at"], @"Missing create_at");
XCTAssertTrue([keys containsObject:@"params"], @"Missing params");
}
- (void)testCatchNullInAttributes {
Phobos.sharedClient.captureNullExpection = ^(NSString *eventId, NSDictionary *att) {
NSCAssert([att[@"bussness_id"] integerValue] == 1244, @"testCatchNullInAttributes 没有捕获到有用信息");
};
NSDictionary *attributes = @{@"key": [NSNull null],
@"bussness_id": @1244};
[Phobos track:@"testCatchNullInAttributes" attributes:attributes];
}
// 某种情况下没有先走 onPageStart,只走了OnPageEnd,此时数据应该完整,某个key对应的value可以是空
- (void)testOnPageStart {
GMPhobosController *controller = [GMPhobosController new];
controller.pageName = @"pageNameTest";
controller.businessId = @"businessIdTest";
controller.referrerId = @"rreferrerIdTest";
[controller viewWillAppear:true];
XCTAssertTrue(controller.inTime.integerValue > 0, "inTime 应该有值");
}
// 某种情况下没有先走 onPageStart,只走了OnPageEnd,此时数据应该完整,某个key对应的value可以是空
- (void)testOnPageEnd {
GMPhobosController *controller = [GMPhobosController new];
controller.pageName = @"pageNameTest";
controller.businessId = @"businessIdTest";
controller.referrerId = @"rreferrerIdTest";
[controller viewWillAppear:true];
[controller viewWillDisappear:true];
[self paramUnNilCheck];
[NSThread sleepForTimeInterval:0.2];
NSArray *array = [Phobos normalPhobosDataForServerAPI];
XCTAssertTrue(array.count != 0, @"PhobosCacheKey 下面应该有数据");
NSDictionary *dic = array[0][@"params"];
XCTAssertTrue([dic[@"referrer_id"] isEqualToString:@"rreferrerIdTest"], @"referrerId至少使用默认的空字符串");
}
- (void)testSimulativePageViewEvent {
[NSThread sleepForTimeInterval:0.2];
[Phobos.sharedClient simulativePV:nil businessId:nil referer:nil];
[self paramUnNilCheck];
}
- (void)paramUnNilCheck {
[NSThread sleepForTimeInterval:0.2];
NSArray *array = [Phobos normalPhobosDataForServerAPI];
XCTAssertTrue(array.count != 0, @"PhobosCacheKey 下面应该有数据");
NSDictionary *dic = array[0][@"params"];
XCTAssertTrue(dic[@"page_name"] != nil, @"page_name至少使用默认的空字符串");
XCTAssertTrue([dic[@"referer"] integerValue] >= 0, @"referer至少使用默认的空字符串");
XCTAssertTrue(dic[@"business_id"] != nil, @"business_id至少使用默认的空字符串");
}
#pragma mark - 属性test
- (void)testNeedLogPV {
UIViewController *controller = [UIViewController new];
XCTAssertTrue(controller.needLogPV, @"needLogPV应该默认为YES");
controller.needLogPV = NO;
XCTAssertFalse(controller.needLogPV, @"needLogPV赋值为NO时应该NO");
}
// 该单元测试暂时不用,因为过滤代码暂时不用,所以不需要跑通
- (void)testCheckPVPhobos {
[Phobos removeAllNormalPhobosData];
NSString *inDate = [PhobosUtil currentTime];
[NSThread sleepForTimeInterval:1];//模拟浏览页面,让out和in时间相差1s
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[PhobosUtil currentTime] forKey:@"out"];
[dict setObject:inDate forKey:@"in"];
[dict setObject:@"test" forKey:@"page_name"];
[dict setObject:@"" forKey:@"business_id"];
[dict setObject:@"" forKey:@"referrer"];
[dict setObject:@(0) forKey:@"fake"];
[dict setObject:@"" forKey:@"referrer_id"];
[dict setObject:@"" forKey:@"extra_param"];
[dict setObject:@"" forKey:@"referrer_tab_name"];
[dict setObject:@(0) forKey:@"is_push"];
[Phobos track:@"page_view" attributes:dict];
NSArray *array = [Phobos normalPhobosDataForServerAPI];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue(array.count == 1, @"PhobosCacheKey 下面应该有数据");
[Phobos track:@"page_view" attributes:dict];
XCTAssertTrue([Phobos normalPhobosCount] == 1, @"PhobosCacheKey 上条数据不应该发送");
[NSThread sleepForTimeInterval:2];//模拟浏览页面,让第二次浏览和上一次时间相差2s
[dict setObject:[PhobosUtil currentTime] forKey:@"in"];
[NSThread sleepForTimeInterval:1];//模拟浏览页面,让out和in时间相差1s
[dict setObject:[PhobosUtil currentTime] forKey:@"out"];
[Phobos track:@"page_view" attributes:dict];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount]== 2, @"PhobosCacheKey 上条数据应该发送");
[Phobos track:@"page_view" attributes:dict];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 2, @"PhobosCacheKey 上条数据不应该发送");
[Phobos track:@"test" attributes:dict];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos normalPhobosCount] == 3, @"PhobosCacheKey 上条数据应该发送");
}
#pragma mark - 其它方法test
- (void)testVisibleController {
}
@end