gpt4 book ai didi

unit-testing - NUnit "theory"假设是否应该包括算法细节

转载 作者:行者123 更新时间:2023-12-04 20:45:00 25 4
gpt4 key购买 nike

假设我想将我的 NUnit 参数化测试方法更改为理论。就理论而言,他们应该定义断言将通过的所有假设/先决条件。根据 NUnit 文档:

[when comparing theory to parametrized test] A theory, on the other hand, makes a general statement that all of its assertions will pass for all arguments satisfying certain assumptions.



但据我所知,这意味着所谓的 PUT 代码应该基本上被转换为假设。 完全 .

那有什么理论意义呢?因为我们的算法会被写两次。首先是可测试的代码,其次是理论假设。因此,如果我们在算法中引入一个错误,我们的代码和测试都可能有相同的错误。 那有什么意义呢?

更好理解的例子

假设我们有一个只支持数字的校验和方法,我们想用理论来测试它。让我们写一个理论:
static Regex rx = new Regex(@"^\d+$", RegexOptions.Compiled);

[Theory]
public void ChecksumTheory(string value)
{
Assume.That(!string.IsNotNullOrWhiteSpace(value));
Assume.That(value.Length > 1); // one single number + checksum = same number twice
Assume.That(rx.IsMatch(value));

var cc = new ChecksumValidator();

bool result = cc.ValidateValue(value);

Assert.IsTrue(result); // not really as algorithm assumptions are missing
}

这是一个非常好的理论,除了没有实际实现测试代码算法并将其表示为一组假设,它的断言仍然不会通过,因为没有明确的算法假设,我们无法知道验证的结果是什么。

附加信息

当我们只需要提供关于输入状态的假设,即检查特定值是否被正确设置或它们的组合是否相关时,理论似乎相当琐碎和简洁:
[Theory]
public void Person_ValidateState(Person input)
{
Assume.That(input.Age < 110);
Assume.That(input.Birth < input.Death || input.Death == null);
...
}

问题
  • 如果需要为所有断言提供足够的假设,为什么要编写单元测试理论?
  • 如果我们不想通过提供所有算法假设来重新发明轮子,我们如何提供正确的假设?
  • 如果不是这种情况,我应该如何重写我的理论以使其成为 NUnit 理论的一个很好的例子?
  • 无论如何,测试理论的预期用途(由他们的创造者)是什么?
  • 最佳答案

    理论与参数化测试

    我还旨在在我的测试中引入假设,而不是使用参数化测试。但由于类似的想法,我仍然没有开始。

    假设的目标是通过应用过滤器将给定的输入描述为不可数的 - 或者说庞大但完整的 - 值集的子集。通过这种方式,您上面的代码是绝对正确的,但是在这种情况下,您必须为阴性结果测试编写几个类似的测试 - 例如。当结局cc.ValidateValue(...)false .再一次——为了便于理解——我仍然会依赖精心挑选的参数来对这个微不足道的函数进行参数化测试。

    另一方面,假设对于更复杂的业务逻辑的测试可能很有用。想象一下,你有一个装满高档汽车的车库,你想在一些偏远的地形上踩 throttle - 也让我们想象一下这是一个业务需求,所以你需要为它编写测试(这有多酷!)。然后你可以写一个这样的测试:

    [Theory]
    public void CarCanDriveOnMuddyGround(Car car)
    {
    Assume.That(car.IsFourWheelDrive);
    Assume.That(car.HasMotor);
    Assume.That(car.MaxSpeed > 50);
    Assume.That(car.Color != "white");

    bool result = car.DriveWithGivenSpeedOn<MuddyGround>(50);

    Assert.IsTrue(result);
    }

    看看这与 BDD 方法有什么密切关系?像你一样,我也不太相信在简单的单元测试中使用假设。但我确信根据不同的测试级别(单元、集成、系统、用户接受度)对测试功能(参数化、断言)使用不同的方法是个好主意。

    关于假设中的算法细节

    再想想你的具体问题。现在我明白你的意思了。用我的话来说:在你断言它给出一个积极的结果之前,你需要假设一个给定的值会给出一个积极的结果。对?我认为你找到了一个很好的例子,为什么理论并不总是有效。

    无论如何,我试图在一个稍微简单的例子中解决它(为了可读性)。但我承认这不是很有说服力:
    public class TheoryTests
    {
    [Datapoints]
    public string[] InvalidValues = new[] { null, string.Empty };

    [Datapoints]
    public string[] PositiveValues = new[] { "good" };

    [Datapoints]
    public string[] NegativeValues = new[] { "Bad" };

    private bool FunctionUnderTest(string value)
    {
    return value.ToLower().Equals(value);
    }

    [Theory]
    public void PositiveTest(string value)
    {
    Assume.That(!string.IsNullOrEmpty(value));

    var result = FunctionUnderTest(value);

    Assert.True(result);
    }

    [Theory]
    public void PassingPositiveTest(string value)
    {
    Assume.That(!string.IsNullOrEmpty(value));
    Assume.That(!NegativeValues.Contains(value));

    var result = FunctionUnderTest(value);

    Assert.True(result);
    }
    }
    PositiveTest显然会失败,因为缺少算法假设。
    参见 PassingPositiveTest 正文中的第二行这可以防止测试失败。缺点当然是这实际上是基于示例的测试,而不是纯粹的基于理论的测试。欢迎更好的想法。

    关于unit-testing - NUnit "theory"假设是否应该包括算法细节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19351648/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com