标签: ocunit

如何运行和调试iPhone应用程序的单元测试

注意:现在单元测试更容易设置.本教程与Xcode版本5及更高版本无关.

我花了很长时间,但我终于设法使它适用于我的项目.为了创建"逻辑"测试,我遵循Apple关于创建逻辑测试的指导原则.一旦您了解在构建期间运行逻辑测试,这就可以正常工作.

为了能够调试这些测试,需要创建一个可以调用这些测试的自定义可执行文件.本文通过对所著的Grokking可可博客肖恩·米塞利提供的所有信息来做到这一点.然而,它并没有立即取得成功,需要进行一些调整.

我将介绍Sean教程中提供的主要步骤,提供一些"for dummies"大纲,这花了我一些时间来弄清楚:

  1. 设置包含单元测试的目标但不运行它们
  2. 设置otest可执行文件以运行测试
  3. 设置otest环境变量,以便otest可以找到您的单元测试

使用XCode 3.2.5执行以下操作

XCode 4的注意事项

在XCode 4中,可以直接调试单元测试.只需编写测试,将其作为测试之一添加到目标并在其中设置断点.就这样.会有更多.

第1步 - 设置目标

  1. 复制位于项目目标下的单元测试目标.这也将创建单元测试产品(.octest文件)的副本.在下图中,"LogicTest"是原始目标.
  2. 将单元测试目标和单元测试产品(.octest文件)重命名为相同的名称.在下图中,"LogicTestsDebug"是重复的目标.
  3. 删除新目标的RunScript阶段

两者的名字可以是任何东西,但我会避免空格.

在此输入图像描述

第2步 - 设置otest

这里最重要的一点是获得正确的otest,即适用于您当前的iOS而不是默认的Mac版本.这在Sean的教程中有详细描述.以下是一些帮助我做好准备的细节:

  1. Go Project-> New Custom Executable.这将弹出一个窗口,提示您输入可执行文件名和可执行文件路径.
  2. 输入您想要的任何名称.
  3. 复制粘贴路径到您的iOS otest可执行文件.在我的例子中,这是/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.2.sdk/Developer/usr/bin/otest
  4. 按enter键.这将带您进入可执行文件的配置页面.
  5. 此时唯一要改变的是选择"路径类型:相对于当前SDK".不要输入路径,这是在步骤3完成的. 在此输入图像描述

第3步 - 设置otest参数和环境变量

讽刺的论点很容易设置......但事实证明这是我最大的问题.我最初将我的逻辑测试目标命名为"LogicTests Debug".使用此名称和"LogicTests Debug.octest"(带引号)作为otest的参数我保持otest终止与退出代码1并且永远不会停止到我的代码...

解决方案:目标名称中没有空格!

otest的论据是:

  1. -SenTest Self(或全部或测试名称 - 在终端中键入man otest以获取列表)
  2. {LogicTestsDebug} .octest - 需要用逻辑测试包名称替换{LogicTestsDebug}.

以下是复制/粘贴的环境变量列表:

  • DYLD_ROOT_PATH:$ SDKROOT
  • DYLD_FRAMEWORK_PATH:"$ {BUILD_PRODUCTS_DIR}:$ {SDK_ROOT}:$ {DYLD_FRAMEWORK_PATH}"
  • IPHONE_SIMULATOR_ROOT:$ SDKROOT
  • CFFIXED_USER_HOME:"$ {HOME} /图书馆/应用程序支持/ iPhone模拟器/用户"
  • DYLD_LIBRARY_PATH:$ {BUILD_PRODUCTS_DIR}:$ {DYLD_LIBRARY_PATH}
  • DYLD_NEW_LOCAL_SHARED_REGIONS:是的
  • DYLD_NO_FIX_PREBINDING:是的

请注意,我也尝试过DYLD_FORCE_FLAT_NAMESPACE,但这只是造成了骚乱.

在此输入图像描述

第4步 - …

iphone xcode unit-testing ocunit ios

16
推荐指数
1
解决办法
6597
查看次数

单元测试无法找到Core Data模型文件

我已经创建了一个带有Core Data模型的项目.应用程序查找模型文件(.momd)并运行正常.

不幸的是,单元测试不断返回null:

NSURL *dataModelURL = [[NSBundle mainBundle] URLForResource:@"myDataModel" withExtension:@"momd"];
Run Code Online (Sandbox Code Playgroud)

我可以在主目标和单元测试目标的Compile Sources目录中看到myDataModel.xdatamodeld文件夹和文件 - 但这似乎不够.我在单元测试目标中还缺少什么?

谢谢,-Luther

iphone xcode cocoa unit-testing ocunit

16
推荐指数
2
解决办法
5253
查看次数

如何对Core Data迁移进行单元测试?

我正在使用自定义实体迁移策略为我的迁移构建映射模型,我真的想为此迁移构建一些单元测试.当我运行应用程序时,迁移似乎正常工作,但当我通过单元测试运行迁移时,根本不会调用我的NSEntityMigrationPolicy子类方法.

我正在使用Xcode的内置OCUnit框架.

我的测试代码:

- (void)test1to2Migration_appIdentifierMoved {
  [self createVersion1Store];

  // TODO Perform migration
  NSManagedObjectModel *version1Model = [self version1Model];
  NSManagedObjectModel *version2Model = [self version2Model];

  NSError *error = nil;
  NSMappingModel *mappingModel = [NSMappingModel
      inferredMappingModelForSourceModel:version1Model
      destinationModel:version2Model error:&error];
  STAssertNotNil(mappingModel, @"Error finding mapping model: %@", error);

  NSMigrationManager *migrationManager =
      [[[NSMigrationManager alloc]
        initWithSourceModel:version1Model
        destinationModel:version2Model]
       autorelease];

  BOOL migrationSucceeded =
      [migrationManager migrateStoreFromURL:self.version1StoreURL
           type:NSSQLiteStoreType
           options:nil
           withMappingModel:mappingModel
           toDestinationURL:self.version2StoreURL
           destinationType:NSSQLiteStoreType
           destinationOptions:nil
           error:&error];
  STAssertTrue(migrationSucceeded, @"Error migrating store: %@", error);

  // TODO Verify appIdentifier is moved from Project to its Tests

  [self deleteTempStores];
} …
Run Code Online (Sandbox Code Playgroud)

unit-testing core-data ocunit core-data-migration ios

16
推荐指数
2
解决办法
1740
查看次数

如何从故事板加载原型单元?

有没有办法加载原型单元格,以及故事板中定义的任何IBOutlet连接?

更新

我想对单元格(单元的UICollectionViewCell)进行单元测试,因此希望将它加载到UIViewController上下文之外.

实际上,就像您可以从笔尖加载自定义视图一样,指定其文件的所有者并设置其IBOutlet.

objective-c ocunit uikit sentestingkit

16
推荐指数
2
解决办法
1万
查看次数

为什么gcov没有报告我的单元测试所涵盖的任何行?

我在10.6上使用Xcode 3.2,带有gcov的发布版本和默认的GCC编译器(版本4.2.1).我已经创建了一个依赖的Cocoa单元测试包,它被注入到我的应用程序中,并遵循Apple的文档来设置基于gcov检测的构建配置 - 基于Debug配置,该配置没有启用任何编译器优化.

当我使用这种'Gcov-instrumented'配置构建测试包时,应用程序启动并注入并运行测试.覆盖统计文件也是在以下位置生成的:

build/<AppTarget>.build/Gcov-instrumented/<AppTarget>.build/Objects-normal/x86_64/<object>.gcda

build/<AppTarget>.build/Gcov-instrumented/<AppTarget>.build/Objects-normal/x86_64/<object>.gcno

到现在为止还挺好.我知道测试确实在运行,因为如果我插入失败,那么测试套件会按预期失败.不幸的是,gcov报告测试中没有涉及任何对象线!每行报告为0覆盖.我在这里和Apple邮件列表档案中搜索过,找不到有类似问题的人.我希望我错过了什么 - 但它是什么?

xcode cocoa code-coverage ocunit gcov

15
推荐指数
2
解决办法
6682
查看次数

在设备上运行OCUnit应用程序测试套件时偶尔会出现错误

在运行应用程序测试时(即在设备上),我的OCUnit测试套件出现了一些问题.偶尔,我会收到一个似乎从OCUnit类抛出的棘手错误.我一直在试图查看添加到测试套件中的文件,但无法理解它.

我在设置测试目标时遵循了Apple文档并查看了其他教程,从而产生了以下目标(以及缩进的依赖项):

LogicTests

MyApp LogicTests

ApplicationTests MyApp

MyAppTesting ApplicationTests

最后一个(MyAppTesting)是我在设备上运行以启动测试套件的那个.

如上所述,测试无法启动有时会在控制台中抛出以下输出:

2010-11-17 12:02:48.537 VCCTesting[12018:307] *** Assertion failure in -[SenTestClassEnumerator init], /SourceCache/OCUnit/OCUnit-1685/SourceCode/SenTestingKit/SenTestClassEnumerator.m:137

2010-11-17 12:02:48.556 VCCTesting[12018:307] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'objc_getClassList returned more classes than it should have.'
*** Call stack at first throw:
(
0   CoreFoundation                      0x30897ed3 __exceptionPreprocess + 114
1   libobjc.A.dylib                     0x3002f811 objc_exception_throw + 24
2   CoreFoundation                      0x30897d15 +[NSException raise:format:arguments:] + 68
3   Foundation                          0x349f932f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 62
4   SenTestingKit                       0x20107c29 -[SenTestClassEnumerator init] + …
Run Code Online (Sandbox Code Playgroud)

iphone testing unit-testing ocunit

15
推荐指数
1
解决办法
1571
查看次数

isKindOfClass和NSStringFromClass不同意UIApplicationDelegate

我正在玩一个简单的OCUnit测试用于iPhone应用程序,并且只是想断言应用程序委托是我期望它的类的实例.我没想到这个测试非常有用,但结果却揭示了我对Objective C的误解.

我首先得到了代表的参考.然后我记录回来的类名.在我的例子中,输出正确地说"app delegate的类名是CalculatorAppDelegate".

但是,下一行的断言失败了,我不明白为什么.

- (void)testAppDelegate 
{
    id appDelegate = [[UIApplication sharedApplication] delegate];
    NSLog(@"app delegate's class name is %@", NSStringFromClass([appDelegate class]));
    NSLog(@"is it kind? %i", [appDelegate isKindOfClass:[CalculatorAppDelegate class]]);
    NSLog(@"is it member? %i", [appDelegate isMemberOfClass:[CalculatorAppDelegate class]]);
    NSLog(@"class == class %i", [appDelegate class] == [CalculatorAppDelegate class]);
    STAssertTrue([appDelegate isKindOfClass:[CalculatorAppDelegate class]], @"wtf");
}
Run Code Online (Sandbox Code Playgroud)

什么情况可能导致NSStringFromClass()返回正确的类名,而isKindOfClass返回false?

2011-03-19 15:51:13.864 Calculator[40092:207] app delegate's class name is CalculatorAppDelegate
2011-03-19 15:51:13.864 Calculator[40092:207] is it kind? 0
2011-03-19 15:51:13.865 Calculator[40092:207] is it member? 0
2011-03-19 15:51:13.865 Calculator[40092:207] class == class …
Run Code Online (Sandbox Code Playgroud)

iphone objective-c ocunit cs193p uiapplicationdelegate

14
推荐指数
1
解决办法
4151
查看次数

访问OCMock的andDo中的参数时的EXC_BAD_ACCESS

我正在尝试使用OCMock的stub和Do方法编写一段代码.

在这种情况下,正在测试UIImageView扩展类.我想检查扩展名为[self setImage:]并使用非零参数(稍后将使用其他图像比较).

使用OCMock的andDo方法时,在块完成后,测试将与EXC_BAD_ACCESS崩溃.

id mockView = [OCMockObject mockForClass:[UIImageView class]];
[[[mockView stub] andDo:^(NSInvocation *invocation)
  {
      UIImage *img;
      [invocation getArgument:&img atIndex:2]; <---- line causing the exception
      somebodySetImage |= (img != nil);

  }] setImage:OCMOCK_ANY];

  [mockView do_something_that_calls_setImage];
Run Code Online (Sandbox Code Playgroud)

我现在发现的唯一解决方案是使用andCall而不是andDo,但这使测试变得复杂.

我可以用andDo避免崩溃吗?

更新 嗯,我会尝试在这里给出一个更好的例子:这是测试代码的新部分:

- (void)testDownloadingThumbnail
{
    PInfo *_sut = [[PInfo alloc] init];

    __block id target = nil;

    id mock = [OCMockObject mockForClass:[NSOperationQueue class]];

    [[[mock expect] andDo:^(NSInvocation *inv)
    {
        NSInvocationOperation *op;
        [inv getArgument:&op atIndex:2]; …
Run Code Online (Sandbox Code Playgroud)

iphone xcode ocunit ocmock ios

14
推荐指数
1
解决办法
3630
查看次数

SSL连接从命令行运行单元测试时出现问题

目标

我们的目标是在持续集成环境中执行我们的单元测试(Jenkins)

(我认为每个问题都必须说明一个人想要实现的目标.也许这个问题实际上可以通过一种非常不同的方式解决)

更新:更多关于"你为什么要这样做?"

首先,我们正在讨论具体的,自行开发的硬件.我希望持续集成测试告诉我是否有人在没有告诉所有开发人员的情况下改变了盒子的行为(是的,是的,我知道,这样的事情永远不会发生......)

其次,我们的一些(并非所有)连接使用默认无效的证书,因此我们有代码来检查证书的有效性(SecTrustEvaluate等).当然,理想情况下,我们的测试也会测试该代码.但这似乎太多了.

第三:嗯,如果我能得到真正的交易,为什么我要嘲笑任何东西?IDE没有问题,为什么要命令行.

如果我想要可预测性,我会YES在所有测试中返回;)(我已经看到人们这样做了).不,我想知道代码是否真正适用于我们的设备.这是某种变态的欲望吗?

到目前为止问题已解决

从命令行运行测试听起来非常简单,但是

xcodebuild -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO clean test
Run Code Online (Sandbox Code Playgroud)

导致一个丑陋的错误:

unsupported build action 'test'
Run Code Online (Sandbox Code Playgroud)

所以我在网上搜索了一篇关于从命令行运行OCUnit测试的文章.

我按照所有步骤操作,我可以从命令行运行我的测试,如下所示:

xcodebuild -scheme CITests -sdk iphonesimulator TEST_AFTER_BUILD=YES ONLY_ACTIVE_ARCH=NO clean build
Run Code Online (Sandbox Code Playgroud)

剩下的问题

但是,现在对SSL服务器的任何NSURLConnection都将失败,因为"此服务器的证书无效.".从命令行运行测试时,我听说过钥匙串问题,但这是真的吗?是否拒绝任何SSL连接?

重现

https://github.com/below/SSLTestDemo获取示例.打开它,然后使用Xcode自己的Test⌘U命令运行样本测试.测试应该成功.

现在在命令行上运行测试:

xcodebuild -scheme CITests -sdk iphonesimulator TEST_AFTER_BUILD=YES ONLY_ACTIVE_ARCH=NO clean build
Run Code Online (Sandbox Code Playgroud)

由于"此服务器的证书无效",测试失败.错误.

任何指针?

  • 我做错了吗?
  • 这是一个真正的错误吗?
  • 如果是这样,有工作吗?

任何输入都表示赞赏!

xcode xcodebuild ocunit ios jenkins

14
推荐指数
1
解决办法
1099
查看次数

访问OCUnit测试目标中的UIImage

我正在为iPad应用程序编写图像处理测试.我的单元测试目标中有一个资源文件夹,里面有一张照片,但是当我尝试使用[UIImage imageNamed:@"photo1.jpg"]访问它时,没有返回任何图像.如果我将文件名更改为主资源文件夹中的文件名,则会返回图像.

有没有办法访问单元测试目标内的Resources文件夹?

iphone unit-testing objective-c ocunit ipad

13
推荐指数
2
解决办法
2493
查看次数