注意:现在单元测试更容易设置.本教程与Xcode版本5及更高版本无关.
我花了很长时间,但我终于设法使它适用于我的项目.为了创建"逻辑"测试,我遵循Apple关于创建逻辑测试的指导原则.一旦您了解在构建期间运行逻辑测试,这就可以正常工作.
为了能够调试这些测试,需要创建一个可以调用这些测试的自定义可执行文件.本文通过对所著的Grokking可可博客肖恩·米塞利提供的所有信息来做到这一点.然而,它并没有立即取得成功,需要进行一些调整.
我将介绍Sean教程中提供的主要步骤,提供一些"for dummies"大纲,这花了我一些时间来弄清楚:
使用XCode 3.2.5执行以下操作
在XCode 4中,可以直接调试单元测试.只需编写测试,将其作为测试之一添加到目标并在其中设置断点.就这样.会有更多.
两者的名字可以是任何东西,但我会避免空格.
这里最重要的一点是获得正确的otest,即适用于您当前的iOS而不是默认的Mac版本.这在Sean的教程中有详细描述.以下是一些帮助我做好准备的细节:
讽刺的论点很容易设置......但事实证明这是我最大的问题.我最初将我的逻辑测试目标命名为"LogicTests Debug".使用此名称和"LogicTests Debug.octest"(带引号)作为otest的参数我保持otest终止与退出代码1并且永远不会停止到我的代码...
解决方案:目标名称中没有空格!
otest的论据是:
以下是复制/粘贴的环境变量列表:
请注意,我也尝试过DYLD_FORCE_FLAT_NAMESPACE,但这只是造成了骚乱.
我已经创建了一个带有Core Data模型的项目.应用程序查找模型文件(.momd)并运行正常.
不幸的是,单元测试不断返回null:
NSURL *dataModelURL = [[NSBundle mainBundle] URLForResource:@"myDataModel" withExtension:@"momd"];
Run Code Online (Sandbox Code Playgroud)
我可以在主目标和单元测试目标的Compile Sources目录中看到myDataModel.xdatamodeld文件夹和文件 - 但这似乎不够.我在单元测试目标中还缺少什么?
谢谢,-Luther
我正在使用自定义实体迁移策略为我的迁移构建映射模型,我真的想为此迁移构建一些单元测试.当我运行应用程序时,迁移似乎正常工作,但当我通过单元测试运行迁移时,根本不会调用我的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) 有没有办法加载原型单元格,以及故事板中定义的任何IBOutlet连接?
更新
我想对单元格(单元的UICollectionViewCell)进行单元测试,因此希望将它加载到UIViewController上下文之外.
实际上,就像您可以从笔尖加载自定义视图一样,指定其文件的所有者并设置其IBOutlet.
我在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邮件列表档案中搜索过,找不到有类似问题的人.我希望我错过了什么 - 但它是什么?
在运行应用程序测试时(即在设备上),我的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) 我正在玩一个简单的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) 我正在尝试使用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) 我们的目标是在持续集成环境中执行我们的单元测试(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)
由于"此服务器的证书无效",测试失败.错误.
任何输入都表示赞赏!
我正在为iPad应用程序编写图像处理测试.我的单元测试目标中有一个资源文件夹,里面有一张照片,但是当我尝试使用[UIImage imageNamed:@"photo1.jpg"]访问它时,没有返回任何图像.如果我将文件名更改为主资源文件夹中的文件名,则会返回图像.
有没有办法访问单元测试目标内的Resources文件夹?