【问题标题】:How do I create a Unit test in Java?如何在 Java 中创建单元测试?
【发布时间】:2021-02-24 23:08:19
【问题描述】:

我有一个 java 类,它接受一个数字数组和一个相应概率数组,并充当随机数生成器,根据另一个数组中定义的相应概率从数组中返回一个数字。如何编写最少但有效的单元测试集?

class RandomGen {

    private int[] randomNums;
    private float[] probabilities;
    private float[] total_prob;

    RandomGen(int[] randomNums, float[] probabilites) throws Exception {
        if (this.set_arrays(randomNums, probabilites));
        else {
            throw new Exception("Invalid array format");
        }
    }

    private boolean set_arrays(int[] randomNums, float[] probabilities) {
        if (check_arrays(randomNums, probabilities)) {
            this.randomNums = randomNums;
            this.probabilities = probabilities;
            this.total_prob = new float[this.probabilities.length];

            total_prob[0] = probabilities[0];
            for (int i = 1; i < probabilities.length; i++){
                total_prob[i] = total_prob[i-1] + probabilities[i];
            }
            return true;
        }
        return false;
    }

    public int[] return_randomNums() {
        return this.randomNums;
    }

    public float[] return_probabilites() {
        return this.probabilities;
    }

    private boolean check_arrays(int[] randomNums, float[] probabilities) {
        float total_prob = 0;
        for (int i = 0; i < probabilities.length; i++) {
            if (probabilities[i] < 0) return false;
            total_prob += probabilities[i];
        }
        if (randomNums.length != probabilities.length || total_prob != 1) return false;
        return true;
    }

    public int nextNum() {
        float random = (float) Math.random();
        if (random <= total_prob[0]) {
            return randomNums[0];
        }
        for (int i=1; i < total_prob.length; i++) {
            if (total_prob[i-1] < random  && random <= total_prob[i]) return randomNums[i];
        }
        return 0;
    }
}

【问题讨论】:

  • 这是一个很奇怪的类。不应该只是一种方法吗?
  • 出于 OOP 的原因,我的任务是为这个随机数生成器创建一个类,我正在尝试为此进行单元测试。
  • 不清楚创建单元测试有什么问题。如果您认为仅仅因为您使用的是 Math.random(),那么将很难重现测试,只需更改为 new java.util.Random(seed) 并使用相同的种子进行测试。否则,您必须说明实施单元测试时遇到的问题。
  • 我的问题很笼统。我之前没有对我的任何代码进行单元测试,所以我只是想问一下如何处理这个任务

标签: java unit-testing class testing


【解决方案1】:

对于学习单元测试,这个类可能有点太复杂了。我们也可以在这里只触及表面,因为这不是你可以从几个例子中学到的东西。我敦促你买一本关于这个主题的书。

但既然我们已经在这里了,让我们看看你的班级。

您的类的公共接口由构造函数nextNum() 和两个getter 组成(只返回字段的方法称为getter,因为它们通常命名为getFieldName(),例如getRandomNums())。

getter 不包含任何逻辑。因此,我会避免测试它们。

您的构造函数实际上做了很多工作。首先,它检查数组是否有效(长度相同且概率加起来为 1),然后存储数组并使用累积概率构建一个新数组。为了对其进行测试,每个测试用例将创建一个新的RandomGen 实例,其中包含不同的数组构成不同的情况。显而易见的三种情况是:

  • 概率加起来为 1,但两个数组的长度不同
  • 两个数组的长度相同,但概率数组元素的和不等于 1
  • 两个数组长度相同,概率加起来为一

前两种情况是错误情况,预计会引发异常,最后一种情况是“阳光情况”,您可以在其中检查您的 getter 现在是否返回了两个数组。累积概率(total_prob)只能使用nextNum()观察。

然后是nextNum() 方法。这已经有点高级了,因为你无法预测Math.random() 的结果。可能的解决方案是使用预定义的种子(正如 Victor Polo De Gyves Montero 建议的那样)或包装和注入 Math.random()。在你的情况下,我会跳过它,先读一本书并获得一些单元测试经验。

【讨论】:

  • 谢谢!这真的很有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多