不要在单元测试中使用非测试常量

每个开发人员都希望促进代码重用。 通常,重用是一件好事。 它使代码更易于维护且更正确。

但是,有一个地方不应发生重用,而这又跨越了生产和测试代码之间的界限。 常量就是一个很好的例子。 让我举一个具体的例子来解释我的意思。

假设您的应用程序中有此FizzBu​​zz代码,FizzBu​​zz.java文件:

String[] generate(int start, int end) {
        String[] result = new String[end - start + 1];
        for (int x = 0, number = start; number <= end; x++, number++) {
            if (number % 15 == 0) {
                result[x] = "FizzBuzz";
            } else if (number % 3 == 0) {
                result[x] = "Fizz";
            } else if (number % 5 == 0) {
                result[x] = "Buzz";
            } else {
                result[x] = String.valueOf(number);
            }
        }
        return result;
    }

然后,您在其中编写了一些基本的单元测试,例如FizzBu​​zzTest.java文件:

@Test
    void fizzTest() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        String[] result = fizzBuzz.generate(3, 3);
        assertEquals("Fizz", result[0]);
    }

    @Test
    void buzzTest() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        String[] result = fizzBuzz.generate(5, 5);
        assertEquals("Buzz", result[0]);
    }

    @Test
    void fizzBuzzTest() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        String[] result = fizzBuzz.generate(15, 15);
        assertEquals("FizzBuzz", result[0]);
    }

一些开发人员很想将解决方案重构为常量FizzBu​​zz.java然后它也会显示在测试中:

public class FizzBuzz {
    public static final String FIZZ = "Fizz";
    public static final String BUZZ = "Buzz";

    String[] generate(int start, int end) {
        String[] result = new String[end - start + 1];
        for (int x = 0, number = start; number <= end; x++, number++) {
            if (number % 15 == 0) {
                result[x] = FIZZ + BUZZ;
            } else if (number % 3 == 0) {
                result[x] = FIZZ;
            } else if (number % 5 == 0) {
                result[x] = BUZZ;
            } else {
                result[x] = String.valueOf(number);
            }
        }
        return result;
    }

而在FizzBu​​zzTest.java:

@Test
    void fizzTest() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        String[] result = fizzBuzz.generate(3, 3);
        assertEquals(FIZZ, result[0]);
    }

    @Test
    void buzzTest() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        String[] result = fizzBuzz.generate(5, 5);
        assertEquals(BUZZ, result[0]);
    }

    @Test
    void fizzBuzzTest() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        String[] result = fizzBuzz.generate(15, 15);
        assertEquals(FIZZ + BUZZ, result[0]);
    }

Reasons not to do this

为什么不应该这样做有两个关键原因。

Tests change when production code changes

不这样做的一个原因是,这会导致一种情况,当重构生产代码时,不必要地将测试重构。 考虑一下如果您进行IDE重构以重命名常量会发生什么情况模糊或将其移至另一堂课。 您还将看到重构会自动触摸测试代码。 这可能令人不安,因为它对测试是否仍然准确提出了疑问。

理想的测试代码是在重构生产代码时不会更改的代码,并且测试不断通过。 这告诉您您的重构是100%安全的。 通常,您不必更改测试代码即可更改生产代码,如果这样做,则应该是因为功能其实是变化。 不幸的是,通过引用生产中的常量的测试,由于将它们耦合在一起,因此无法获得保证。

Tests will pass when the code is wrong

更重要的是,引用生产常量的测试可能会导致以下情况:代码实际上是错误的,但是单元测试还是通过了。

考虑“ Fizz”拼写错误或什至值错误的情况,因为这里的值嗡嗡声:

public class FizzBuzz {
    public static final String FIZZ = "Buzz";

    // . . .

单元测试仍将通过,因为测试针对的是相同的错误嘶嘶声生产代码引用的变量。

在实际的生产代码中,这确实是可怕的和致命的杀伤力,其中常量的值通常与系统进行的某些外部交互有关。 例如,Web服务调用上的查询参数或从前端收到的表单字段的名称。

Unit testing should always be the software equivalent to double-entry bookkeeping. This means that unit tests are meant to repeat values as a way to provide a second point-of-view on the correctness of a given piece of code. The unit test should check for the literal String value "Fizz" even if the production code uses a constant. This guarantees that the literal value expected from the constant is maintained.

Conclusion

由于这些原因,我得出结论,测试代码不应在生产代码中引用常量。 希望能帮助到你。

from: https://dev.to//scottshipp/don-t-use-non-test-constants-in-unit-tests-3ej0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值