Как создать модульный тест, если результат регистрируется с 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\"")
}
}