FsUnit `должен равняться` не работает на `Some []`

Когда я запускаю этот тест FsUnit с NUnit 2.6.3,

let f xs = Some (List.map ((+) 2) xs)

[<Test>]
let test() =
  f []
  |> should equal (Some [])

Я получил:

Result Message: 
Expected: <Some([])>
  But was:  <Some([])>
Result StackTrace:  
at FsUnit.TopLevelOperators.should[a,a](FSharpFunc`2 f, a x, Object y)

Тест завершается неудачно, хотя ожидаемое и фактическое значения в сообщении совпадают. Что случилось?


person Ming-Tang    schedule 02.06.2014    source источник
comment
Похоже, что FsUnit изменил семантику = — запуск эквивалентного кода, но использование = вместо should equal возвращает то, что вы ожидаете.   -  person John Palmer    schedule 02.06.2014
comment
См. stackoverflow.com/questions/5667372/ - Unquote всегда делает то, что я имею в виду, и многое другое.   -  person Ruben Bartelink    schedule 03.06.2014


Ответы (2)


Причина в том, что FsUnit использует нетипизированный механизм под капотом, поэтому Expected выводится средством проверки типов как object (см. часть Object y в трассировке стека).

Обходной путь - добавить аннотацию типа для общих значений, т.е.

[<Test>]
let test() =
  f []
  |> should equal (Some ([]: int list))

Несколько человек были укушены этим, например. Странное поведение None в поставщиках типов.

Красота беглых утверждений для меня бессмысленна, как только они перестают быть типобезопасными. Я предлагаю создать безопасный тип альтернатива:

let shouldEqual (x: 'a) (y: 'a) = 
    Assert.AreEqual(x, y, sprintf "Expected: %A\nActual: %A" x y)
person pad    schedule 02.06.2014
comment
Это доступно в FsUnitTyped: fsprojects.github.io/FsUnit/FsUnitTyped.html. - person jrr; 18.03.2019

Это потому, что ваши два пустых списка имеют разные типы. См. типы actual и expected в этой версии теста:

[<Test>]
let test() =
  let expected = Some []
  let actual = f []
  actual |> should equal expected

expected равно 'a list option, а фактическое равно int list option, поэтому они не равны.

Если вы подскажете компилятору ожидаемый результат, он сработает.

[<Test>]
let test() =
  f []
  |> should equal (Some List.empty<int>)
person Leaf Garland    schedule 02.06.2014