iOS项目中Firebase影响Jenkins代码覆盖率的原因及解决方法咨询
我之前在做iOS项目的Jenkins覆盖率统计时也碰到过类似的问题,给你详细拆解下:
[FIRApp configure];后覆盖率提升的原因 核心原因和Firebase初始化逻辑以及代码覆盖率统计范围有关:
[FIRApp configure];是Firebase SDK的核心启动方法,执行它会触发大量SDK内部的初始化逻辑——比如初始化Firebase Core、Analytics、Crashlytics等子组件的底层代码。- 默认情况下,如果你没配置覆盖率统计工具排除第三方SDK代码,这些Firebase内部代码会被纳入你的项目覆盖率计算中。但你的单元测试肯定不会去覆盖Firebase的内部实现,这部分未覆盖的代码就会拉低整体覆盖率。
- 当你注释掉这行代码后,这部分第三方未覆盖代码不再被执行和统计,你的项目自有代码在覆盖率统计中的占比就提升了,所以看起来覆盖率涨了5%。
另外还有一种次要可能:如果你的项目中有部分代码分支依赖Firebase的初始化状态(比如某些功能只有在Firebase配置完成后才会触发),但你的测试用例没有覆盖这些分支,注释掉configure后,这些分支不会被执行,对应的未覆盖代码也不会被统计,间接推高了覆盖率。
这里给你几个iOS开发中常用的、靠谱的实现方式:
1. 编译宏区分测试环境
这是最简单直接的方式:
在AppDelegate的application:didFinishLaunchingWithOptions:方法里添加编译条件判断:
#ifndef TESTING [FIRApp configure]; #endif
然后打开你的测试Target的Build Settings,找到Preprocessor Macros选项,添加TESTING=1。这样当运行测试时,这个宏会生效,configure代码就会被编译器跳过,不会执行。
2. 依赖注入+协议抽象(更符合测试设计)
如果你的项目规模较大,推荐用这种方式,扩展性更强:
首先定义一个抽象协议封装Firebase初始化逻辑:
@protocol FirebaseConfigurable <NSObject> - (void)configureFirebase; @end
然后分别写生产环境和测试环境的实现:
// 生产环境实现:真正初始化Firebase @interface FirebaseConfigurator : NSObject <FirebaseConfigurable> @end @implementation FirebaseConfigurator - (void)configureFirebase { [FIRApp configure]; } @end // 测试环境实现:空实现,啥也不做 @interface MockFirebaseConfigurator : NSObject <FirebaseConfigurable> @end @implementation MockFirebaseConfigurator - (void)configureFirebase { // 测试时不需要初始化Firebase,留空即可 } @end
最后在AppDelegate里根据环境注入对应的实例:
// AppDelegate.h @property (nonatomic, strong) id<FirebaseConfigurable> firebaseConfigurator; // AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 生产环境注入真实实现,测试环境注入Mock self.firebaseConfigurator = [[FirebaseConfigurator alloc] init]; [self.firebaseConfigurator configureFirebase]; return YES; }
测试时,在测试用例的setUp方法里替换成Mock实例即可。
3. 运行时环境变量控制
这种方式不需要修改编译配置,通过运行时环境变量判断:
在AppDelegate里添加逻辑读取环境变量:
NSString *isRunningTests = [[NSProcessInfo processInfo] environment][@"RUNNING_TESTS"]; if (![isRunningTests isEqualToString:@"YES"]) { [FIRApp configure]; }
然后打开你的测试Scheme,在Test阶段的Environment Variables里添加RUNNING_TESTS=YES。这样运行测试时,这个环境变量会生效,configure代码就不会执行了。
内容的提问来源于stack exchange,提问作者frigocat

