33

この質問の解決策に触発されて、XCTest で同じアプローチを使用してみました。

「Generate Test Coverage Files=YES」と「Instrument Program Flow=YES」を設定しました。

XCode はまだ gcda ファイルを生成しません。誰でもこれを解決する方法について何か考えがありますか?

コード:

#import <XCTest/XCTestLog.h>

@interface VATestObserver : XCTestLog

@end

static id mainSuite = nil;

@implementation VATestObserver

+ (void)initialize {
    [[NSUserDefaults standardUserDefaults] setValue:@"VATestObserver"
                                             forKey:XCTestObserverClassKey];
    [super initialize];
}

- (void)testSuiteDidStart:(XCTestRun *)testRun {
    [super testSuiteDidStart:testRun];

    XCTestSuiteRun *suite = [[XCTestSuiteRun alloc] init];
    [suite addTestRun:testRun];

    if (mainSuite == nil) {
        mainSuite = suite;
    }
}

- (void)testSuiteDidStop:(XCTestRun *)testRun {
    [super testSuiteDidStop:testRun];

    XCTestSuiteRun *suite = [[XCTestSuiteRun alloc] init];
    [suite addTestRun:testRun];

    if (mainSuite == suite) {
        UIApplication* application = [UIApplication sharedApplication];
        [application.delegate applicationWillTerminate:application];
    }
}

@end

AppDelegate.m には次のものがあります。

extern void __gcov_flush(void);
- (void)applicationWillTerminate:(UIApplication *)application {
    __gcov_flush();
}

編集:現在のステータスを反映するように質問を編集しました(赤いニシンなし)。

編集それを機能させるには、テスト中のすべてのファイルをVATestObserverを含むテストターゲットに追加する必要がありました。

AppDelegate.m

#ifdef DEBUG
+ (void)initialize {
    if([self class] == [AppDelegate class]) {
        [[NSUserDefaults standardUserDefaults] setValue:@"VATestObserver"
                                                 forKey:@"XCTestObserverClass"];
    }
}
#endif

VATestObserver.m

#import <XCTest/XCTestLog.h>
#import <XCTest/XCTestSuiteRun.h>
#import <XCTest/XCTest.h>

// Workaround for XCode 5 bug where __gcov_flush is not called properly when Test Coverage flags are set

@interface VATestObserver : XCTestLog
@end

#ifdef DEBUG
extern void __gcov_flush(void);
#endif

static NSUInteger sTestCounter = 0;
static id mainSuite = nil;

@implementation VATestObserver

+ (void)initialize {
    [[NSUserDefaults standardUserDefaults] setValue:@"VATestObserver"
                                             forKey:XCTestObserverClassKey];
    [super initialize];
}

- (void)testSuiteDidStart:(XCTestRun *)testRun {
    [super testSuiteDidStart:testRun];

    XCTestSuiteRun *suite = [[XCTestSuiteRun alloc] init];
    [suite addTestRun:testRun];

    sTestCounter++;

    if (mainSuite == nil) {
        mainSuite = suite;
    }
}

- (void)testSuiteDidStop:(XCTestRun *)testRun {

    sTestCounter--;

    [super testSuiteDidStop:testRun];

    XCTestSuiteRun *suite = [[XCTestSuiteRun alloc] init];
    [suite addTestRun:testRun];

    if (sTestCounter == 0) {
        __gcov_flush();
    }
}
4

6 に答える 6

44
于 2013-10-15T16:59:04.763 に答える
3

testSuiteDidStop メソッドで新しい XCTestSuiteRun インスタンスを作成する必要があるため、== チェックで適切な結果が得られません。インスタンスの等価性に依存する代わりに、単純なカウンターを使用し、それがゼロになったときにフラッシュを呼び出します。これは、最上位の XCTestSuite の実行が終了したときに行われます。これを行うには、おそらくもっと賢い方法があります。

まず、テスト ターゲットとメイン アプリ ターゲットの両方で、'Generate Test Coverage Files=YES' と 'Instrument Program Flow=YES' を設定する必要がありました。

#import <XCTest/XCTestLog.h>
#import <XCTest/XCTestSuiteRun.h>
#import <XCTest/XCTest.h>

// Workaround for XCode 5 bug where __gcov_flush is not called properly when Test Coverage flags are set

@interface GCovrTestObserver : XCTestLog
@end

#ifdef DEBUG
extern void __gcov_flush(void);
#endif

static NSUInteger sTestCounter = 0;
static id mainSuite = nil;

@implementation GCovrTestObserver

- (void)testSuiteDidStart:(XCTestRun *)testRun {
    [super testSuiteDidStart:testRun];

    XCTestSuiteRun *suite = [[XCTestSuiteRun alloc] init];
    [suite addTestRun:testRun];

    sTestCounter++;

    if (mainSuite == nil) {
        mainSuite = suite;
    }
}

- (void)testSuiteDidStop:(XCTestRun *)testRun {

    sTestCounter--;

    [super testSuiteDidStop:testRun];

    XCTestSuiteRun *suite = [[XCTestSuiteRun alloc] init];
    [suite addTestRun:testRun];

    if (sTestCounter == 0) {
        __gcov_flush();
    }
}

@end

+initialize 呼び出しが Test ターゲットに含まれているときにオブザーバーで行われていないため、追加の手順が必要でした。

AppDelegate で、次を追加します。

#ifdef DEBUG
+(void) initialize {
    if([self class] == [AppDelegate class]) {
        [[NSUserDefaults standardUserDefaults] setValue:@"GCovrTestObserver"
                                                 forKey:@"XCTestObserverClass"];
    }
}
#endif
于 2013-10-02T22:18:37.730 に答える
0

Specta を使用している場合、独自のスウィズリングを行うため、このプロセスは少し異なります。以下は私のために働いています:

テスト バンドル:

@interface MyReporter : SPTNestedReporter // keeps the default reporter style
@end

@implementation MyReporter

- (void) stopObserving
{
  [super stopObserving];
  UIApplication* application = [UIApplication sharedApplication];
  [application.delegate applicationWillTerminate:application];
}

@end

AppDelegate:

- (void)applicationWillTerminate:(UIApplication *)application
{
#ifdef DEBUG
  extern void __gcov_flush(void);
  __gcov_flush();
#endif
}

次に、メイン スキームの Run セクションで環境変数SPECTA_REPORTER_CLASSをに設定して、カスタム レポーター サブクラスを有効にする必要があります。MyReporter

于 2013-11-28T13:25:04.663 に答える
0

-(void)applicationWillTerminate の GCOV Flush が機能しませんでした。アプリがバックグラウンドで実行されているためだと思います。

また、「Generate Test Coverage Files=YES」と「Instrument Program Flow=YES」を設定しましたが、gcda ファイルは設定しませんでした。

次に、TestClass の -(void)tearDown で "__gcov_flush()" を実行すると、TestClass の gcda-Files が得られました ;)

次に、AppDelegate で次の関数を作成しました。

@interface AppDelegate : UIResponder <UIApplicationDelegate>
+(void)gcovFlush;
@end

@implementation AppDelegate
+(void)gcovFlush{
  extern void __gcov_flush(void);
  __gcov_flush();
  NSLog(@"%s - GCOV FLUSH!", __PRETTY_FUNCTION__);
}
@end

-(void)tearDown で [AppDelegate gcovFlush] を呼び出したところ、私の gcda ファイルがあります ;)

これがお役に立てば幸いです、さようならクリス

于 2014-01-12T17:03:12.953 に答える