单元测试代码合同

flu*_*ent 6 nunit code-contracts c#-4.0

我只是在.Net 4.0中玩代码合同,并且必须缺少一些明显的东西,因为它们的行为并不像我期望的那样.

我总是使用一个简单的if ... then .. throw语句来在函数的开头执行任何验证.

if (hours < 0 || hours > 8)
    throw new ArgumentOutOfRangeException("hours", "Hours must be between 0 and 8");
Run Code Online (Sandbox Code Playgroud)

我简单地用这个替换了

Contract.Requires<ArgumentOutOfRangeException>(hours >= 0 && hours <= 8, "Hours must be between 0 and 8");
Run Code Online (Sandbox Code Playgroud)

但它似乎从未在我的单元测试中引发问题.

    public static DurationUnit HoursAsDuration(int hours)
    {
        Contract.Requires<ArgumentOutOfRangeException>(hours >= 0 && hours <= 8, "Hours must be between 0 and 8");

        switch (hours)
        {
            case 1:
            case 2:
                return DurationUnit.Quarter;
            case 3:
            case 4:
                return DurationUnit.Half;
            case 5:
            case 6:
                return DurationUnit.ThreeQuarter;
            case 7:
            case 8:
                return DurationUnit.Full;
            default:
                return DurationUnit.None;
        }
    }

    [Test]
    public void CanConvertToDuration()
    {
        Assert.AreEqual(DurationUnit.None, DateTimeUtility.HoursAsDuration(0));
        Assert.AreEqual(DurationUnit.Quarter, DateTimeUtility.HoursAsDuration(1));
        Assert.AreEqual(DurationUnit.Quarter, DateTimeUtility.HoursAsDuration(2));
        Assert.AreEqual(DurationUnit.Half, DateTimeUtility.HoursAsDuration(3));
        Assert.AreEqual(DurationUnit.Half, DateTimeUtility.HoursAsDuration(4));
        Assert.AreEqual(DurationUnit.ThreeQuarter, DateTimeUtility.HoursAsDuration(5));
        Assert.AreEqual(DurationUnit.ThreeQuarter, DateTimeUtility.HoursAsDuration(6));
        Assert.AreEqual(DurationUnit.Full, DateTimeUtility.HoursAsDuration(7));
        Assert.AreEqual(DurationUnit.Full, DateTimeUtility.HoursAsDuration(8));

        //Would expect this to cause an issue
        Assert.AreEqual(DurationUnit.None, DateTimeUtility.HoursAsDuration(9));
    }
Run Code Online (Sandbox Code Playgroud)

测试返回true但我希望代码合同能够停止"9"的值进入switch语句.这是预期的行为吗?

Pas*_*uoq 1

如果你的函数的规范(用英语表达)是它接受 0..8 范围内的任何值hours并抛出异常hours,那么它的契约(用代码契约语言表达)并不要求它hours介于 0 之间8. 正确的翻译是该函数不需要任何东西,并且它确保如果hours在错误的范围内,则引发异常,并且它确保如果hours在正确的范围内,则完成正确的计算。

我希望有一种方法可以在代码合约中表达这些东西,但我不熟悉这种合约语言,只熟悉另一种语言。但原理是相同的:如果您希望检查成为生产构建的一部分,那么检查的条件不是先决条件。另一方面,合同可以(应该)表明已经进行了检查并且每个案例都得到了适当的处理。