我想创建一个检查一个特定案例的单元测试。此案例的结果是使用系统函数NSLog
进行日志记录。
<2014-02-19 03:05:11> Warning bla-bla-bla. Please, check you code.
我搜索了很多,但还没有找到一个像样的解决方案。是否有可能通过观察或mb Xcode控制台内容可以以某种方式检索日志记录操作?
任何建议都会有所帮助!
编辑好吧,我看到有些误解我想要测试的内容。该库想要警告使用它的开发人员关于一些不好的输入。无论如何它将继续处理它们并返回结果(mb结果不正确)。但在处理的某个时刻,我检查值(虽然不是初始值)并记录警告消息,然后继续处理。即使我封装了这个逻辑,我也不想公开这个功能。
答案 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\"")
}
}