Parameterized tests in f# - This is not a valid constant expression

巧了我就是萌 提交于 2019-12-07 05:02:12

问题


For some reason when passing arguments to the test via TestCase attrubute, I get the following error message about the first argument, which in this case is an array:

This is not a valid constant expression or custom attribute value

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)

But when removing the last argument, from both the attribute and the method itself, it all works just fine.

[<TestCase( [| 1; 2; 3 |], 3, 1)>]
let ``let example.`` (a, m, h) = 
    a
    |> proof1 m
    |> should equal (h,1)

What am I doing wrong? Preferably I would also define a tuple of int * int but it doesn't seem to work either.


回答1:


CLI has a restriction regarding kinds of attribute parameters:

  • primitive: bool, int, float, etc
  • enums
  • strings
  • type references: System.Type
  • 'kinda objects': boxed (if needed) representation of types from above
  • one dimensional array of one of types from above (ie. no nested arrays allowed)

So we can conclude at this point that you can not use tuple as an attribute parameter's type.

From here starts my speculations, so none of below can be true.

I played a bit with different attributes and found that F# compiler starts complain about an every array parameter, when attribute has variable number of arguments (params). For example, if I define the following attribute

public class ParamsAttribute : Attribute
{
    public ParamsAttribute(params object[] parameters)
    {}
}

and try to use it from F# code, I'll get an error:

[<Params(1, 2, 3)>] // here everything is OK
let x () = ()

[<Params([|1; 2; 3|])>] // the same error as you have
let y () = ()

I guess the compiler can consider params arguments as an array and therefore does not allow to define 'nested' array in it. But as I said, it is a pure speculation.




回答2:


Instead of an array parameter use a string parameter. Concatenate all the terms into the string and pass it in. Use String.Split to convert the string parameter into a string array then use Array.map to convert to the array of choice.

[<TestCase([|1, 2, 3|], 4, 5, 6)>]
let ``My Test``(param1: int[], param2: int, param3: int, param4: int) =
    // My test code

Becomes

[<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


来源:https://stackoverflow.com/questions/28012156/parameterized-tests-in-f-this-is-not-a-valid-constant-expression

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!