Eam*_*nne 23 c# linq unit-testing expression-trees
基本上NUnit,xUnit,MbUnit,MsTest等具有类似于以下的方法:
Assert.IsGreater(a,b)
//or, a little more discoverable
Assert.That(a, Is.GreaterThan(b))
Run Code Online (Sandbox Code Playgroud)
但是,内置的这种比较运算符数量有限; 并且他们不必要地复制语言运算符.当我想要任何稍微复杂的东西时,比如...
Assert.That(a.SequenceEquals(b))
Run Code Online (Sandbox Code Playgroud)
我经常要么继续挖掘手册以找到NUnit-speak中表达式的等价物,要么被迫回退到具有较少有用错误消息的普通布尔断言.
但是,C#与任意表达式很好地集成 - 因此应该可以使用具有以下签名的方法:
void That(Expression<Func<bool>> expr);
Run Code Online (Sandbox Code Playgroud)
这种方法既可用于执行测试(即验证断言),也可用于在测试失败时提供不太透明的诊断; 毕竟,表达式可以呈现为伪代码,以指示哪个表达式失败; 通过一些努力,您甚至可以智能地评估失败的表达式,以提供子表达式值的一些线索.
例如:
Assert.That(()=> a == b);//could inspect expression and print a and b
Assert.That(()=> a < b && b < c);
//could mention the values of "a<b" and "b<c" and/or list the values of a, b, and c.
Run Code Online (Sandbox Code Playgroud)
至少,它会使表达式的并行语言变得不必要,并且在某些情况下,它可能使失败消息更有用.
这样的事情存在吗?
编辑: 在尝试(并且喜欢!)Power Assert之后,我最终重新实现它以解决一些限制.我的变体发表为ExpressionToCode ; 请参阅下面的答案以获取改进列表.
Guy*_*Guy 11
查看PowerAssert库(下面的示例输出):
PAssert.IsTrue(() => x + 5 == d.Month * y);
System.Exception : IsTrue failed, expression was:
x + 5 == d.Month * y
| | | | | | |
| | | | | | 6
| | | | | 18
| | | | 3
| | | 01/03/2010 00:00:00
| | False
| 16
11
Run Code Online (Sandbox Code Playgroud)
http://powerassert.codeplex.com/
小智 5
实际上有一个很好的理由是NUnit提供自己的DSL而不是使用普通的C#表达式.NUnit应该使用相同的语法处理任何 .NET语言.这并不是说我们不能拥有lambdas,只是因为我们不会完全依赖任何特定的语言功能.
所提出的许多想法都可行,许多第三方软件解决方案可以纳入NUnit,只要他们的作者想要提供它们.当然,很多人喜欢将他们的解决方案分开,这也没关系.但如果您希望他们与NUnit更紧密地合作,请与您最喜欢的作者交谈.
在NUnit 2.5中,您可以使用PredicateConstraint,它以lambda作为参数.但是,语法有点限制.Matches关键字将在表达式的中间工作,因此您可以编写...
Assert.That(someActual,Not.Matches(someLambda);
但这样做没有不要求......
Assert.That(someActual,new PredicateConstraint(someLambda));
当然,这些都不像建议的语法那样干净.
欢迎所有对此问题感兴趣的人加入我们的nunit讨论,讨论NUnit中的内容实际上会导致行动!
查理
(原海报在这里)
我喜欢PowerAssert.NET的简单语法和消息,但它生成的 C# 有很多问题。特别是,它不支持多种表达式功能,并且不会在运算符优先级/关联性需要的地方添加括号。在修复了一些错误(并将其报告给作者)后,我发现使用不同的方法修复并从头开始重新实现它会更简单。
用法类似:
PAssert.That(()=>
Enumerable.Range(0,1000).ToDictionary(i=>"n"+i)["n3"].ToString()
== (3.5).ToString()
);
Run Code Online (Sandbox Code Playgroud)
输出:
PAssert.That failed for:
Enumerable.Range(0, 1000).ToDictionary(i => "n" + (object)i)["n3"].ToString() == 3.5.ToString()
| | | | | |
| | | | | "3.5"
| | | | false
| | | "3"
| | 3
| {[n0, 0], [n1, 1], [n2, 2], [n3, 3], [n4, 4], [n5, 5], [n6, 6], [n7, 7], [n8, 8], [n9, 9], ...}
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...}
Run Code Online (Sandbox Code Playgroud)
对PowerAssert.NET的改进:
dict["mykey"]==3)() => x - (a - b) + x * (a + b)正确重新生成)1m + (decimal)Math.Sqrt(1.41))Func<int, bool>生成的项目(带有单元测试)托管在 Google 代码中,名称为ExpressionToCode - 我希望它对其他人有用。