我想在Xcode 4中使用OCUnit运行测试,而不启动模拟器。请不要试图说服我做单元测试的方式有误或类似的话语。我喜欢以传统方式进行TDD:在测试中编写类的API,然后使该类通过测试。我会编写单独的端到端测试,在模拟器中运行。
如果没有办法实现这一点,请告诉我如何让测试框架不实例化整个应用程序?我的应用程序是事件驱动的,启动时会发送大量事件,影响我的测试。
如果没有办法实现这一点,请告诉我如何让测试框架不实例化整个应用程序?我的应用程序是事件驱动的,启动时会发送大量事件,影响我的测试。
#if DEBUG
if (getenv("runningTests"))
return YES;
#endif
对于-applicationDidBecomeActive:
方法也做同样的操作,但只需使用return
。
更新:我改变了我的方法。请参见如何轻松切换您的应用委托以进行测试。
注意,未在Xcode 5上进行测试。
我使用了@jon-reid的答案,但是发现Xcode将环境变量添加到XcodeProjects的xcuserstated
部分中,而这些是特定于用户的,通常不会提交到仓库。因此,我用交换方法(swizzle)重写了我的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
MyAppDelegate
重命名为您主目标中 AppDelegate 类的名称。您的测试目标没有应用程序委托,但这就是这个问题的重点,来自主目标的应用程序委托仍然会被执行。 - mxcl基于这个模型,这就是我为了让我的逻辑测试正常工作所做的事情。创建一个新的目标(Cocoa Touch 静态库),并将所有要进行逻辑测试的文件(通常是您的所有模型)移动到这个新目标中。在"Build Phases"设置中,在应用程序目标和逻辑测试目标的"Link Binary With Libraries"中添加这个新库。
我可以想象这些说明可能有点令人困惑。如果你剖析上面提到的示例项目,你会更好地理解。
我使用GHUnit创建了适用于OSX/iOS的测试套件。虽然存在一些问题,但我发现它比OCUnit更可靠/兼容/简单。
GHUnit为OS X和iOS提供基本的模板项目,使初始设置变得简单。
注意:通常我只使用自己的工具包进行大部分测试。