【问题标题】:C Preprocessor to Determine if in Unit Test确定是否在单元测试中的 C 预处理器
【发布时间】:2014-08-15 21:51:44
【问题描述】:

我正在尝试使用 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);
}

但是,使用这种方法,我仍然只能收到“未测试”日志消息。任何帮助将不胜感激。

@结束

【问题讨论】:

    标签: objective-c c c-preprocessor


    【解决方案1】:

    定义是预处理器宏,这意味着它们只存在于正在编译的文件中。这意味着要使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"];
    

    一般来说,最好是您的项目不知道自己正在测试。否则,您将面临不测试实际行为的风险,并使用测试代码污染您的主项目。

    【讨论】:

    • 谢谢布赖恩。在这种情况下,在测试时必须处理一些主应用程序不必担心的线程问题。你的方法会很好用。
    【解决方案2】:

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

    给出的代码有两个问题会导致不良行为。首先,正如 Brian 指出的那样,因为您既没有 #include 也没有 #import 带有定义的头文件,所以在编译 .m 文件时常量是不可见的。这是因为预处理器在与 Objective-C 语言本身完全不同的级别上运行。 #directives 形成一个编译时程序,它“向下”执行通过预处理器传递的文件,并在到达文件末尾时结束。因此,一旦到达文件末尾,定义就完全不存在了;使它们在实现文件中可见的唯一方法是使用#include#import 将这两个文件拼接成一个“翻译单元”。

    因为头文件中的定义对 .m 文件没有影响,所以预处理器在没有声明 TESTING 的情况下继续进行。您可能认为这会导致编译器错误,但它不会因为预处理器语言处理条件表达式中使用的未定义名称(“缺失变量”,如果您愿意的话),默默地假设它们应该扩展为 0。它永远不会警告你这种行为(这也是考虑使用#ifdef 而不是#if 的原因)。因此,您在 .m 文件中运行的实际比较将扩展为 #if 0 == 1,现在可预测结果。

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

    #define TESTING 1
    

    没有=(正如您已经知道的,没有; 或其他任何东西)。而问题中的定义将导致TESTING 从字面上扩展为序列= 1,这在许多情况下都没有意义。如果你有#imported 头文件,你会在#if 行收到错误,原因很明显,= 1 不是数字,不能有意义地与 0 进行比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-02
      • 2014-11-23
      • 1970-01-01
      • 1970-01-01
      • 2010-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多