Параметризованные тесты в F# - это недопустимое константное выражение
По какой-то причине при передаче аргументов в тест через TestCase
attrubute, я получаю следующее сообщение об ошибке о первом аргументе, который в данном случае является массивом:
Это недопустимое константное выражение или значение пользовательского атрибута
module GameLogicTest =
open FsUnit
open NUnit.Framework
open GameLogic.Examle
// This is not a valid constant expression or custom attribute value
[<TestCase( [| 1; 2; 3 |], 3, 1,1)>]
let ``let example.`` (a, m, h, c) =
a
|> proof1 m
|> should equal (h,c)
Но при удалении последнего аргумента как из атрибута, так и из самого метода все работает просто отлично.
[<TestCase( [| 1; 2; 3 |], 3, 1)>]
let ``let example.`` (a, m, h) =
a
|> proof1 m
|> should equal (h,1)
Что я делаю неправильно? Предпочтительно, я бы также определил кортеж int * int
но, похоже, это тоже не работает.
2 ответа
CLI имеет ограничение относительно видов параметров атрибута:
- примитив: bool, int, float и т. д.
- перечислений
- строки
- Тип ссылки: System.Type
- 'kinda objects': коробочное (при необходимости) представление типов сверху
- одномерный массив одного из типов сверху (т.е. вложенные массивы не допускаются)
Таким образом, мы можем сделать вывод, что вы не можете использовать кортеж в качестве типа параметра атрибута.
Отсюда начинаются мои предположения, поэтому ни одно из нижеприведенного не может быть правдой.
Я немного поиграл с разными атрибутами и обнаружил, что компилятор F# начинает жаловаться на каждый параметр массива, когда атрибут имеет переменное количество аргументов (params). Например, если я определю следующий атрибут
public class ParamsAttribute : Attribute
{
public ParamsAttribute(params object[] parameters)
{}
}
и попробуйте использовать его из кода F#, я получу ошибку:
[<Params(1, 2, 3)>] // here everything is OK
let x () = ()
[<Params([|1; 2; 3|])>] // the same error as you have
let y () = ()
Я предполагаю, что компилятор может рассматривать аргументы params как массив и, следовательно, не позволяет определять в нем "вложенный" массив. Но, как я уже сказал, это чистое предположение.
Вместо параметра массива используйте строковый параметр. Объедините все члены в строку и передайте ее. Используйте String.Split, чтобы преобразовать строковый параметр в строковый массив, затем используйте Array.map
преобразовать в массив выбора.
[<TestCase([|1, 2, 3|], 4, 5, 6)>]
let ``My Test``(param1: int[], param2: int, param3: int, param4: int) =
// My test code
становится
[<TestCase("1|2|3", 4, 5, 6)>]
let ``My Test``(param1: string, param2: int, param3: int, param4: int) =
let stringArray = param1.Split('|', SplitStringOptions.None)
let intArray = Array.map int stringArray
// My test code