草庐IT

iphone - 对具有许多对象的核心数据进行单元测试

coder 2024-01-12 原文

我想对我的Core Data应用进行单元测试(带有许多记录的压力测试)。一切都已设置好以进行单元和应用程序测试,并且工作正常。

我想创建许多核心数据对象,然后查看我的图形视图控制器是否仍然有效。我该怎么做?

如果我在MyAppApplicationTest.m测试类中创建一种测试方法,则该测试将在测试后终止应用,并且无法与图形视图控制器进行交互。

我是否不得不在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);
}

您可以保留代码,也可以#ifdef代码。放在那里就很安全。

编辑

抱歉-我要立即添加,但是被召唤了...

对于那个很抱歉。我绝不是要暗示您提供了测试代码。您当然不想这样做。我以为您只是在寻找一种在运行应用程序时加载大型数据库的方法,因此您可以在设备上进行手动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并且不带任何参数的方法。您可以执行其他参数处理,但是随后您将不得不处理与ARC相关的问题(因为编译器不确定如何处理-至少会给您警告)。无论如何,这只是让您入门...您可以将类型编码添加为参数,并使它更通用...

现在,在您的运行时代码中,您只需调用...
[self runAllMethodsThatBeginWith:@"runtimeTest"];

它将运行所有看起来像...的方法
- (void)runtimeTestFoo {
}

如果没有,那么它只会默默地无所作为。

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

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

编辑

嗯我以为您正在寻找某种方法来动态地决定要做什么。如果仅此而已,那么只需提供创建数据库的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”)来查看是否链接到它来调用它。

或者,如果要完全分离,只需创建另一个目标。在其中有应用程序委托子类,并在main.m中将其用于该目标。链接所有其他文件。

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

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

还有许多其他选项,例如在资源束中提供配置文件,包括应用程序plist中的其他内容,为应用程序提供“专家”模式,您可以在执行过程中向其发送特殊命令(例如拥有它)打开套接字并读取特殊命令并发送回响应-这样,您就可以为所需的脚本编写脚本,在Mac上运行它们并远程控制应用程序-也有用于此目的的工具)。

希望这些方法之一可以满足您的需求。

关于iphone - 对具有许多对象的核心数据进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11666806/

有关iphone - 对具有许多对象的核心数据进行单元测试的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  3. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  4. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  7. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  8. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  9. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  10. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

随机推荐