我正在编写一个框架,其中还包括一个可以在运行时启用/禁用的简单记录器。由于我希望尽可能多地对框架进行单元测试,所以我也希望测试记录器是否正确工作。
记录器只是通过NSLog进行日志记录。现在,我需要测试输出是否真正符合预期(即,它是否真的日志并是正确格式的输出)。我无法找到一种使用Xcode的XCTest框架来实现这个目标的方法。
我可以修改记录器,以便它在测试时不使用NSLog,但我认为这很容易出错。那么,是否有更好的方法来检查NSLog输出?
发布于 2016-02-11 09:12:02
我编写了一个实用工具类来解决这个问题,该类将文件描述符重定向到文件,并能够重置此重定向:
@interface IORedirector : NSObject
- (instancetype)initWithFileDescriptor:(int)fileDescriptor targetPath:(NSURL *)fileURL flags:(int)oflags mode:(mode_t)mode;
- (void)reset;
@end
@implementation IORedirector
{
int _fileDescriptor;
int _savedFileDescriptor;
}
- (instancetype)initWithFileDescriptor:(int)fileDescriptor targetPath:(NSURL *)fileURL flags:(int)oflags mode:(mode_t)mode
{
_savedFileDescriptor = dup(fileDescriptor);
if (_savedFileDescriptor == -1) {
NSLog(@"Could not save file descriptor %d: %s", fileDescriptor, strerror(errno));
return nil;
}
int tempFD = open(fileURL.path.fileSystemRepresentation, oflags, mode);
if (tempFD == -1) {
NSLog(@"Could not open %@: %s", fileURL.path, strerror(errno));
close(_savedFileDescriptor);
return nil;
}
if (close(fileDescriptor) == -1) {
NSLog(@"Closing file descriptor %d failed: %s", fileDescriptor, strerror(errno));
close(_savedFileDescriptor);
close(tempFD);
return nil;
}
if (dup2(tempFD, fileDescriptor) == -1) {
NSLog(@"Could not replace file descriptor %d with new one for %@: %s", fileDescriptor, fileURL.path, strerror(errno));
close(_savedFileDescriptor);
close(tempFD);
return nil;
}
_fileDescriptor = fileDescriptor;
close(tempFD);
return self;
}
- (void)dealloc
{
[self reset];
}
- (void)reset
{
if (_savedFileDescriptor == -1) return;
if (close(_fileDescriptor) == -1) {
NSLog(@"Closing file descriptor %d failed: %s", _fileDescriptor, strerror(errno));
return;
}
if (dup2(_savedFileDescriptor, _fileDescriptor) == -1) {
NSLog(@"Could not restore file descriptor %d: %s", _fileDescriptor, strerror(errno));
return;
}
close(_savedFileDescriptor);
_savedFileDescriptor = -1;
}
@end初始化器返回有效实例(重定向已建立)或nil。调用reset立即恢复重定向。
初始化程序和reset都可能失败并“丢失”原始文件描述符,但是窗口很小而且不太可能。这可能只有在多线程应用程序中使用这个类时才有意义(我不这么做),所以如果您打算在多线程环境中使用这个类,您需要确保每次只能使用一个初始化器或reset来使用全局互斥体或其他东西。
使用这个类(当然,我有一个单独的测试用例),我可以将STDERR_FILENO重定向到一个文件,从而捕获NSLog的输出。这样,我就可以测试未经修改的日志记录类。
创建临时文件的适当路径是留给读者的练习。
发布于 2016-02-05 11:53:36
有记录器输出字符串。让另一个对象打印这些。这样,您就可以对第一个对象和第二个对象分别进行单元测试。
https://stackoverflow.com/questions/35223468
复制相似问题