【问题标题】:Should I write unit test for everything?我应该为所有内容编写单元测试吗?
【发布时间】:2010-10-05 14:57:48
【问题描述】:

我想知道我是否应该为所有内容编写单元测试。有一些类是很难写单元测试的。例如,我正在编写一些处理音频的程序。从麦克风捕获音频的类,以及向扬声器播放音频的类,我如何为这些类编写单元测试?我无法获得这些类的输出和输入,所以几乎不可能测试它们?我唯一能做的测试是 getter 和 setter,那些无聊的测试。那么问题来了,编写单元测试的指导方针是什么?而我应该如何处理这些难以测试的类?

【问题讨论】:

    标签: unit-testing tdd mocking


    【解决方案1】:

    在有意义的地方使用单元测试 - 不要以 100% 的覆盖率为目标。主要准则是思考,而不是套用教条或懒惰。

    话虽如此:如果您有自然难以测试的课程,请尽量减少他们必须做的事情。隔离不可测试的代码并将其 API 分离到一个接口中。然后针对模拟或存根测试使用该 API 的逻辑。

    【讨论】:

    • 我试着嘲笑管理层和公司。在银行开始退回我的 MockPaychecks 之前,一切正常。我出去试图解释说我正在推动 TDD 作为一种社会变革的力量,但他们称之为安全。愚蠢的银行家。
    【解决方案2】:

    我只在我知道这样可以节省时间的地方编写单元测试。当我开始进行单元测试时,这只是类的一小部分(那些糟糕的 ejb !!)。今天,我几乎测试了所有东西,并节省了我所做的每一件事的总开发时间。如果有一种通过麦克风测试用户输入的有效方法,我也会这样做。但据我所知,以节省我时间的方式是不可能的。

    所以我认为您应该对当前“测试能力”中的所有内容进行单元测试。您应该尝试扩展此功能,但过度扩展确实会发出错误优先级的信号;很可能还有其他一些值得您关注的测试。 (技术上我是测试感染,但不是TDD感染

    收益递减规律适用于单元测试和任何其他测试一样;最后 5% 的回报非常低,而且成本很高。

    【讨论】:

      【解决方案3】:

      我用来决定是否开发单元测试的一个规则是:如果你的类(或任何单元)将被“发布到野外”,那么你绝对应该考虑编写单元测试。

      我所说的“在野外”是指:一旦您的代码处于无法预测或控制事物如何与之交互的情况。因此,通过 API 公开的类或向用户输入公开的类可能应该进行单元测试。

      就个人而言,我认为为一切编写单元测试可能是在浪费您的时间。这确实是一个您需要考虑的复杂问题:

      • 这个类有多复杂?死简单的类可能不值得测试。
      • 课程有多重要?在 ATM 上运行的代码有望经过单元测试。
      • 您对课程的使用方式有多少控制权?

      那么总会有:

      • 项目截止日期是什么时候?
      • 您投入了多少人力来创建测试?
      • 您的要求是具体而详细的,还是课程仍然经常变化?

      至于难的课,不妨阅读一下fuzz testing

      【讨论】:

        【解决方案4】:

        简短的回答是,不,但是当你问“我应该为所有事情都用 X 吗?”时,这适用于编程中的所有事情。

        更长的答案是您至少应该考虑它,您正在这样做。为什么你不能模拟录音课的输入?为什么不让课程绕过麦克风录制以从文件加载音频并将输出转到文件而不是扬声器。测试可以将输出结果与已知的正确结果进行比较。

        有关哲学方面的更多信息,请参阅this

        【讨论】:

          【解决方案5】:

          无法对捕获和重放音频的代码进行单元测试(尽管您可以测试当类未成功绑定到资源时调用捕获方法时是否返回错误)。

          但是,除非您只是将捕获的声音写入磁盘,否则调用捕获和播放类的代码当然可以。

          两条建议:

          • 不要测试编译器(例如 getter 和 setter)
          • 测试所有可能损坏的东西

          【讨论】:

            【解决方案6】:

            便宜的答案:Test everything that could possibly break

            尽管您最终需要了解您编写的测试的商业价值 - 与您付出的任何其他努力、您承诺维护的任何其他代码库没有什么不同。

            【讨论】:

              【解决方案7】:

              我测试大多数东西。

              每当我编写测试时,我也会认为测试是关于如何使用我的代码的文档或说明,供我和其他人在未来阅读。

              虽然我不测试实现。我希望能够在不更改测试的情况下更改实现。

              我已经使用 TDD 可能有一两年了,所以也许我会成熟并停止。不过,到目前为止,我仍在学习并认为我没有编写足够的测试。

              【讨论】:

                【解决方案8】:

                要回答您的具体问题,请使用环回电缆。将扬声器连接到麦克风输入。编写一个渲染到扬声器并从麦克风捕获并验证您播放的相同内容被捕获的测试。我的建议是使用简单的正弦音,以便 FFT 可以告诉您是否捕获了相同的内容。

                对于更一般的问题,答案是肯定的,您应该尽可能对所有内容进行单元测试。这样做会为以后留下遗产,因此可以放心地完成未来的更改。它确保您的代码按预期工作。它还记录了接口的预期用途。最后,它强制更好的编码风格。通常难以进行单元测试的东西也设计得很差。为可测试性而写作意味着为更好的设计而写作。

                【讨论】:

                  【解决方案9】:

                  其他例子:如果你开发一个游戏引擎,你想测试你的阴影和其他功能,但你必须在视觉上确认 - 这是经典的 UnitTest 无法决定的。

                  您的案例:随着您的应用程序变得越来越复杂,每次点击您的 UI 来测试您的所有功能都会变得很痛苦。

                  我会编写一个“交互式测试套件”,其中仅显示您需要测试的功能的各种虚拟对话框(为每个测试用例定制)。关闭对话框后,系统将提示您该行为是否符合预期。但我不确定是否有可用的解决方案可以在这里提供帮助。

                  【讨论】:

                  【解决方案10】:

                  您可能想在我的博客中查看我的系列“测试不可能”,了解如何测试的一些想法。

                  在您的情况下,我建议按照idea of Steve Rowe 编写一个设置扬声器和麦克风的测试,并使用环回电缆测试硬件设置代码以及允许通过扬声器发出数据并读取的 API来自麦克风的数据。

                  这是一个单元测试,但不是自动化的。将其移至不与其他自动测试一起运行的独立测试套件中。如果您想自动化它,请使用正确的配置(加上环回电缆)设置第二台 PC,然后远程运行测试。

                  之后,您确定硬件设置正常,您可以发送和接收音频。这使您可以独立于硬件测试数据处理类。使用模型来模拟扬声器和麦克风。

                  【讨论】:

                  【解决方案11】:

                  我倾向于尽可能多地编写测试。不仅是为了证明某事有效,而且是为了让其他人在以后不可避免地破坏它时清楚地看到它。

                  我有一个只有 1 行长的方法。在我的应用程序的类似地方,我编写了单元测试,但我很着急,我认为它不可能失败。我错了,它不起作用:-)

                  编写单元测试的另一个好处不仅是测试您的代码,而且让以前从未见过您的代码的人可以阅读测试并了解您的代码在特定场景下应该如何工作……比如规范。

                  【讨论】:

                  • 自我发布此答案以来,网站似乎发生了变化。我已经更改了我的回复,感谢您抽出宝贵时间查看我的答案:)
                  【解决方案12】:

                  如果您在设置特定区域的代码进行测试时遇到困难,那么可能值得研究一个模拟框架,例如 jMockEasyMock

                  【讨论】:

                    【解决方案13】:

                    设计测试是一项后天习得的技能——你测试得越多,你就越擅长。有些事情似乎很难测试,但如果您考虑几分钟,您通常会找到方法。

                    测试可能很混乱 - 例如java 程序可以启动解释器,甚至可以启动 shell,例如 bash,然后启动一系列 unix 过滤器,您希望这些过滤器输出相同的二进制文件。不过不用担心 - 测试代码的质量不必像成品中的代码那么高。

                    【讨论】:

                      猜你喜欢
                      • 2014-10-01
                      • 2021-08-08
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-08-07
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多