C预处理器确定是否在单元测试中

时间:2014-08-15 21:51:45

标签: objective-c c c-preprocessor

我正在尝试使用c宏来确定我是否在进行单元测试,但我对C预处理器还不熟悉。基本上,我试图使用下面的内容。

@implementation thisThing

+(void)thisMethod{
#if TESTING == 1
NSLog(@"TESTING");
#else
NSLog(@"NOT TESTING");
#endif
}

@end

然后在测试文件的标题中

#define TESTING = 1
@interface tester : XCTestCase

@end

@implementation tester

-(void)testTheThing{
XCTAssertEqual(1,1);
}

然而,使用这种方法我仍然只能得到“NOT TESTING”日志消息。任何帮助将不胜感激。

@end

2 个答案:

答案 0 :(得分:2)

定义是预处理器宏,这意味着它们只存在于编译时正在编译的文件中。这意味着,如果TESTING == 1为真,则必须将tester.m导入thisThing.m。您可以将-dTESTING=1定义为Xcode中的编译器指令,但这会使其始终处于该构建配置,即使在未进行测试时也是如此。

更符合您的尝试是在主项目中创建变量,然后在测试项目中,将其引用为extern变量并将其设置为YES:

主要实施:

BOOL TESTING = NO;

@implementation thisThing

+(void)thisMethod{
    if (TESTING) {
        NSLog(@"TESTING");
    } else {
        NSLog(@"NOT TESTING");
    }
}

@end

测试文件:

extern BOOL TESTING;

@implementation MyTest

+ (void)initialize
{
    TESTING = YES;
}

简单地检查您的应用是否使用XCTest捆绑包启动可能更容易:

BOOL isTesting = [[[NSProcessInfo processInfo] arguments] containsObject:@"-XCTest"];

但一般情况下,最好是您的项目不知道它正在测试中。否则,您将面临不测试实际行为的风险,并使用测试代码污染您的主项目。

答案 1 :(得分:1)

作为实际解释问题中预处理器行为的补充答案:

代码有两个问题会导致不必要的行为。首先,正如Brian指出的那样,因为你既没有#include也没有#import带有定义的头文件,当编译.m文件时,常量是不可见的。这是因为预处理器的操作与Objective-C语言完全不同; #directives形成一个编译时程序,执行" down"正在通过预处理器传递的文件,当到达文件末尾时结束。因此,一旦到达文件末尾,定义就会停止存在;使它们在实现文件中可见的唯一方法是将两个文件拼接成一个"翻译单元"使用#include#import

因为标头中的定义对.m文件没有影响,所以预处理器正在进行,而根本没有声明TESTING。您可能希望这会导致编译器错误,但它不会因为预处理器语言处理条件表达式中使用的未定义名称("缺少变量",如果您愿意),通过静默假设它们应该扩展为0。它永远不会警告您这种行为(这也是考虑使用#ifdef而不是#if的原因)。因此,您在.m文件中运行的实际比较会扩展为#if 0 == 1,并具有现在可预测的结果。

第二个问题是您的定义语法错误。 #define不使用= - 在常量名称之后出现的所有内容都是定义的一部分(这是必要的,因为宏也经常用于插入符号)。要将TESTING定义为1,您需要编写:

#define TESTING 1

=(正如您所知,没有;或其他任何内容)。虽然问题中的定义会导致TESTING字面上扩展到序列= 1,但在许多情况下都不会有意义。如果您有#import个头文件,那么您会在#if行收到错误,原因很明显= 1不是数字,并且无法与0进行有意义的比较