Как создать модульный тест, если результат регистрируется с NSLog

Я хочу создать модульный тест, который проверяет один конкретный случай. Результатом этого случая является запись с системной функцией NSLog,

<2014-02-19 03:05:11> Warning bla-bla-bla. Please, check you code.

Я много искал, но не нашел достойного решения. Есть ли вероятность, что операция регистрации может быть захвачена с помощью наблюдения или содержимое консоли mb Xcode может быть каким-то образом получено?

Любой совет будет полезен!

РЕДАКТИРОВАТЬ Хорошо, я вижу, что есть некоторые недоразумения, что я хочу проверить. Библиотека хочет предупредить разработчика, который ее использует, о каком-то неверном вводе. Он все равно продолжит их обрабатывать и вернет результат (мб неверный результат). Но в какой-то момент обработки я проверяю значение (но не начальное значение) и записываю предупреждение, а затем продолжаю обработку. Даже если я инкапсулирую эту логику, я не хочу, чтобы эта функция была общедоступной.

3 ответа

Решение

У меня тот же случай, так что вы можете сделать это 1.Прямой ваш журнал в текстовый файл.

+ (void)recordLog{
    NSArray *allPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [allPaths objectAtIndex:0];
    pathForLog = [documentsDirectory stringByAppendingPathComponent:@"FWTestLog.txt"];
    NSLog(@"path = %@",pathForLog);

    stderrSave = dup(STDERR_FILENO);
    freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}

2. Найдите шаблон "bla-bla-bla" в текстовом файле. И используйте XCTTest, чтобы проверить, найдена ли строка.

3.Закройте файл и удалите его, чтобы другой nslog вернулся в консоль.

+ (void)closeLog{
    fflush(stderr);
    dup2(stderrSave,STDERR_FILENO);
    close(stderrSave);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    [fileManager removeItemAtPath:pathForLog error:&error];
}

Я обертываю его внутри своего пользовательского тестового класса, чтобы использовать его с другим стандартным XCTTest

Вы не показываете никакого кода, но похоже, что вы хотите проверить значение строки, которая во время выполнения появляется только в журнале. Вы можете легко изолировать этот метод, чтобы позволить модульному тестированию работать.

Итак, представьте, что текущий код:

- (void)someMethod {
    NSString *string = @"Generated using some process";
    NSLog(@"String is %@", string);
    [self useString:string];
}

Это можно изменить на:

- (NSString *)generateString {
    NSString *string = @"Generated using some process";
    return string;
}

- (void)someMethod {
    NSString *string = [self generateString];
    NSLog(@"String is %@", string);
    [self useString:string];
}

Ваш юнит-тест будет сосредоточен на generateString скорее, чем someMethod,

Вот преобразование в Swift, я также добавил функцию поиска:

class YourTestClass: XCTestCase {

    // Used class properties here, because only a specific output is put to the logfile, rest of the logs shall stay in the console e.g. for your build server logs.
    var stderrSave: Int32 = 0
    var logFilePath: String {
        get {
            let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
            return documentsPath! + "/FWTestLog.txt"
        }
    }

    // Will be called before you want to have all logs being redirected to your logile
    func startLogging() {
        self.stderrSave = dup(STDERR_FILENO)
        freopen(self.logFilePath.cString(using: .ascii), "a+", stderr)
    }

    // Will be called when you want to stop redirecting all logs to a separate file
    func closeLogging() {
        fflush(stderr);
        dup2(stderrSave,STDERR_FILENO);
        close(stderrSave);
        try? FileManager.default.removeItem(atPath: self.logFilePath)
    }

    // Search for the according string
    func recordLog(logged string:String) -> Bool {
        let content = try? String(contentsOfFile: self.logFilePath)
        return (content?.hasSuffix(string + "\n"))!
    }

    func testExample() {
        self.startLogging()
        var isRecorded = self.recordLog(logged: "your logged string")
        XCTAssertFalse(isRecorded, " String should not have been logged yet: \"your logged string\"")
        NSLog("your logged string")
        isRecorded = self.recordLog(logged: "your logged string")
        self.closeLogging()
        XCTAssertTrue(isRecorded, " Expected the String to be logged: \"your logged string\"")
    }
}
Другие вопросы по тегам