新しいプロジェクトでは、この簡単なテストがあります
#import <XCTest/XCTest.h>
#import "ViewController.h"
@interface ViewControllerTests : XCTestCase
@end
@implementation ViewControllerTests
- (void)testExample
{
// Using a class that is not in the test target.
ViewController * viewController = [[ViewController alloc] init];
XCTAssertNotNil(viewController, @"");
}
@end
ViewController.hはnotテストターゲットの一部ですが、これは問題なくテストをコンパイルおよび実行します。
これは、アプリケーションが最初に(依存関係として)ビルドされ、次にテストがビルドされるためだと思います。次に、リンカはViewControllerクラスが何であるかを判断します。
ただし、テストとViewControllerファイルがまったく同じである古いプロジェクトでは、リンカーフェーズでビルドが失敗します。
Undefined symbols for architecture i386: "_OBJC_CLASS_$_ViewController", referenced from: objc-class-ref in ViewControllerTests.o
このリンカエラーは、新しいXCTestユニットテストターゲットが作成された場合でも発生します。
代わりにこれを回避するために、アプリとテストターゲットの両方にソースを含めることができます(上の画像の両方のボックスにチェックマークを付けます)。これにより、シミュレータのシステムログに重複シンボルのビルド警告が表示されます(シミュレータを開き、cmd- /を押してこれを確認します)。
Class ViewController is implemented in both [...]/iPhone Simulator/ [...] /MyApp.app/MyApp and [...]/Debug-iphonesimulator/LogicTests.octest/LogicTests. One of the two will be used. Which one is undefined.
これらの警告により、次の例に示す問題が発生する場合があります。
[viewController isKindOfClass:[ViewController class]]; // = NO
// Memory address of the `Class` objects are different.
NSString * instanceClassString = NSStringFromClass([viewController class]);
NSString * classString = NSStringFromClass([ViewController class]);
[instanceClassString isEqualToString:classString]; // = YES
// The actual class names are identical
問題は、古いプロジェクトのどの設定で、アプリケーションソースファイルをテストターゲットに含める必要があるかということです。
稼働中のプロジェクトと稼働していないプロジェクトの間:
Ld
で始まるコマンド)に違いはありません。これを理解するのに少し時間を費やしました。
このドキュメント を読むと、Xcodeにはテストを実行するための2つのモードがあることがわかります。論理テストとアプリケーションテスト。違いは、ロジックテストは、クラスとシンボルが組み込まれた独自のターゲットをビルドすることです。結果の実行可能ファイルは、シミュレータで実行でき、テスト出力をXcodeにレポートします。一方、アプリケーションテストでは、実行時にアプリに挿入されるコードにリンクする動的ライブラリを構築します。これにより、iPhone環境でテストを実行し、Xibの読み込みなどをテストできます。
ソースファイルのリンクを解除すると、テストターゲットにシンボルが表示されないため、古いプロジェクトには、アプリケーション(ユニット)テストではなく、ロジックテスト用に設定されたテストターゲットがあるようです。
最近はXcodeが 2つを区別しないようにしています のようで、デフォルトではApplication Testsターゲットを作成することで、Logic Test Targetを単体テストに変更するために変更する必要があるすべてのことを確認できます1。
また、方向が少し異なるため、静的ライブラリターゲットではなくアプリケーションターゲットがあると仮定します。
$(SDKROOT)/Developer/Library/Frameworks $(inherited) $(DEVELOPER_FRAMEWORKS_DIR)
である必要があり、 余分な引用符やバックスラッシュなしこの情報は多かれ少なかれ上記のリンクされたドキュメントから来ていますが、Xcode 5の手順を更新しました。
うーん、100%eph515がデバッグシンボルが表示されることについて言っていることに注意してください。しかし、誰かがあなたのスキームのテストアクションをRelease
または他の構成でビルドするように設定しなかったことを確認したいかもしれません。スキームセレクタをクリックして、編集スキームを選択します。テストアクションをクリックし、ビルド構成がDebug
であることを確認します
静的ライブラリターゲットがある場合、2つのオプションがあります。1.ロジックテスト2.ホストアプリでのアプリケーションテスト
1.では、Bundle Loader
およびTest Host
が静的ライブラリターゲットに対して空であることを確認する必要があります。ソースは、実行する他の方法がないため、テストターゲットにコンパイルする必要があります。
2.の場合、Xcodeで新しいアプリプロジェクトを作成し、静的ライブラリプロジェクトをサブプロジェクトとして追加する必要があります。次に、Bundle Loader
およびTest Host
ビルド設定を、新しいアプリのテストターゲットから静的ライブラリテストターゲットに手動でコピーする必要があります。次に、新しいテストアプリのスキームを開き、テストターゲットを新しいアプリのテストアクションに追加します。 libでテストを実行するには、ホストアプリのテストアクションを実行します。
Xcode 6では、テストターゲット>一般>テストで「ホストアプリケーションAPIのテストを許可する」をチェックすることで、この問題を修正できました。
私もこれに遭遇し、jackslashの推奨に従いましたが、もう1つ追加しました。メインターゲットを選択し、デフォルトで非表示のシンボル(Apple LVM 5.0-コード生成)を探します。いいえ。これは、単体テストのターゲットが探しているコンパイル済みソースのすべてのシンボルを「隠す」ようです。私のために働く。ジャックスラッシュで概説されているすべてのステップも必ず含めてください。
答えは、ジャックスラッシュとeph515の答えの組み合わせでした。
Eph515の答えのようにsymbols hidden by default
は、デバッグ用にNoにする必要があります。
また、deployment postprocessing
は、デバッグ用にNoにする必要があります。
また、テストターゲットに含まれるすべてのライブラリを単体テストから削除する必要があります。残す必要があるのは、スクリーンショットの3と、単体テストに固有のすべてです。
また、リストの最後にビルドスクリプトのビルドビルドフェーズがある場合は、それを削除する必要があります(ユニットテストの成果物であるため)。
次に、すべてを jackslashの答え で行います。
私の場合、Xcode 6.2では、プロジェクトターゲットとテストターゲットの異なるアーキテクチャでエラーが発生しました。
プロジェクトターゲットには、armv7およびarmv7sアーキテクチャのみがあります(古いライブラリがあるため)
Project Testsターゲットには、armv7、armv7s、およびarm64アーキテクチャがあります。
私の場合、arm64アーキテクチャを削除することでこの問題を解決できます。
Project Editor -> Project Tests target -> Build Settings -> Valid Architectures = armv7 armv7s
(おそらく$(ARCHS_STANDARD)の代わりに "Architectures"を$(ARCHS_STANDARD_32_BIT)に設定する必要もあります)