【问题标题】:Random strings with given length unit testing具有给定长度单元测试的随机字符串
【发布时间】:2015-08-16 19:21:01
【问题描述】:

我有一个生成伪随机数的程序(只允许小写、大写和数字)。

/**
 * 
 * @return - returns a random digit (from 0 to 9)
 * 
 */
int randomDigits() {

    return (int) (Math.random() * 10);
}

/**
 * 
 * @return - returns a random lowercase (from "a" to "z")
 */
char randomLowerCase() {

    return (char) ('a' + Math.random() * 26);
}

/**
 * 
 * @return - returns a random uppercase (from "A" to "Z")
 */
char randomUpperCase() {

    return (char) ('A' + Math.random() * 26);
}

/**
 * 
 * @return - returns a random number between 1 and 3.
 * 
 */
char randomChoice() {

    return (char) ((char) (Math.random() * 3) + 1);
}

/**
 * 
 * @param length
 *            - the length of the random string.
 * @return - returns a combined random string. All elements are builder side
 *         by side.
 * 
 *         We use the randomChoice method to get randomly upper, lower and
 *         digits.
 */
public String stringBuilder(int length) {
    StringBuilder result = new StringBuilder();
    int len = length;

    for (int i = 0; i < len; i++) {
        int ch = randomChoice();
        if (ch == 1) {
            result.append(randomDigits());
        }
        if (ch == 2) {
            result.append(randomLowerCase());
        }
        if (ch == 3) {
            result.append(randomUpperCase());

        }
    }
    return result.toString();

}

我怎样才能对该代码进行测试。我尝试测试数字的范围(从 0 到 9)

    int minRange = 0;
    int maxRange = 0;

    for (int i = 0; i < 100000; i++) {
        int result = item.randomDigits();
        if (result == 52) {
            minRange++;

        } else {
            if (result == 19) {
                maxRange++;

            }
        }
    }
    LOGGER.info("The min range in the digit is 0, and in the test appeared: {}", minRange);
    LOGGER.info("The max range in the digit is 9, and in the test appeared: {}", maxRange);

但我找不到如何测试下层或上层?

【问题讨论】:

  • 尝试随机字符串它不是很有用,这是程序的目标?
  • RandomStrings item = new RandomStrings();
  • 所以看起来 minRange 正在尝试计算 0 的出现次数,而 maxRange 正在尝试计算 9 的出现次数。但是,您正在检查 52 ( != 0 ) 和 19 (!= 9)。那么你真正想要测试的是什么?
  • 你看过stackoverflow.com/questions/363681/…吗?您的问题与这些答案无济于事有何不同?
  • 需要自己写吗?我总是只使用 Commons Lang RandomStringUtils。

标签: java math testing random


【解决方案1】:

使用任何随机性的测试代码都很棘手。您可以采取两种方法:

  1. 您的测试可以有足够的迭代次数,从而很有可能显示逻辑中的任何错误。对于许多情况,迭代 1000 或 1000000 次并检查答案的一致性是合理的。如果您还希望检查某个范围内的某些必需分布,这是您唯一的选择。

这可能看起来像:

for (int i = 0; i < 1000000; i++)
    assertTrue(isValid(new RandomVal()));

如果您想检查所有角色是否至少出现一次:

assertEquals(26 * 2 + 9, IntStream.range(0, 1000000)
    .mapToObj(n -> stringBuilder(6))
    .flatMap(String::chars)
    .collect(Collectors.toSet())
    .size());

这使用 Java 8 并且基本上将每个字符(作为整数)添加到集合中,然后检查它的大小。

  1. 使用模拟框架(例如Mockito)检查结果是预期的结果,无论您使用什么来生成随机性的特定输出。这是测试您是否获得正确结果边界条件(即生成器在其范围的每一端返回结果)的最佳方法。

这可能看起来像:

Random mockRandom = mock(Random.class);
when(mockRandom.nextFloat()).thenReturn(0.0f);
assertTrue(isValid(new RandomVal(mockRandom));
when(mockRandom.nextFloat()).thenReturn(1.0f - Float.MIN_VALUE);
assertTrue(isValid(new RandomVal(mockRandom));

为了完整性,这两个都值得做。

【讨论】:

  • 我没有得到模拟/我是测试中的新手等等/但是如何测试字符/大小写/或如何测试随机字符串/asd2Ad/
  • @P.Peev 我将添加一个范围测试示例
【解决方案2】:

如果我理解您的问题解决方法很简单

    int minRange =  999999; //improbable big value
    int maxRange = -999999; //improbable low value

    for (int i = 0; i < 100000; i++) {
        int result = item.randomDigits();
        minRange = Math.min(result, minRange);
        maxRange = Math.max(result, maxRange);
    }

请试一试。 如果你不喜欢数学库,当然可以不用它

    for (int i = 0; i < 100000; i++) {
        int result = item.randomDigits();
        if (result < minRange) {
            minRange = result;
        }
        if (result > maxRange) {
            maxRange = result;
        }
    }

【讨论】:

  • 甚至没有接近解决问题。您正在捕获找到的最低和最高值。 OP 正在尝试计算 0 和 9。
  • 在那个测试中我试图看到它达到最大和最小范围的那些(52 和 9 是为了使测试失败但它没有)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 2012-02-13
  • 2018-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多