Java如何编写单元测试(一)

  在机房的时候,老师最重视的就是类之间的设计了,什么高内聚、低耦合等等,当时感觉没有什么用,因为当时才刚开始学,没有敲过几行代码,没有写过几个项目,就算实现功能,能实现了就不错了,当时那还管这个,但是到了一定的阶段之后,发现老师说的这个确实是非常重要的,毕竟我们是靠敲代码吃饭的,虽然当时什么也不太懂,我就感觉老师拿这个很当回事,我就感觉很重要,这就足够了,不一定当时非要学到什么东西。

 我们写过的代码为了保证它不出错,那么该怎么办呢?

 也就是我们要对其进行测试,然后让同事code review,那么如何进行单元测试呢?

(一)什么是单元测试

单元测试的测试对象是类或者函数,用来测试一个类和函数是否都按预期的逻辑执行,这是代码层级的测试。


public class Text {
  private String content;

  public Text(String content) {
    this.content = content;
  }

  /**
   * 将字符串转化成数字,忽略字符串中的首尾空格;
   * 如果字符串中包含除首尾空格之外的非数字字符,则返回null。
   */
  public Integer toNumber() {
    if (content == null || content.isEmpty()) {
      return null;
    }
    //...省略代码实现...
    return null;
  }
}

现在我们要测试Text类中的toNumber()函数的正确性,应该如何编写单元测试?

实际上,写单元测试本身不需要什么高深技术。它更多的是考验程序员思维的缜密程度,看是否设计出覆盖各种正常及异常情况的测试用例,来保证代码在任何预期或非预期的情况下都能正常运行。

为了保证测试的全面性,针对toNumber()函数,我们需要设计下面这样几个测试用例。

(1)如果字符串只包含数字:“123”,toNumber()函数输出对应的整数:123。

  (2) 如果字符串是空或者Null,toNumber()函数返回:null

  (3) 如果字符串包含首尾空格:" 123","123"," 123 ",toNumber()返回对应的整数:123.

(4)如果字符串包含多个首尾空格:" 123 ", toNumber() 返回对应的整数: 123;

 (5) 如果字符串包含非数字字符,"123a4" ,"123 4", toNumber() 返回Null;


public class Assert {
  public static void assertEquals(Integer expectedValue, Integer actualValue) {
    if (actualValue != expectedValue) {
      String message = String.format(
              "Test failed, expected: %d, actual: %d.", expectedValue, actualValue);
      System.out.println(message);
    } else {
      System.out.println("Test succeeded.");
    }
  }

  public static boolean assertNull(Integer actualValue) {
    boolean isNull = actualValue == null;
    if (isNull) {
      System.out.println("Test succeeded.");
    } else {
      System.out.println("Test failed, the value is not null:" + actualValue);
    }
    return isNull;
  }
}

public class TestCaseRunner {
  public static void main(String[] args) {
    System.out.println("Run testToNumber()");
    new TextTest().testToNumber();

    System.out.println("Run testToNumber_nullorEmpty()");
    new TextTest().testToNumber_nullorEmpty();

    System.out.println("Run testToNumber_containsLeadingAndTrailingSpaces()");
    new TextTest().testToNumber_containsLeadingAndTrailingSpaces();

    System.out.println("Run testToNumber_containsMultiLeadingAndTrailingSpaces()");
    new TextTest().testToNumber_containsMultiLeadingAndTrailingSpaces();

    System.out.println("Run testToNumber_containsInvalidCharaters()");
    new TextTest().testToNumber_containsInvalidCharaters();
  }
}

public class TextTest {
  public void testToNumber() {
    Text text = new Text("123");
    Assert.assertEquals(123, text.toNumber());
  }

  public void testToNumber_nullorEmpty() {
    Text text1 = new Text(null);
    Assert.assertNull(text1.toNumber());

    Text text2 = new Text("");
    Assert.assertNull(text2.toNumber());
  }

  public void testToNumber_containsLeadingAndTrailingSpaces() {
    Text text1 = new Text(" 123");
    Assert.assertEquals(123, text1.toNumber());

    Text text2 = new Text("123 ");
    Assert.assertEquals(123, text2.toNumber());

    Text text3 = new Text(" 123 ");
    Assert.assertEquals(123, text3.toNumber());
  }

  public void testToNumber_containsMultiLeadingAndTrailingSpaces() {
    Text text1 = new Text("  123");
    Assert.assertEquals(123, text1.toNumber());

    Text text2 = new Text("123  ");
    Assert.assertEquals(123, text2.toNumber());

    Text text3 = new Text("  123  ");
    Assert.assertEquals(123, text3.toNumber());
  }

  public void testToNumber_containsInvalidCharaters() {
    Text text1 = new Text("123a4");
    Assert.assertNull(text1.toNumber());

    Text text2 = new Text("123 4");
    Assert.assertNull(text2.toNumber());
  }
}

(二)为什么要写单元测试?

单元测试能为重构保驾护航之外,也是保证代码质量最有效的两个手段之一,(另一个是Code Review)。

(1)单元测试能有效的帮我们发现代码中的BUG

(2) 写单元测试能帮我们发现代码设计上的问题

(3)单元测试是对继承测试的有力补充

(4)写单元测试的过程本身就是代码重构的过程

(5)阅读单元测试能够帮助快速熟练代码

(6)单元测试是TDD可落地执行的改进方案

(三)如何编写单元测试?

写单元测试就是针对代码设计覆盖各种输入、异常、边界条件的测试用例,并将这些测试用例翻译成代码的过程。

猜你喜欢

转载自blog.csdn.net/MyxZxd/article/details/113953234