如果结果是使用NSLog记录,如何创建单元测试

时间:2014-02-19 12:07:05

标签: ios objective-c unit-testing nslog

我想创建一个检查一个特定案例的单元测试。此案例的结果是使用系统函数NSLog进行日志记录。

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

我搜索了很多,但还没有找到一个像样的解决方案。是否有可能通过观察或mb Xcode控制台内容可以以某种方式检索日志记录操作?

任何建议都会有所帮助!

编辑好吧,我看到有些误解我想要测试的内容。该库想要警告使用它的开发人员关于一些不好的输入。无论如何它将继续处理它们并返回结果(mb结果不正确)。但在处理的某个时刻,我检查值(虽然不是初始值)并记录警告消息,然后继续处理。即使我封装了这个逻辑,我也不想公开这个功能。

3 个答案:

答案 0 :(得分:2)

您没有显示任何代码,但听起来您想要测试在运行时期间仅出现在日志中的字符串的值。您可以轻松地隔离此方法以允许单元测试工作。

想象一下当前的代码是:

- (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

答案 1 :(得分:2)

我有同样的情况,所以你能做的就是 1.将日志直接导入到txt文件。

+ (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.在txt文件中搜索字符串“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一起使用

答案 2 :(得分:1)

这是对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\"")
    }
}