F#中的参数化测试 - 这不是一个有效的常量表达式。

8
由于某些原因,当通过TestCase属性传递参数给测试时,我会收到有关第一个参数的以下错误消息,该参数在此情况下是一个数组:

这不是有效的常量表达式或自定义属性值。

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 的元组,但也似乎行不通。

我刚刚在不同的上下文中研究了相同的错误信息(使用FSharp.Data JsonProvider)。我不得不在我创建的绑定上方添加一个特殊的指示器(即[<Literal>])。老实说,我不太确定这是做什么的,但也许这也可以应用在这里? - pseudoramble
2个回答

7

CLI对属性参数的种类有限制:

  • 基本类型:bool、int、float等
  • 枚举
  • 字符串
  • 类型引用:System.Type
  • '某种对象':上述类型的装箱(如果需要)表示
  • 一维数组中的一个类型(即不允许嵌套数组)

因此,我们可以得出结论:你不能将元组作为属性参数的类型。

从这里开始是我的推测,所以以下内容都可能不正确。

我尝试使用不同的属性并发现,在属性具有可变数量参数(params)时,F#编译器会对每个数组参数进行抱怨。例如,如果我定义以下属性:

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参数视为一个数组,因此不允许在其中定义“嵌套”数组。但正如我所说,这只是一种纯粹的推测。


1

不要使用数组参数,使用字符串参数。将所有术语连接成字符串并传递。使用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接