【问题标题】:What is the "right" way to test the output of Java methods?测试 Java 方法输出的“正确”方法是什么?
【发布时间】:2009-03-19 16:45:19
【问题描述】:

在 Python 中,我经常有如下所示的测试:

tests = [
    (2, 4),
    (3, 9),
    (10, 100),
]
for (input, expected_output) in tests:
    assert f(input) == expected_output

在 Java 中使用 JUnit 编写这样的测试(其中指定一组测试用例,然后循环运行每个测试用例)的“正确”方法是什么?

谢谢!

先发制人的反应:我意识到我可以做这样的事情:

assertEquals(4, f(2))
assertEquals(9, f(3))
....

但是...我希望有更好的方法。

【问题讨论】:

  • 有了这么简单的例子,我认为Java方式是更好的方式。
  • 是的,有这么一个简单的例子,但这只是一个例子。我相信您可以想象这样一种情况,您需要进行几行设置,进行函数调用,然后对结果进行几次检查。

标签: java unit-testing testing junit


【解决方案1】:

同样的事情。

    int[][] tests = {
            {2, 4},
            {3, 9},
            {10, 100}
    };
    for (int[] test : tests) {
        assertEquals(test[1], f(test[0]));
    }

当然不如 python 漂亮,但很少有东西漂亮。

您可能还想研究JUnit Theories,这是一个未来的功能......

【讨论】:

  • 完美。小问题:使用 List 而不是数组更像 Java。
  • 最肯定的是,但是,如果我们正在与 Python 的追随者交谈,则会破坏 List a = new ArrayList(); a.add(); a.add(); a.add();他们的眼睛会流血!
  • 我不明白为什么在这种情况下 List 比数组更好。
  • 我一直在使用这个......但是当你有很多类型时它开始崩溃:如果'f'接受一个字符串怎么办?
  • 你只需要使用一个二维字符串数组。这与 python 示例完全相同。唯一的区别是初始类型声明、for 循环语法、{} 和 ;。
【解决方案2】:

正确的方法是编写单独的断言语句,即使你不喜欢它。

它避免了不必要的复杂性,当它失败时,有时更容易看到哪个值失败(无需启动调试器)。

但是,如果您自动生成测试数据,那就另当别论了。

【讨论】:

  • :( 这不是很高兴。如果您需要进行几行设置会发生什么?那么您创建一个新方法...但是现在每个测试都需要两个方法而不是一个.. . 而且... Java 让我很难过 :(
  • 如果设置相同,我将使用 JUnit 设置方法。如果不同,我会用 setup 和 assert 编写一个私有方法并多次调用它。
【解决方案3】:

看看 Junit 中的参数化测试运行器。

http://junit.org/apidocs/org/junit/runners/Parameterized.html

看起来它会完全满足您的需求。

【讨论】:

  • 太棒了——这看起来就像我想要的。我会玩它看看。
  • 我玩过它一次,但是对于我来说,提供更多指导而不是指向 javadoc 的链接已经太久了。
【解决方案4】:

嗯...

int[][] tests = new int[][]{
        {2, 4},
        {3, 9},
        {10, 100},
    };

for(int[] i : tests)
{
    assertEquals(i[1], f(i[0]);
}

同样的事情,真的。唯一的问题是 Java 缺少元组字面量,因此对于更复杂的情况,您必须使用 Object[] 数组和强制转换,或者编写一个元组类。

【讨论】:

  • 正如你所提到的,你必须使用 Object[] 数组并稍后进行强制转换......这并不好玩......但看起来没有“好”的方法。哦,好吧。
【解决方案5】:

难道你不应该只定义一个包含两个字段的简单类,即真实结果和预期结果,然后以类似于 Python sn-p 正在执行的方式遍历集合吗?

【讨论】:

  • 我考虑过...我最初认为创建所有需要的类有点愚蠢...但这也许只是表明我缺乏经验Java。
【解决方案6】:

Java 中没有元组,但您可以使用 Map 或两个并行数组来指定输入/输出对,然后像 Python 示例一样执行循环。

【讨论】:

    【解决方案7】:

    绝对不是单元测试方面的专家,但我更愿意为我正在测试的每个案例使用单独的方法,并使用一些测试运行工具(如 NUnit-GUI,用于 C#)。这样我就可以确切地知道哪种情况会失败,如果确实如此。它还有更多的工作要做,但我认为它最终会得到很好的回报。

    【讨论】:

    • 我倾向于同意,但是如果你参数化你的失败消息,你可以得到这个信息。
    • 这很快就变得很荒谬了……假设你有三个实用函数:对于每一个你应该测试至少三个案例(零案例,一个案例,许多案例)。突然之间,您需要九种方法,而每种方法无疑都会重复代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    相关资源
    最近更新 更多