Я ищу чистый набор способов управления Конкретное равенство тестов в модульных тестах F#. В 90% случаев стандартное структурное равенство отвечает всем требованиям, и я могу использовать его с снять кавычки, чтобы выразить связь между моими result
и моими expected
.
TL; DR «Я не могу найти чистый способ иметь пользовательскую функцию равенства для одного или двух свойств в значении, 90% которого хорошо обслуживается структурным равенством, есть ли в F # способ сопоставить произвольную запись с пользовательским равенством только для одного или двух его полей?»
Пример общей техники, которая работает для меня
При проверке функции, которая выполняет сопоставление 1:1 одного типа данных с другим, я часто в некоторых случаях извлекаю совпадающие кортежи с обеих сторон и сравниваю входной и выходной наборы. Например, у меня есть оператор: -
let (====) x y = (x |> Set.ofSeq) = (y |> Set.ofSeq)
Итак, я могу сделать:
let inputs = ["KeyA",DateTime.Today; "KeyB",DateTime.Today.AddDays(1); "KeyC",DateTime.Today.AddDays(2)]
let trivialFun (a:string,b) = a.ToLower(),b
let expected = inputs |> Seq.map trivialFun
let result = inputs |> MyMagicMapper
test <@ expected ==== actual @>
Это позволяет мне Assert
сопоставлять каждый из моих входов с выходом без каких-либо лишних выходов.
Эта проблема
Проблема в том, что я хочу иметь собственное сравнение для одного или двух полей.
Например, если мой DateTime проходит через уровень сериализации с небольшими потерями с помощью SUT, мне нужно толерантное DateTime
сравнение для конкретного теста. Или, может быть, я хочу сделать проверку без учета регистра для поля string
Обычно я использую библиотеку Likeness<Source,Destination>
SemanticComparison Марка Симанна для определения Проверьте конкретное равенство, но я столкнулся с некоторыми препятствиями:
- кортежи: F# скрывает
.ItemX
вTuple
, поэтому я не могу определить свойство через.With
строго типизированное имя поляExpression<T>
- типы записей: TTBOMK это
sealed
от F# без отказа, поэтому SemanticComparison не может проксировать их, чтобы переопределитьObject.Equals
Мои идеи
Все, что я могу придумать, это создать общий прокси типа сходства, который я может включаться в кортеж или запись.
Или, может быть, используя сопоставление с образцом (можно ли использовать это для создания IEqualityComparer
, а затем выполнить сравнение набора, используя это?)
Альтернативный провальный тест
Я также готов использовать некоторые другие функции для проверки полного сопоставления (т.е. не злоупотреблять F# Set
или включает слишком много стороннего кода, т.е. что-то, что нужно сделать:
let sut (a:string,b:DateTime) = a.ToLower(),b + TimeSpan.FromTicks(1L)
let inputs = ["KeyA",DateTime.Today; "KeyB",DateTime.Today.AddDays(1.0); "KeyC",DateTime.Today.AddDays(2.0)]
let toResemblance (a,b) = TODO generate Resemblance which will case insensitively compare fst and tolerantly compare snd
let expected = inputs |> List.map toResemblance
let result = inputs |> List.map sut
test <@ expected = result @>
SemanticComparer<T>
от SemanticComparison? Я не знаю, может ли это помочь вам с этими проблемами, но это лучшее предложение, которое я могу сейчас сделать. - person Mark Seemann   schedule 29.11.2013propertyPicker
и типов записей, являющиесяsealed
. (Я тоже немного исключил это из-за того, что многиеLikeness
средства были излишними в этом контексте. Честно говоря, я корпел над обсуждением #99 более одного раза и просто не получил его (правда, я не прошел код) - до сих пор!). - person Ruben Bartelink   schedule 29.11.2013SemanticComparer<T>
возможно может помочь. Между прочим, он работает со структурными типами F#< /а> также. Текущий API находится в стадии разработки. - person Nikos Baxevanis   schedule 07.12.2013