在 F# 中,如何将集合传递给 xUnit 的 InlineData 属性

编程入门 行业动态 更新时间:2024-10-24 05:21:47
本文介绍了在 F# 中,如何将集合传递给 xUnit 的 InlineData 属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想使用列表、数组和/或序列作为 xUnit 的 InlineData 的参数.

I would like to be about to use a list, array, and/or seq as a parameter to xUnit's InlineData.

在 C# 中,我可以这样做:

In C# I can do this:

using Xunit; //2.1.0 namespace CsTests { public class Tests { [Theory] [InlineData(new[] {1, 2})] public void GivenCollectionItMustPassItToTest(int[] coll) { Assert.Equal(coll, coll); } } }

在 F# 中,我有这个:

In F# I have this:

namespace XunitTests module Tests = open Xunit //2.1.0 [<Theory>] [<InlineData(8)>] [<InlineData(42)>] let ``given a value it must give it to the test`` (value : int) = Assert.Equal(value, value) [<Theory>] [<InlineData([1; 2])>] let ``given a list it should be able to pass it to the test`` (coll : int list) = Assert.Equal<int list>(coll, coll) [<Theory>] [<InlineData([|3; 4|])>] let ``given an array it should be able to pass it to the test`` (coll : int array) = Assert.Equal<int array>(coll, coll)

F# 代码给出以下构建错误:

The F# code give the following build errors:

Library1.fs (13, 16):这不是有效的常量表达式或自定义属性值

Library1.fs (13, 16): This is not a valid constant expression or custom attribute value

Library1.fs (18, 16):这不是有效的常量表达式或自定义属性值

Library1.fs (18, 16): This is not a valid constant expression or custom attribute value

参考第二和第三测试理论.

Referring to the 2nd and 3rd test theories.

是否可以使用 xUnit 将集合传递给 InlineData 属性?

Is it possible to use xUnit to pass in collections to the InlineData attribute?

推荐答案

InlineDataAttribute 依赖于 C# params 机制.这就是在 C# 中启用 InlineData 的默认语法的原因:-

InlineDataAttribute leans on the C# params mechanism. This is what enables the default syntax of InlineData in C# :-

[InlineData(1,2)]

您使用数组构造的版本:-

Your version with array construction:-

[InlineData( new object[] {1,2})]

只是编译器将上述内容翻译成的内容.如果您走得更远,您将遇到与 CLI 实际启用的内容相同的限制 - 最重要的是,在 IL 级别,使用属性构造函数意味着所有内容都需要在编译时归结为常量.与上述语法等效的 F# 很简单:[<InlineData(1,2)>],因此对您的问题的直接回答是:

is simply what the compiler translates the above into. The minute you go further, you'll run into the same restrictions on what the CLI will actually enable - the bottom line is that at the IL level, using attribute constructors implies that everything needs to be boiled down to constants at compile time. The F# equivalent of the above syntax is simply: [<InlineData(1,2)>], so the direct answer to your question is:

module UsingInlineData = [<Theory>] [<InlineData(1, 2)>] [<InlineData(1, 1)>] let v4 (a : int, b : int) : unit = Assert.NotEqual(a, b)

虽然我无法避免对@bytebuster 的例子进行重复:) 如果我们定义一个助手:-

I was unable to avoid riffing on @bytebuster's example though :) If we define a helper:-

type ClassDataBase(generator : obj [] seq) = interface seq<obj []> with member this.GetEnumerator() = generator.GetEnumerator() member this.GetEnumerator() = generator.GetEnumerator() :> System.Collections.IEnumerator

那么(如果我们愿意放弃懒惰),我们可以滥用list来避免必须使用seq/yield来赢得代码高尔夫:-

Then (if we are willing to forgo laziness), we can abuse list to avoid having to use seq / yield to win the code golf:-

type MyArrays1() = inherit ClassDataBase([ [| 3; 4 |]; [| 32; 42 |] ]) [<Theory>] [<ClassData(typeof<MyArrays1>)>] let v1 (a : int, b : int) : unit = Assert.NotEqual(a, b)

但是seq的原始语法可以做得足够干净,所以没有必要像上面那样使用它,而是我们这样做:

But the raw syntax of seq can be made sufficiently clean, so no real need to use it as above, instead we do:

let values : obj[] seq = seq { yield [| 3; 4 |] yield [| 32; 42 |] // in recent versions of F#, `yield` is optional in seq too } type ValuesAsClassData() = inherit ClassDataBase(values) [<Theory; ClassData(typeof<ValuesAsClassData>)>] let v2 (a : int, b : int) : unit = Assert.NotEqual(a, b)

然而,对我来说,xUnit v2 最惯用的方式是直接使用 MemberData(类似于 xUnit v1 的 PropertyData,但一般也适用于字段):-

However, most idiomatic with xUnit v2 for me is to use straight MemberData (which is like xUnit v1's PropertyData but generalized to also work on fields) :-

[<Theory; MemberData("values")>] let v3 (a : int, b : int) : unit = Assert.NotEqual(a, b)

正确的关键是将 : seq(或 : obj[] seq)放在序列的声明上,否则 xUnit 将抛出在你身边.

The key thing to get right is to put the : seq<obj> (or : obj[] seq) on the declaration of the sequence or xUnit will throw at you.

xUnit 2 的更高版本包括一个类型化的 TheoryData,它允许您编写:

Later versions of xUnit 2 include a typed TheoryData, which lets you write:

type Values() as this = inherit TheoryData<int,int>() do this.Add(3, 4) this.Add(32, 42) [<Theory; ClassData(typeof<Values>)>] let v2 (a : int, b : int) : unit = Assert.NotEqual(a, b)

这也会对每个参数进行类型检查.

That also type-checks each argument.

更多推荐

在 F# 中,如何将集合传递给 xUnit 的 InlineData 属性

本文发布于:2023-11-08 07:51:02,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1568786.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何将   属性   xUnit   InlineData

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!