Резюме
Существуют ли какие-либо события, которые можно запускать перед каждым случаем свойства, чтобы я мог запускать установку и демонтаж для каждого запуска свойства?
Полная версия
Я хочу иметь возможность тестировать парное поведение, например, я всегда могу получать письменные записи или выходные данные readAllLines равны входным данным для writeAllLines со свойствами. Я также хочу, чтобы свойство не заботилось о том, как реализованы наборы операций (т. е. нужно ли очищать какие-либо ресурсы).
Каждый запуск свойства должен
- быть независимым от других запусков
- поддерживать состояние между вызовами операций в рамках одного запуска
- не знаю о том, как операции поддерживают состояние
- не быть утечкой ресурсов
Я использую FsCheck и Expecto. Примеры будут в Expecto, но проблема не во фреймворке.
Очень легко написать такую настройку и разборку с помощью тестов, основанных на примерах. Они принимают предсказуемый набор аргументов, поэтому я могу запускать их в оболочке, которая добавляет события до и после.
let testWithEnv setup cleanup name test =
let testWrap () =
let (api, env) = setup ()
test api
cleanup env
testCase name testWrap
То же самое нельзя сделать с тестами свойств. У них есть неизвестное количество аргументов, которые в значительной степени будут заполнены случайными данными.
Я могу довольно легко применить набор парных поведений, но любые созданные ресурсы, такие как потоки, остаются неиспользованными.
let testPropertyWithEnv setup cleanup name test =
let testWrap () =
let (api, env) = setup () // this is actually run once, but immutable so the individual runs don't leak state
test api // have to return this to pass along unapplied parameters
testProperty name testWrap
я изучил
Runner eventsГлядя на как запускать тесты FsCheck, ближайшие хуки кажутся
OnStartFixture
который запускается только один раз для каждого тестового классаOnArguments
запускается после каждого прохода и потенциально может работать для запуска очистки
Существуют также экспериментальные функции тестирования на основе моделей, которые могут работать. Однако это кажется очень тяжелым, учитывая, что меня интересует только внешняя согласованность операций. Мне не нужен доступ к резервному состоянию.
Giving up and inliningя всегда могу написать
testProperty "name" (fun arg1 arg2 ->
let (api,env) = setup ()
//test code here
cleanup env
)
но я хотел бы избежать шаблонов в каждом свойстве и разоблачения резервного состояния.
IDisposablesОдноразовые объекты также не решают проблему отсутствия установочного хука.
More hands-on run loopЯ искал способы запуска тестов свойств в своей оболочке, но самый маленький бегун Check.one
предназначен для одного свойства, без перехватов между запусками свойства.
Сделать обёртку ленивой тоже не получится testProperty name lazy(testWithSetup)