Кстати, как общее практическое правило, всякий раз, когда вы используете DateTime.Now
внутри функции, я бы рекомендовал превратить ее в функцию pure , переместив currentTime
в параметр. Это делает ваше модульное тестирование намного проще, потому что вам не нужно высмеивать DateTime.Now
, вам просто нужно пройти время, которое вы хотите, чтобы быть «текущим» временем для этого модульного теста. Например, чтобы проверить isFileStale
с вашей текущей функцией, ваш модульный тест должен будет проверить текущее время, создать файл с отметкой времени (текущее время - N дней), а затем вызвать isFileStale
для этого файла. Но с версией isFileStale
, которая принимает currentTime
в качестве параметра, ваш тест будет:
- Создание файла с отметкой времени 2010-01-01
- Это 7 дней 2010-01-07? Ответ должен быть "нет".
- Это 7 дней 2010-01-08? Ответ должен быть "да".
Это также позволяет вам легко тестировать такие вещи, как 29 февраля, без необходимости запускать ваши модульные тесты точно в нужное время каждые четыре года.
Теперь для такой простой функции, как isFileStale
, это может не понадобиться. Но это хорошее правило, чтобы запомнить. Я бы порекомендовал написать следующую пару функций (начиная с кода gileCAD, так как он отлично):
let isFileStale currentTime days_old fn =
let lastFileUsed = File.GetLastAccessTime(fn)
(currentTime - lastFileUsed).Days >= days_old
let isFileOlderThanNDays days_old fn =
isFileStale DateTime.Now days_old fn
Обратите внимание, что я поменял местами параметры days_old
и fn
, потому что это позволяет вам писать код, который имеет смысл в конвейере:
if "/path/to/file" |> isFileOlderThanNDays 7 then
printfn "File is at least a week old"
else
printfn "File is relatively fresh"