Xcode中的单元测试,是否运行应用程序?

时间:2013-03-30 03:38:15

标签: iphone ios xcode unit-testing

我遇到了一个我以前没遇到过的奇怪问题。

当您执行cmd + U运行单元测试(例如OCUnit)时,它是否实际调用main.m,新建了appDelegate并运行应用程序,就像您按下了cmd + R一样?

我只是问,因为我在这个DataLayer后面使用了CoreData。我在我的测试中成功地模拟了DataLayer,但是一旦我实现了一个实际调用CoreData的getAll方法,app / xcode抛出了一个关于托管对象模型的例外不能为零。我理解这一点,但我并没有意义地实际创建DataLayer类,并且我在我的mainviewcontroller loadView方法中设置了一个断点,它调用了DataLayer getAll方法。它不应该与测试有关,因为它是一个模拟对象,但它显然是在调用真实实例。

回到我的问题,当按下cmd + U时它是否还运行应用程序然后运行测试?

9 个答案:

答案 0 :(得分:62)

应用程序实际上已运行,但您可以使用一种技巧来阻止它运行。

int main(int argc, char* argv[]) {
    int returnValue;

    @autoreleasepool {
        BOOL inTests = (NSClassFromString(@"SenTestCase") != nil
                     || NSClassFromString(@"XCTest") != nil);    

        if (inTests) {
            //use a special empty delegate when we are inside the tests
            returnValue = UIApplicationMain(argc, argv, nil, @"TestsAppDelegate");
        }
        else {
            //use the normal delegate 
            returnValue = UIApplicationMain(argc, argv, nil, @"AppDelegate");
        }
    }

    return returnValue;
}

答案 1 :(得分:20)

这是Sulthan使用XCTest的答案的变体,这是XCode 5生成的测试类的默认值。


int main(int argc, char * argv[])
{
    @autoreleasepool {
        BOOL runningTests = NSClassFromString(@"XCTestCase") != nil;
        if(!runningTests)
        {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
        else
        {
            return UIApplicationMain(argc, argv, nil, @"TestAppDelegate");
        }
    }
}

这将进入main.m,它应位于标准项目布局中的 Supporting Files 下。

然后在您的测试目录中添加:

<强> TestAppDelegate.h


#import <Foundation/Foundation.h>

@interface TestAppDelegate : NSObject<UIApplicationDelegate>
@end

<强> TestAppDelegate.m


#import "TestAppDelegate.h"

@implementation TestAppDelegate
@end

答案 2 :(得分:5)

如果您正在使用Swift(您可能没有main.c),则必须执行以下步骤:

1:删除@UIApplicationMain

中的AppDelegate.swift

2:创建一个空的TestingAppDelegate.swift

import UIKit
class TestingAppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
}

3:创建一个名为main.swift的文件:

import Foundation
import UIKit

let isRunningTests = NSClassFromString("XCTestCase") != nil

if isRunningTests {
   UIApplicationMain(C_ARGC, C_ARGV, nil, NSStringFromClass(TestingAppDelegate))
} else {
   UIApplicationMain(C_ARGC, C_ARGV, nil, NSStringFromClass(AppDelegate))
}

答案 3 :(得分:2)

我找到了另一个问题的解决方案:

AppBarButton

从这里开始:http://qualitycoding.org/app-delegate-for-tests/#comment-63984

答案 4 :(得分:1)

是的,您的测试目标将具有与应用目标的目标依赖关系,因此当您按Cmd + U或Cmd + Shift + U时,将构建应用目标。

答案 5 :(得分:1)

使用xCode 7和xCtool

xctool 能够在不运行应用程序的情况下执行单元测试。

要实现这一目标,

1。更新目标设置以在没有主机应用程序的情况下运行。

选择您的项目 - &gt;然后测试目标 - &gt;将主机应用程序设置为none。

enter image description here

<强> 2。如果没有,请安装xctool。

brew install xctool

第3。使用带xctool的终端运行测试。

xctool -workspace yourWorkspace.xcworkspace -scheme yourScheme run-tests -sdk iphonesimulator

答案 6 :(得分:1)

高于answers,建议在运行时动态更改应用程序委托。

我通过查询NSProcessInfo进行的小修改是detect a unit test run。优点是您不需要检测可以检测单元测试是否正在运行的类。

    int main(int argc, char * argv[])
    {
        // Put your App delegate class here.
        const Class appDelegateClass = [ATAppDelegate class];

        NSDictionary *const environmentDictionary =
        [[NSProcessInfo processInfo] environment];

        const BOOL runningUnitTests =
        environmentDictionary[@"XCInjectBundleInto"] != nil;

        NSString *delegateName = 
        runningUnitTests ? nil : NSStringFromClass(appDelegateClass);

        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, delegateName);
        }
    }

@"XCInjectBundleInto"中的environmentDictionary属性是单元测试包的路径,由Xcode设置。

答案 7 :(得分:0)

我使用Tomasz Bak的方法加上一些dwb答案的代码并提出以下内容:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    BOOL runningTests = NSClassFromString(@"XCTestCase") != nil;
    if (runningTests) {
        self.window.rootViewController = [UIViewController new];
        return true;
    }

    // Your normal code below this
    ....
}

答案 8 :(得分:0)

您可以通过在测试目标中将主机应用程序设置为无来实现。

enter image description here