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
//
// 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>
#import <MJExtension/MJExtension.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];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:PhobosGray];
[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 = @"";
Phobos.sharedClient.getTopController = ^UIViewController * _Nonnull{
return [UIViewController new];
};
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
[Phobos removeAllPhobosData];
}
/**
* @brief 测试有用户ID的时候,埋点事件是否正确
*
* @since <#version number#>
*/
- (void)testClientWithUserId{
[self setUp];
[Phobos removeAllPhobosData];
[Phobos.sharedClient setUserId:MockUserId];
[Phobos.sharedClient setCurrentCityId:MockCityId];
[Phobos track:MockEventId];
[NSThread sleepForTimeInterval:0.2];
NSArray<PhobosSendDataEntity *> *array = [Phobos fetchToBeSendPhobosData];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array.firstObject.data mj_JSONObject];
[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<PhobosSendDataEntity *> *array = [Phobos fetchToBeSendPhobosData];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array.firstObject.data mj_JSONObject];
[self verfiyDict:dict];
}
/**
* @brief 测试发送带参数事件成功
*
* @since <#version number#>
*/
- (void)testTrackEventWithAttr{
NSDictionary *attr = @{@"attr":@"track_attr"};
[Phobos track:MockEventId attributes:attr];
NSArray<PhobosSendDataEntity *> *array = [Phobos fetchToBeSendPhobosData];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array.firstObject.data mj_JSONObject];
[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 removeAllPhobosData];
// Given
NSDictionary *attr = @{@"attr":@"track_attr"};
// When
[Phobos track:MockEventId attributes:attr sendNow:YES];
// Then
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 0, @"array should be empty");
}
/**
* @brief 测试立即发送带参数事件成功,应该把普通埋点也带上
*
* @since 1.1.4
*/
- (void)testTrackEventWithAttrAndSendNowDonotClearNormal {
// Given
[Phobos removeAllPhobosData];
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 fetchToBeSendPhobosDataCount] == 0, @"array should be empty");
}
/**
* @brief 测试二次立即发送带参数事件成功,不应该重复发送上一条
*
* @since 1.1.4
*/
- (void)testTrackEventWithDoubleAttrAndSendNow {
[Phobos removeAllPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
[Phobos track:MockEventId attributes:attr sendNow:YES];
// 因为实时埋点是异步删除,所以这个位置暂时延时取数据,待优化 TODO
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr sendNow:YES];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr sendNow:YES];
}
/**
* @brief 测试不立即发送带参数事件成功后,数据会被清除
*
* @since 1.1.4
*/
- (void)testTrackEventWithDoubleAttrAndNoSendNow {
[Phobos removeAllPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
//
[Phobos track:MockEventId attributes:attr];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 1, @"array shouldn't be empty");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
for (int i = 0; i < 50; i++) {
[Phobos track:MockEventId attributes:attr];
}
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 1, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 2, @"array shouldn't be empty");
}
/**
* @brief 测试不实时和实时穿插 1
*
* @since 1.1.4
*/
- (void)testTrackEventWithSendNowAndNoSendNowOne {
[Phobos removeAllPhobosData];
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 fetchToBeSendPhobosDataCount] == 30, @"array shouldn't be empty");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:NO];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 1, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 1, @"array shouldn't be empty");
}
/**
* @brief 测试不实时和实时穿插 3
*
* @since 1.1.4
*/
- (void)testTrackEventWithSendNowAndNoSendNowThree {
[Phobos removeAllPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
//
[Phobos track:MockEventId attributes:attr];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 1, @"array shouldn't be empty");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
for (int i = 0; i < 50; i++) {
[Phobos track:MockEventId attributes:attr];
}
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 1, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 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");
XCTAssertTrue([keys containsObject:@"absolute_time"], @"Missing absolute_time");
XCTAssertTrue([keys containsObject:@"create_at_millis"], @"Missing create_at_millis");
XCTAssertTrue([keys containsObject:@"nano_time"], @"Missing nano_time");
XCTAssertTrue([[dict[@"params"] allKeys] containsObject:@"referrer_link"],@"Missing referrer_link");
XCTAssertTrue((dict[@"params"][@"referrer_link"] != nil || ![dict[@"params"][@"referrer_link"] isEqual:@{}] || dict[@"params"][@"referrer_link"] != NULL), @"referrer_link至少使用默认的[]");
}
- (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.isPush = @"1";
controller.pageName = @"pageNameTest";
controller.businessId = @"businessIdTest";
controller.referrerId = @"rreferrerIdTest";
[controller viewWillAppear:true];
[controller viewWillDisappear:true];
[self paramUnNilCheck];
NSArray<PhobosSendDataEntity *> *array = [Phobos fetchToBeSendPhobosData];
XCTAssertTrue(array.count != 0, @"PhobosCacheKey 下面应该有数据");
NSDictionary *dic = [array.firstObject.data mj_JSONObject][@"params"];
XCTAssertTrue([dic[@"referrer_id"] isEqualToString:@"rreferrerIdTest"], @"referrerId至少使用默认的空字符串");
}
- (void)paramUnNilCheck {
NSArray<PhobosSendDataEntity *> *array = [Phobos fetchToBeSendPhobosData];
XCTAssertTrue(array.count != 0, @"PhobosCacheKey 下面应该有数据");
NSDictionary *dic = [array.firstObject.data mj_JSONObject][@"params"];
XCTAssertTrue(dic[@"page_name"] != nil, @"page_name至少使用默认的空字符串");
XCTAssertTrue([dic[@"referer"] integerValue] >= 0, @"referer至少使用默认的空字符串");
XCTAssertTrue(dic[@"business_id"] != nil, @"business_id至少使用默认的空字符串");
XCTAssertTrue(dic[@"in_time_millis"] != nil, @"in_time_millis至少使用默认的空字符串");
XCTAssertTrue(dic[@"out_time_millis"] != nil, @"out_time_millis至少使用默认的空字符串");
XCTAssertTrue((dic[@"referrer_link"] != nil || ![dic[@"referrer_link"] isEqual:@{}] || dic[@"referrer_link"] != NULL), @"referrer_link至少使用默认的[]");
}
#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 removeAllPhobosData];
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<SendDataEntity *> *array = [Phobos fetchToBeSendPhobosData];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue(array.count == 1, @"PhobosCacheKey 下面应该有数据");
[Phobos track:@"page_view" attributes:dict];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 2, @"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 fetchToBeSendPhobosDataCount]== 2, @"PhobosCacheKey 上条数据应该发送");
[Phobos track:@"page_view" attributes:dict];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 2, @"PhobosCacheKey 上条数据不应该发送");
[Phobos track:@"test" attributes:dict];
[NSThread sleepForTimeInterval:0.2];
XCTAssertTrue([Phobos fetchToBeSendPhobosDataCount] == 3, @"PhobosCacheKey 上条数据应该发送");
}
*/
#pragma mark - 其它方法test
- (void)testVisibleController {
}
@end