Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 有没有办法对副作用进行单元测试?_Unit Testing_Side Effects - Fatal编程技术网

Unit testing 有没有办法对副作用进行单元测试?

Unit testing 有没有办法对副作用进行单元测试?,unit-testing,side-effects,Unit Testing,Side Effects,任何代码都可能产生副作用。大多数情况下,副作用可能是糟糕设计和/或重构需求的标志,但当我发现很难针对单元测试进行测试时。考虑下面的例子: [Test] public void TrimAll_Removes_All_Spaces() { // Arrange var testSubject = "A string with lots of space"; var expectedResult = "Astringwithlotsofspace"

任何代码都可能产生副作用。大多数情况下,副作用可能是糟糕设计和/或重构需求的标志,但当我发现很难针对单元测试进行测试时。考虑下面的例子:

[Test]
public void TrimAll_Removes_All_Spaces()
{
    // Arrange
    var testSubject = "A    string  with     lots   of     space";
    var expectedResult = "Astringwithlotsofspace";

    // Act
    var result = testSubject.TrimAll();

    // Assert
    Assert.AreEqual(expectedResult, result);
}
这将测试以下扩展:

public static string TrimAll(this string str)
{
    PokeAround();

    return str.Replace(" ", "");
}
测试将通过,但没有预防副作用。调用
PokeAround
的效果将完全不被注意

假设你不知道什么是
PokeAround
,它可能是任何东西你如何编写一个测试来防范它?有可能吗

澄清: 关于
PokeAround
有一些评论认为完全未知是一个非常不可能的场景,因为我们在编写测试时有了源代码。不过,我问这个问题的原因是想找到一种方法来防止后来增加的副作用。也就是说,当我编写测试时,我可能会让exension方法如下所示:

public static string TrimAll(this string str)
{
    return str.Replace(" ", "");
}
考试通过了,一切都很好。然后,一个月后,当我在度假时,一位同事打电话给我。我希望我已经写过的测试失败,因为他失败了。

这就是所谓的感知。也就是说,感知调用被测试方法的效果

既然你不知道PokeAround是什么-它可能是任何东西

因为我们谈论的是单元测试,这几乎不应该是真的-单元测试是白盒测试,代码应该在那里供您检查。除非它位于某个封闭源代码的第三方库中,否则在这种情况下,您不需要对它进行测试,也不能根据定义对它进行单元测试(可能您需要功能/验收测试,但这完全是另一回事……)

更新:那么您想确保将来对单元测试方法的更改不会产生任何意外的副作用吗?我想你

  • 不能,
  • 不应该 您不能,因为在现实生活(非平凡)程序中,没有合理的方法来检测方法调用是否没有副作用。你要找的是一些检查,除了这个和这个小东西,整个宇宙的状态没有改变。即使从一个卑微的程序来看,这个宇宙也是巨大的。方法调用可以创建/更新/删除任意数量的本地对象(其中许多在单元测试环境中甚至看不到)、在可用的本地/网络文件系统上触摸文件、执行DB请求、进行远程过程调用


    你不应该这样做,因为这取决于你的同事在未来做出的改变,来负责他/她的改变的单元测试。如果您不相信会发生这种情况,那么您遇到的是人员或流程问题,而不是单元测试问题。

    您可以从另一个角度来看,通过为此代码编写单元测试,您将迫使自己承认代码中的问题(副作用)。然后,您可以以可测试的方式重新编写/重构代码,可以将
    PokeAround
    移动到它自己的函数中,或者如果它需要更多的输入/状态才能进行测试,就将它从您尝试测试的代码中重新定位。

    我不确定您是否可以。毕竟,它是一种预期效果还是一种副作用取决于设计者的意图

    我建议您断言“副作用”代码是不变的


    另外,像这样的工具可能会有所帮助,但我不认为它会对您的示例产生影响。

    取决于您所说的副作用-我的意思是,可能PokeAround()做了一些需要做的重要事情。副作用如何分类

    不管怎么说,我所知道的并没有特别的技术/技巧可以防止单单元测试中的副作用,但只要您对所有代码都有测试覆盖率,任何不必要的副作用都有希望通过至少一个测试得到

    BDD/集成测试工具也有助于解决这一问题,因为它们(通常)测试更大范围的功能,而不仅仅是单个类/方法


    您可能需要了解的一件事是(DBC)。这允许您指定前置和后置条件以及不变量,因此,如果使用无效参数调用方法、返回无效值或对象进入无效状态,将抛出某种错误。

    不可能。在任何测试阶段,副作用测试都很困难。在不同的项目(产品开发、工具开发、业务应用程序开发、游戏开发等)中是不同的

    如果没有完整的回归测试,就无法发现副作用

    在一个典型的项目(我经历过)中,“此更改是否有任何副作用”的问题通常会在项目快结束时(接近上线)或当有人想在已经生产的系统中添加热修复程序时被问到。我发现在没有回归测试的情况下,唯一(仍然有风险的)质量控制措施是代码审查

    希望能有帮助

    考虑到你不知道什么是PokeAround,它可能是任何东西你如何编写一个测试来防范它?有可能吗

    这个问题似是而非。这种情况在现实世界中不太可能发生

  • 你总是知道什么是口袋狗。这是单元测试。你有消息来源

    如果——通过某种组织上的邪恶——你被禁止阅读源代码,那么你就有组织上的问题,而不是技术上的问题

    如果你不知道PokeAround是什么,你会发现有些人特别邪恶,阻碍成功。他们需要新的工作。或者是你

  • 你必须为这个口袋灵犬使用模拟,这样你才能观察到副作用

  • “防止以后增加的副作用。”

    这不是一段神秘代码的例子。你还知道什么是口袋狗。你总是知道什么是口袋狗

    这就是为什么我们做回归T
    [Test]
    public void TrimAll_Removes_All_Spaces()
    {
        // Arrange
        var testSubject = "A    string  with     lots   of     space";
        var testSubjectCopy = "A    string  with     lots   of     space";
        var expectedResult = "Astringwithlotsofspace";
    
        // Act
        var result = testSubject.TrimAll();
    
        // Assert
        Assert.AreEqual(expectedResult, result);
    
        // Check for side effects
        Assert.AreEqual(testSubjectCopy, testSubject);
    }