iOS生成追溯關系的邏輯和Android端從用戶角度來說是一致的,就是需要通過開始和結束關聯用例,將用例信息與覆蓋率信息建立關系,然后再解析覆蓋率數據。
4.3.1 添加關聯用例彈層
關聯用例彈層和Android類似,只要你能設計出相應的樣式即可,下面給出彈層的部分代碼,你可以根據自己的需求進行優化。
- (void)addFoatingMicInView:(UIView *)view :(NSString *) acenv :(NSString *)kbuildid :(createSwiftCodeCov *) cscc{//添加浮層代碼,人工打點獲取覆蓋率數據self.uistackview=[[UIStackView alloc] initWithFrame:CGRectMake(10, 100, 250, 40)];self.uistackview.axis=UILayoutConstraintAxisHorizontal;self.uistackview.spacing=1;self.uistackview.backgroundColor=UIColor.lightGrayColor;self.uistackview.layer.cornerRadius=20;//添加標簽,用于占位self.caseidlabel=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 20)];self.caseidlabel.text=@" ";[self.uistackview addArrangedSubview:self.caseidlabel];//標簽self.corelabel=[[UILabel alloc] initWithFrame:CGRectMake(10, 0, 20, 20)];self.corelabel.text=@"開始關聯用例ID: ";self.corelabel.textAlignment=NSTextAlignmentLeft;self.corelabel.font= [UIFont systemFontOfSize:14];[self.uistackview addArrangedSubview:self.corelabel];//buttonself.uibutton=[UIButton buttonWithType:UIButtonTypeCustom];self.uibutton.frame=CGRectMake(0, 0, 0, 0 );[self.uibutton setImage:[UIImage imageNamed:@"record"] forState:UIControlStateNormal];[self.uibutton setImageEdgeInsets:UIEdgeInsetsMake(8, 0, 8, 0)];self.uibutton.imageView.contentMode=UIViewContentModeScaleAspectFit;[self.uistackview addArrangedSubview:self.uibutton];[view addSubview:self.uistackview];self.panSuperView =view;UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panFloatingMic:)];[self.uistackview addGestureRecognizer:pan];UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(recordClick:)];[self.uibutton addGestureRecognizer:tap];//初始化時隱藏self.uistackview.hidden=YES;}//新定義button點擊事件
-(void) recordClick:(UITapGestureRecognizer *)tap {//刪除覆蓋率數據文件NSLog(@"********開始錄制覆蓋率數據********");self.uibutton.hidden=true;//開始錄制deeplinkNSString *tmp=[@"用例ID: " stringByAppendingString: self.caseid];self.corelabel.text=[tmp stringByAppendingString:@"錄制中.... "];self.corelabel.textAlignment=NSTextAlignmentLeft;if ([self.covflag isEqual:@"2"]){NSLog(@"先上傳自動收集的覆蓋率數據,再清空收集用例覆蓋率數據!");//先上傳自動收集的覆蓋率數據,再清空收集用例覆蓋率數據 2022-12-12[self.swiftoper uploadCodeCoverageFiles:@"" :@""];NSLog(@"上傳自動收集的覆蓋率數據,開始收集用例對應的覆蓋率數據!");[self.swiftoper clearCodeCoverageFiles];}else{//開始錄制用例,清除舊的覆蓋率數據文件[self.swiftoper clearCodeCoverageFiles];}}//關閉收集覆蓋率彈層
- (void)hideFloatingMicrophone{NSString *tmp=[@"關聯用例ID:" stringByAppendingString: self.caseid];self.corelabel.text=[tmp stringByAppendingString:@"結束!!! "];self.corelabel.textAlignment=NSTextAlignmentLeft;[self performSelector:@selector(dissmisfloatview:)withObject:self.uistackview afterDelay:3.0];//上傳覆蓋率數據[self.swiftoper uploadCodeCoverageFiles:self.caseid :@""];
}
彈層示例:
樣式做的比較簡單,需要請專業人員進行優化一下。
4.3.2 覆蓋率文件解析
通過關聯用例操作,可以將覆蓋率數據文件上傳到精準測試平臺,現在分兩種情況再進行解析:
一,Object C覆蓋率解析
1,獲取gcda文件
通過關聯用例操作,拿到指定文件夾下的所有gcda文件,也就是被測試應用的覆蓋率數據文件,是一個zip包。
2,構建文件
通過構建平臺,拿到.o,.gcno文件,再從git上下載源碼。
3,將所有文件放在一起
將源碼文件,.o, .gcno, .gcda文件放在一起。
4,生成覆蓋率報告
執行下面兩個命令:
geninfo --ignore-errors inconsistent
-o coverage.info ./qt-360-master genhtml
--ignore-errors inconsistent
-o coverage_report coverage.info
5,解析info文件
讀取info文件,通過對應行號的執行次數來解析文件覆蓋的行啊。也就是說一個類中,對應的行號只要不為0,就把行號記錄下來,最后得到文件行號列表:
SF:/Users/*****/TestmPinYin.swift
FN:16,$s4Kima9KimPinYinC7preloadyyFZ
...
FNF:14
FNH:1
DA:16,2
DA:17,2
DA:18,2
DA:20,0
DA:21,0
DA:22,0
DA:23,0
DA:24,0
.....
得到覆蓋文件詳情
{"/Users/*****/TestmPinYin.swift":[16,17,18],"文件2":[行號列表]....}
6,分析類中的函數
使用工具:https://github.com/L-Zephyr/Drafter,來解析一個類中的函數
使用命令:
draft -f 文件全路徑.m
就可以得到文件中的函數列表以及函數的起始位置。
根據類覆蓋的行號,類中函數的起始位置,就可以得到測試用例覆蓋的函數列表。
二,Swift項目覆蓋率解析
Swift項目產生的覆蓋率文件是profraw文件,需要通過如下步驟進行處理。
1,轉為profdata文件
使用命令將profraw文件轉化成profdata文件。
xcrun llvm-profdata merge -sparse ./covdata.profraw -o ./covdata.profdata
2,將profdata文件轉化成info報告文件
將覆蓋率數據文件轉化成profdata文件后,要下載覆蓋率測試對應的安裝包,解壓出其中的二進看文件,然后通過下面的命令生成info報告文件。
xcrun llvm-cov export 二進制文件 --instr-profile=./covdata.profdata -use-color --format=lcov > ./report.info
3,解析用例覆蓋信息
當拿到info文件后,就可以按照上面介紹的步驟,解析出用例覆蓋的文件以及文件中對應覆蓋的類信息。
{"類文件1":["fun1","fun2"...],"類文件2":["fun1","fun2"...],"類文件3":["fun1","fun2"...]}
最后將用例與覆蓋的類函數信息寫入數據庫,就建立起用例與代碼的關聯關系。