XCode 5单元测试:启动我的应用程序

34
当我在XCode 5中运行测试时,我的OS X应用程序的主窗口会在运行测试时出现几秒钟。为什么?即使我取消注释所有测试,它仍然打开我的主窗口。

这里被点赞的解决方案是静态地更改你构建的内容,以排除应用程序运行部分。这可能是你想要的,但一个非常简单而且非常有效的替代方案是在没有应用程序委托的情况下启动你的单元测试。不幸的是,这个问题的答案只有一个赞。另一个关于这个主题的问题有使用委托方法的更高票数的答案 - Benjohn
我使用动态委托,并在我的答案中添加了一个用于检测测试运行的细化。 - Benjohn
7个回答

39

您正在运行应用程序测试,而不是逻辑测试。这意味着将启动应用程序实例,然后运行单元测试。这允许您执行一些需要应用程序正在运行的集成测试。

这里是设置应用程序测试和逻辑测试的指南。

如果您想将其更改为逻辑测试(以使其运行更快且不需要首先启动您的应用程序):

  1. 转到单元测试目标的构建设置
  2. 搜索Bundle
  3. 删除“Bundle Loader”和“Test Host”

enter image description here


9
当我这样做时,测试目标无法正确链接。测试目标是由XCode创建的(通过测试导航器中的“新建测试目标”选项),除此之外我没有对其进行任何修改。 - Daniel Bruce
这在 Xcode 4 中曾经是这样,楼主能否验证一下这是否有效?(必须是注册的开发者才能看到链接)https://devforums.apple.com/message/867874#867874 - qnoid
4
在Xcode 5中不可能实现这个。请参考上面的openradar链接:http://openradar.appspot.com/15859153。 - cbowns
7
在XCode 6中也不可能。 - H.Rabiee
2
适用于Xcode7,您只需在测试目标的“常规”选项卡中将“主机应用程序”设置为“无”。 - Daniel
显示剩余5条评论

10

没错,你需要从构建设置中删除"Bundle Loader"和 "Test Host"。

但是,你需要将必要的实现文件添加到你的单元测试目标中。这些必要的文件是你想在单元测试中使用的文件。你需要这样做是因为在逻辑测试中,XCode不会编译整个应用程序。所以你的一些文件会丢失。

如果你遗漏了一个文件,这是一个错误信息:

Undefined symbols for architecture i386:
  "_OBJC_CLASS_$_Module", referenced from:
      objc-class-ref in Lobic Network.o
      objc-class-ref in Logic_Unit.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

通过选择实现文件并打开文件检查器,您可以添加缺失的文件。那里将会有一个名为“目标成员资格”的部分,您可以在那里将文件的目标成员资格设置为您的单元测试。


9
使用XCTest时,应用程序文件不需要包含在XCTest目标中。 XCTest包链接到应用程序,使这些文件在运行时可用。
为了使其正常工作,请确保在应用程序目标内设置编译器选项“默认情况下隐藏符号”为NO
这里有一篇带有屏幕截图的博客文章,以便更加清晰地理解:http://zmcartor.github.io/code/2014/02/24/slim-xctest-targets 这种方法的优点是测试目标构建速度更快。

1
我认为苹果公司要求在运行测试之前必须拥有编译应用程序有点可惜...我更希望我的测试与我的应用程序具有相同的依赖关系,但是独立于应用程序目标进行编译(即主机应用程序应为空)。这种做法可行吗? - fatuhoku
链接已经失效,很遗憾。 - Benjohn
你好,链接已修复。 - HackaZach

4
在XCode 7中,移除“宿主应用程序(Host Application)”对我没有起作用。事实上,我使用以下方法来避免应用程序运行。
  1. Setup Test Scheme Arguments enter image description here

  2. in main.m

    static bool isRunningTests()
    {
        NSDictionary* environment = [[NSProcessInfo processInfo] environment];
        NSString* testEnabled = environment[@"TEST_ENABLED"];
        return [testEnabled isEqualToString:@"YES"];
    }
    
  3. modify main()

    int main(int argc, char * argv[]) {
        @autoreleasepool {
            if (isRunningTests()) {
                return UIApplicationMain(argc, argv, nil, nil);
            } else {
                return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
            }
        }
    }
    

3

如果测试的代码可以在桌面和移动设备上运行,那么您可以在不使用模拟器或将其托管到应用程序中的情况下运行它们。

问题在于您不能使用选定方案(桌面或iOS)来运行测试。

以下方法适用于我在Xcode6中:

File > New Target...

从 OS X 类别中选择 Cocoa 测试包。
请确保从目标下拉列表中选择“None”。
点击“完成”。按照上述说明将相关文件添加到新目标中。
现在创建一个方案来运行测试。
点击顶部右侧的方案选择器,选择“New Scheme...”,点击下拉列表并向下导航到新目标。现在,您可以从方案选择器中选择方案,并使用⌘U来运行测试。

2

对我来说,这是一个更好的解决方案。很遗憾你在这里的答案没有得到投票,而那个问题也不是我搜索到的! - Benjohn

1
我刚刚浪费了一个上午的时间。
该项目是在XCode 4中创建并使用SenTesting。
尝试将测试迁移到XCode 5/XCTTest。
遇到相同的问题-应用程序在模拟器中运行,但测试从未启动,在尝试了所有方法后(从应用程序更改为逻辑测试,更改为XCTest,删除SenTesting),放弃并创建了一个干净的XCode 5项目。
添加了所有文件后,测试运行良好。
可能仍存在Storyboard问题,因为这些是在XCode 4中构建的。
这是一个激烈的方法,但它有效,所以把它作为最后的手段。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接