Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 具有多个对象的单元测试核心数据_Iphone_Ios_Unit Testing_Core Data - Fatal编程技术网

Iphone 具有多个对象的单元测试核心数据

Iphone 具有多个对象的单元测试核心数据,iphone,ios,unit-testing,core-data,Iphone,Ios,Unit Testing,Core Data,我想对我的核心数据应用程序进行单元测试(有很多记录的压力测试)。一切都是为单元和应用程序测试而设置的,工作正常 我想创建许多核心数据对象,然后看看我的图形视图控制器是否还能工作。我该怎么做 如果我在我的MyAppApplicationTest.mtest类中创建了一个测试方法,测试将在测试后终止应用程序,我无法与图形视图控制器交互 我是否不得不在我的AppDelegate中创建许多记录,然后删除这些代码?或者有没有一种方法可以使用单元测试框架 谢谢您的帮助。有几个UI测试选项。然而,在本例中,我

我想对我的核心数据应用程序进行单元测试(有很多记录的压力测试)。一切都是为单元和应用程序测试而设置的,工作正常

我想创建许多核心数据对象,然后看看我的图形视图控制器是否还能工作。我该怎么做

如果我在我的
MyAppApplicationTest.m
test类中创建了一个测试方法,测试将在测试后终止应用程序,我无法与图形视图控制器交互

我是否不得不在我的
AppDelegate
中创建许多记录,然后删除这些代码?或者有没有一种方法可以使用单元测试框架


谢谢您的帮助。

有几个UI测试选项。然而,在本例中,我建议构建一个巨大的数据库,并将其保留下来,以便进行各种测试。您可以选择在命令行、环境中或仅在用户默认值中设置值来使用它

下面是检查用户默认值的示例代码,然后是环境设置

static NSString * findOption(NSString *name) {
    NSString *result = nil;
    NSDictionary *options  = [NSUserDefaults standardUserDefaults];
    if ((result = [options objectForKey:name]) != nil) return result;
    options = [[NSProcessInfo processInfo] environment];
    if ((result = [options objectForKey:name]) != nil) return result;
    return nil;
}
注意,如果您只想检查命令行参数,而不是用户默认值的所有域,您可以使用此

NSDictionary *options  = [[NSUserDefaults standardUserDefaults] volatileDomainForName:NSArgumentDomain];
然后,在创建持久存储的代码中,您可以查看是否设置了该选项

if ((value = findOption(@"MundiLargeData")) && value.boolValue) {
    // Create the persistent store with the pre-generated big database
    // If creation failed, can continue with normal database as failsafe
}
另外,请注意,如果使用SenTest进行测试,它将使用命令行参数:

NSString *value = findOption(@"SenTest");
if (value) {
    NSLog(@"Using SenTest: %@", value);
}
你可以把代码留在里面,也可以把它去掉。留在那里很安全

编辑

抱歉,我本想马上补充一下,但却被叫走了

很抱歉。我从来没有暗示过你要发布你的测试代码。你当然不想那样做。我以为您只是在寻找一种在运行应用程序时加载大型数据库的方法,这样您就可以在设备上进行手动UI测试,而无需编译不同的版本

如果你想做那样的事情,那么你有很多选择。您可以将测试作为要测试的类的一个类别来编写,只需将该文件从发布版本中排除即可。如果您给您的测试一个一致的命名方案,比如前缀为“test”或“runtimeTest”,那么您可以有这样一个方法

- (void)runAllMethodsThatBeginWith:(NSString*)prefix {
    Class aClass = [self class];
    Method *methods;
    unsigned methodCount;
    if ((methods = class_copyMethodList(aClass, &methodCount)))
    {
        // For this example, we only want methods that take no arguments and return void
        char const *desiredEncoding = method_getTypeEncoding(class_getClassMethod([NSObject class], @selector(load)));

        for (unsigned i = 0; i < methodCount; ++i) {
            SEL selector = method_getName(methods[i]);
            NSString *name = NSStringFromSelector(selector);
            char const * typeEncoding = method_getTypeEncoding(methods[i]);
            NSLog(@"%@: %s %s", name, typeEncoding, desiredEncoding);
            NSRange range = [name rangeOfString:prefix];
            if (range.location == 0 && range.length == prefix.length && strcmp(desiredEncoding, typeEncoding) == 0) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                [self performSelector:selector];
#pragma clang diagnostic pop
            }
        }

        // Don't forget to free the allocated methods array
        free(methods);
    }
}
它将运行所有看起来像

- (void)runtimeTestFoo {
}
如果没有,那么它将默默地什么也不做

您可以从发布版本中排除使用这些实现的整个文件,也可以仅使用宏ifdef排除它们

现在,您的测试都没有编译到发行版中,但它们是用于其他内容的,您可以随时调用您的测试。如果您知道一个特定的测试,那么您当然可以使用respondsToSelector:并有条件地运行该特定的测试方法

编辑

嗯,我以为你在寻找某种方法来动态地决定该做什么。如果这就是您想要的,那么只需提供创建数据库的AppDelegate的子类

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Create your mondo database
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
现在,你有几个选择。在main.o中,您告诉它要使用哪个应用程序委托类。您可以使用一个选项(#ifdef DEBUG)、一个环境变量或其他方法来告诉它要使用哪个应用程序委托类

#import "AppDelegate.h"
#define APP_DELEGATE AppDelegate

#ifdef USE_MY_SPECIAL_RUNTIME_TEST_DELEGATE
#import "RuntimeTestDelegate.h"
#undef APP_DELEGATE
#define APP_DELEGATE RuntimeTestDelegate
#endif

int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([APP_DELEGATE class]));
    }
}
或者,它可以只调用NSClassFromString(@“MyTestingAppDelegate”),查看是否链接到以调用它

或者,如果您想要完全分离,只需创建另一个目标。将app delegate子类放在那里,并在main.m中为该目标使用它。链接到所有其他文件

现在,您有了一个完全独立的可执行文件,它与“产品”相同,只是它有一个特殊的应用程序委托,在启动应用程序之前构建数据库

测试很难。你必须确切地知道你想要什么和不想要什么。没有涵盖所有情况的正确答案

还有很多其他选项,比如在资源包中提供配置文件,包括应用程序plist中的额外内容,向应用程序提供“guru”模式,在执行过程中可以向应用程序发送特殊命令(比如让它打开一个套接字,读取特殊命令并发送回响应——这样你就可以为任何你想要的场景编写脚本,在你的mac上运行它们并远程控制应用程序——也有相应的工具)


希望其中一种方法能满足您的需求。

从我的java开发人员的角度来看,我经常编写单元测试用例来查看后端的反应。我最近发布的一个iOS应用程序也遇到了同样的问题,我为后端编写了测试用例,同时也为前端编写了测试用例(这是所有的UIViewController和UITableView…等等)我没有找到任何其他解决方案,除了将代码放入AppDelegate并稍后删除,正如您所说。使用此解决方案,我的生产目标中仍然有所有的测试代码。无法解决问题。“所有测试代码”是什么--您只加载备用数据库。您没有实际的测试。如果您只希望有一种方法可以选择性地包含某些内容…太多了…我将编辑帖子…我将以编程方式创建数据库记录。这将是“所有测试代码”。另一种加载数据库的方式是测试代码,这是另一种潜在的错误源。这些都是很好的方案,但它们一点也不比我原来的设置简单,如果我需要的话,它们会通过git重新出现……看起来,单元测试框架毕竟不允许进行UI测试。SenTest框架并不声称是一个UI测试框架。苹果确实提供了一个,你可以用可访问性ID识别对象,并用javascript编写UI测试脚本。它的GUI界面允许你记录UI交互以便回放。
#import "AppDelegate.h"
#define APP_DELEGATE AppDelegate

#ifdef USE_MY_SPECIAL_RUNTIME_TEST_DELEGATE
#import "RuntimeTestDelegate.h"
#undef APP_DELEGATE
#define APP_DELEGATE RuntimeTestDelegate
#endif

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