我想在不启动模拟器的情况下使用OCUnit在Xcode 4中运行测试。请不要试图说服我,我正在进行单元测试错误或类似的事情。我喜欢用传统方式做TDD:在测试中为类编写API,然后让类通过测试。我将编写在模拟器中运行的端到端的单独测试。
如果没有办法做到这一点,那么请有人告诉我如何让测试工具不实例化整个应用程序?我的应用程序是事件驱动的,当它启动我的测试时,会发送一堆事件。
答案 0 :(得分:28)
请有人告诉我如何让测试工具不实例化整个应用程序?我的应用程序是事件驱动的,当它启动我的测试时,会发送一堆事件。
我使用Xcode 4的内置测试。应用实例化可能看起来很痛苦,但正如我在Xcode Unit Testing: The Good, the Bad, the Ugly上写的那样,它可以在不区分逻辑测试和应用测试的情况下编写测试。具体来说,它允许我为视图控制器编写单元测试。
以下是我为避免完整启动顺序所做的工作:
编辑方案
runningTests
设置为YES
修改您的应用代理
一旦有意义,就将以下内容添加到-application:didFinishLaunchingWithOptions:
:
#if DEBUG
if (getenv("runningTests"))
return YES;
#endif
对-applicationDidBecomeActive:
执行相同操作,但只需return
。
更新:我改变了方法。请参阅How to Easily Switch Your App Delegate for Testing。
答案 1 :(得分:5)
在上一个xcode版本(5.0.2)中,您可以非常简单地完成此操作。选择您的测试目标,“常规”选项卡。在“目标”字段中设置“无”。然后点击“构建阶段”选项卡,从“目标依赖项”中删除主目标。
答案 2 :(得分:3)
在您的情况下,我假设您有一个单独的逻辑测试和应用程序测试目标(如果不是 - 您需要)。在方案配置中,您可以定义为“测试”方案构建的目标。如果您的应用程序测试未运行,则模拟器将无法启动。
我怀疑您可能正在尝试在“应用程序测试”目标中运行“逻辑测试”(例如Xcode默认创建的目标)。详细了解这种差异here(以及如何设置)。
答案 3 :(得分:2)
在之前的回答中指出,逻辑测试对于这种情况来说是正确的。我在使用XCode版本4.3.2(4E2002)进行逻辑测试时非常困难。看Apple's sample unit test project让我明白如何通过明确的分离来做到这一点。在该示例中,逻辑测试来自库目标的测试文件,而不是应用程序目标。该模型被封装到一个库中,然后与主目标和逻辑测试目标链接。应用程序目标仅包含视图和控制器。
基于这个模型,我就是为了让我的逻辑测试正常工作。创建一个新目标(Cocoa Touch Static Library)并将所有要进行逻辑测试的文件(通常是所有模型)移动到这个新目标。在“Build Phases”设置下,在应用程序目标和逻辑测试目标的“Link Binary With Libraries”中添加此新库。
我可以想象这些说明有点令人困惑。如果您剖析上面提到的示例项目,您将会有更好的想法。
答案 4 :(得分:2)
注意,在Xcode 5上未经测试。
我使用@jon-reid’s answer,但发现Xcode将环境变量添加到XcodeProjects的xcuserstated
部分,这些是用户特定的,通常不会提交到存储库。因此,我调动我的AppDelegate
来覆盖其加载:
@implementation MyAppDelegate (Testing)
+ (void)initialize {
SEL new = @selector(application:didFinishLaunchingWithOptions:);
SEL orig = @selector(swizzled_application:didFinishLaunchingWithOptions:);
Class c = [self class];
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if (class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
} else {
method_exchangeImplementations(origMethod, newMethod);
}
}
- (BOOL)swizzled_application:(id)app didFinishLaunchingWithOptions:(id)opts {
return YES;
}
@end
请注意,以下内容更简单且仍然有效,但我不确定它是否可靠:
@implementation MyAppDelegate (Testing)
- (BOOL)application:(id)app didFinishLaunchingWithOptions:(id)opts {
return YES;
}
@end
这是有效的,因为动态加载的组件(如测试包)中的方法类别优先。但是,调侃感觉更安全。
答案 5 :(得分:1)
使用xCode 7和xctool
xctool 能够在没有模拟器的情况下执行单元测试。
要实现这一目标,
1。在没有主机应用程序的情况下更新目标设置。
选择您的项目 - >然后测试目标 - >将主机应用程序设置为none。
<强> 2。安装xctool,如果你没有。
brew install xctool
第3。使用带xctool的终端运行测试。
xctool -workspace yourWorkspace.xcworkspace -scheme yourScheme run-tests -sdk iphonesimulator
答案 6 :(得分:0)
我使用GHUnit创建了兼容osx / ios的测试套件。有一些问题,但我发现它比OCUnit更可靠/兼容/直接。
GHUnit为OS X和iOS提供基本模板项目,使初始设置变得简单。
注意:我通常只使用自己的套件进行大部分测试。