首页游戏资讯iOS代码笼盖率(一)-全量笼盖率主动化理论

iOS代码笼盖率(一)-全量笼盖率主动化理论

misa2 04-16 3次浏览 0条评论

做者:京东零售 邓立兵

简介

那是一个统计基于 Swift Objective-C 工程的代码笼盖率的主动化脚本。之所以做成 Pod ,是便于更好的复用,该 Pod 只包罗了搜集生成代码笼盖率的脚本。整体比力简双方便。

那里只将流程,咱不讲原理。后续别的介绍

那里只将流程,咱不讲原理。后续别的介绍

利用

1、安拆:

通过 CocoaPods 停止安拆,在你的 Podfile 文件添加如下代码:

pod 'HDCoverage' 复造代码

然后 pod install 安拆下载相关脚本文件。

2、联系关系脚本:

在项目标 Xcode 的 Build Phases 添加新的脚本(New Run Script Phase)(App在Build会施行该脚本):

"${PODS_ROOT}/HDCoverage/HDCoverage/hd_coverage_env.sh" 复造代码

iOS代码笼盖率(一)-全量笼盖率主动化理论

3、工程设置装备摆设代码笼盖率参数:

那里原来是在 HDCoverage 有脚本撑持的,但是基于对哪些模块(Pod做为独立模版)停止代码笼盖率,所以定见在 Podfile 自主添加如下代码乖巧治理,详尽阐明如下:

展开全文

# 实现post_install Hooks

# 需要搜集Code Coverage的模块

ntargets = Array['AFNetworking']

require 'xcodeproj'

post_install do |installer|

# 修改Pods中某一个模块的设置装备摆设文件,好摘集代码笼盖率,需要源码!

installer.pods_project.targets.each do |target|

target.build_configurations.each do |config|

if(config.name = 'Release') == 0

config.build_settings['OTHER_CFLAGS'] = '$(inherited)'

config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited)'

config.build_settings['OTHER_LDFLAGS'] = '$(inherited)'

ntargets.each do |ntarget|

if(ntarget = target.name) == 0

config.build_settings['OTHER_CFLAGS'] = '$(inherited) -fprofile-instr-generate -fcoverage-mapping'

config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -profile-generate -profile-coverage-mapping'

config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -fprofile-instr-generate'

break

end

end

else

config.build_settings['OTHER_CFLAGS'] = '$(inherited)'

config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited)'

config.build_settings['OTHER_LDFLAGS'] = '$(inherited)'

end

end

end

# 修改主工程

project_path = './HDCoverage.xcodeproj'

project = Xcodeproj::Project.open(project_path)

puts project

project.targets.each do |target|

if(target.name = 'HDCoverageDemo') == 0

target.build_configurations.each do |config|

if ((config.name = 'Release') == 0 || (config.name = 'Debug') == 0)

# 设置预编译变量CODECOVERAGE

config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) CODECOVERAGE=1'

# OC代码笼盖率插桩设置装备摆设

config.build_settings['OTHER_CFLAGS'] = '$(inherited) -fprofile-instr-generate -fcoverage-mapping'

# Swift代码笼盖率插桩设置装备摆设

config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -profile-generate -profile-coverage-mapping'

# 摘集代码笼盖率设置装备摆设

config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -fprofile-instr-generate'

# Release需要设置,否则无法解析代码笼盖率

config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Onone'

else

config.build_settings['OTHER_CFLAGS'] = '$(inherited)'

config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited)'

config.build_settings['OTHER_LDFLAGS'] = '$(inherited)'

config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = ''

end

end

end

end

project.save()

end

4、代码施行数据搜集:

利用 GCC 无法称心 同时兼容 Swift和 Objective-C ,所以那里是基于 LLVM 停止,官网文档 。也能够参考笔者翻译的 Source-based Code Coverage ,完全详尽的教程能够看 Source-based Code Coverage for Swift Step by Step。

4.1、起首在工程中申明 LLVM 几个关键的函数:

#ifndef PROFILE_INSTRPROFILING_H_

#define PROFILE_INSTRPROFILING_H_

//

int __llvm_profile_runtime = 0;

void __llvm_profile_initialize_file(void);

const char *__llvm_profile_get_filename(void);

void __llvm_profile_set_filename(const char *);

int __llvm_profile_write_file(void);

int __llvm_profile_register_write_file_atexit(void);

const char *__llvm_profile_get_path_prefix(void);

#endif /* PROFILE_INSTRPROFILING_H_ */

4.2、再次封拆代码笼盖率相关API,便于上层更好利用(定见):

class HDCoverageTools: NSObject { static var shared = HDCoverageTools()

// 重视:动态库是需要零丁注册,而且需要在动态库中施行\_\_llvm\_profile\_write\_file()

func registerCoverage(moduleName: String) {

let name = "\\(moduleName).profraw"

print("registerCoverage, moduleName: \\(moduleName)")

let fileManager = FileManager.default

do {

let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)

let filePath: NSString = documentDirectory.appendingPathComponent(name).path as NSString

print("HDCoverageGather filePath: \\(filePath)")

\_\_llvm\_profile\_set\_filename(filePath.utf8String)

} catch {

print(error)

saveAndUpload()

// 适宜的时机代码笼盖率上报

func saveAndUpload() {

\_\_llvm\_profile\_write\_file()

4.3、启动时刻,注册代码笼盖率API:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) - Bool {

HDCoverageTools.shared.registerCoverage(moduleName: "HDCoverageDemo")

return true

4.4、在适宜的时刻(根据各人的营业场景)将笼盖率数据写进造定的途径:

func sceneDidEnterBackground(_ scene: UIScene) {

// 笔者那里测试,是在App进进后台后写进

DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) { [self] in

HDCoverageTools.shared.saveAndUpload()

5、测试以便生成笼盖率数据:

以本工程的demo为例阐明

5.1、在运行胜利后,Finder 会主动弹出如下目次:

iOS代码笼盖率(一)-全量笼盖率主动化理论

那里是在项目主工程生成 CoverageResult 目次,而且将生成代码笼盖率可视化的脚本 hd_parse_profraw.sh 拷贝到那里,将 项目 HDCoverageDemo.app 拷贝过来,次要是获取其 Mach-O :

$ tree -L 2

├── MachOFiles

│ └── HDCoverageDemo.app

├── Profraw

└── hd_parse_profraw.sh

5.2、施行测试用例,那里我别离点击了:"主工程(OC)-Case1/Case2"、"主工程(Swift)-Case2/Case3"、"Framework(OC)-Case1/Case2"、"FrameworkSwift)-Case2/Case3" 后,App退到后台

iOS代码笼盖率(一)-全量笼盖率主动化理论

5.3、查看掌握台,能够看到 profraw 文件:

registerCoverage, moduleName: HDCoverageDemo

HDCoverageGather filePath: /Users/denglibing/Library/Developer/CoreSimulator/Devices/5D01D4AA-40AE-4FC6-845C-391A94828EE3/data/Containers/Data/Application/283906A5-1681-44A5-8522-126D29D2F148/Documents/HDCoverageDemo.profraw

将 HDCoverageDemo.profraw 拷贝到 CoverageResult/Profraw 目次中;

5.4、施行 hd_parse_profraw.sh 脚本:

$ tree -L 2

├── MachOFiles

│ └── HDCoverageDemo.app

├── Profraw

│ └── HDCoverageDemo.profraw

└── hd_parse_profraw.sh

$ sh hd_parse_profraw.sh

CoverageResult: /Users/denglibing/HDProject/iOSProject/SProject/hdcoverage/Example/CoverageResult/CoverageResult

machOFiles: /Users/denglibing/HDProject/iOSProject/SProject/hdcoverage/Example/CoverageResult/MachOFiles

/Users/denglibing/HDProject/iOSProject/SProject/hdcoverage/Example/CoverageResult/CoverageResult 不存在,已经创建

disposeProfrawFiles profraws: /Users/denglibing/HDProject/iOSProject/SProject/hdcoverage/Example/CoverageResult/Profraw

disposeProfrawFiles profraw file: HDCoverageDemo.profraw

findMachOFileName: HDCoverageDemo

findMachOFilePath: /Users/denglibing/HDProject/iOSProject/SProject/hdcoverage/Example/CoverageResult/MachOFiles/HDCoverageDemo.app/HDCoverageDemo

disposeProfrawToHtml, machoFileName: HDCoverageDemo machOFilePath: /Users/denglibing/HDProject/iOSProject/SProject/hdcoverage/Example/CoverageResult/MachOFiles/HDCoverageDemo.app/HDCoverageDemo

施行胜利后将主动将可视化的代码笼盖率目次翻开:

$ tree -L 3

├── CoverageResult

│ └── HDCoverageDemo

│ ├── coverage

│ ├── index.html

│ └── style.css

├── MachOFiles

│ └── HDCoverageDemo.app

│ ├── Base.lproj

│ ├── Frameworks

│ ├── HDCoverageDemo

│ ├── Info.plist

│ ├── PkgInfo

│ └── _CodeSignature

├── Profraw

│ ├── HDCoverageDemo.profdata

│ └── HDCoverageDemo.profraw

└── hd_parse_profraw.sh

9 directories, 8 files

复造代码

5.5、查看:翻开 CoverageResult/HDCoverageDemo/index.html 即可得到本次测试的代码笼盖率情状:

iOS代码笼盖率(一)-全量笼盖率主动化理论

点击某一个 Filename区域 能够查看详情,例如点击 HDOCFramework.m:

iOS代码笼盖率(一)-全量笼盖率主动化理论

能够看出,tag == 3 的代码行数并没有施行到,那正和上面测试的 "Framework(OC)-Case1/Case2" 契合。

小结

全量代码笼盖率能够搀扶帮助开发者聚焦变更代码的逻辑缺陷,从而更好地制止线上问题。那里更多的是讲述基于 Swift Objective-C 工程的 全量代码笼盖率 的计划,没有原理,只要简单的流程。半途测验考试过多个计划,最末依靠 Cocoapods 才能将主动化脚本赋能出往。

但是现实开发过程,不成能每次都往存眷 全量代码笼盖率,下一篇陆续介绍:iOS代码笼盖率(二)-增量笼盖率主动化理论

Demo及脚本源码地址,欢送批示+Star

参考

Source-based Code Coverage for Swift Step by Step : 十分详尽的Swift代码笼盖率教程,收获颇丰。

iOS 基于非Case的Code Coverage系统搭建 : 基于对OC项目标代码笼盖率介绍,供给了脚本化构想,收益匪浅。

llvm-profdata - Profile data tool: 用于处置生成profdata号令

Source-based Code Coverage :llvm官网基于源码对Swift和OC停止代码笼盖率

Source-based Code Coverage 中文版 :llvm官网基于源码对Swift和OC停止代码笼盖率-笔者翻译(轻喷)

地球帝国2中文版下载
Ai软件下载 AI全版本下载 2022 奖金26万元〡第二届“艾青诗歌奖” 参评做品征集启事
相关内容
发表评论

游客 回复需填写必要信息