单元测试又称模块测试,是对最小单元的程序模块进行正确性检测。
单元测试本身可以提高代码质量,不过要不要做单元测试,需要从功能的复杂度和功能性质来考虑。
(1)编写的工具类不建议在主程序中出现test的方法,所以可以采用单元测试,这样不会打包到主程序中。
(2)根据功能复杂度考虑单元测试,复杂的功能尽量拆到最小单元,不要让单元测试加重编码负担。
java主要用jUnit单元测试,后面记录下jUnit的使用。
maven引入junit包
junit junit 自己找一个版本 test
Assert.assertFalse("连接失败!",Objects.isNull(db));
Assert.assertEquals("匹配失败!",2,3);
测试用例是使用 JUnitCore 类来执行的,每个单元测试类都可以作为测试用例。
JUnitCore 是运行测试的外观类,可通过循环打印错误信息。
public class TestRunner {public static void main(String[] args) {Result result = JUnitCore.runClasses(TestJunit.class);for (Failure failure : result.getFailures()) {System.out.println(failure.toString());}System.out.println(result.wasSuccessful());}
}
测试样例定义了运行多重测试的固定格式。例如:
public class DBTestCase extends TestCase {public void test(){int i =this.countTestCases();String name=this.getName();}
}
TestResult收集所有执行测试案例的结果,是收集参数层面的一个实例。它区分失败和错误,失败是可以预料的并且可以通过假设来检查,错误是不可预料的问题比如异常。
public class DBTestResult extends TestResult {public synchronized void addError(Test test, Throwable t) {super.addError((junit.framework.Test) test, t);}
}
可以运行很多测试用例。
public static void main(String[] args) {//测试套件TestSuite suite = new TestSuite(DbTest.class, DBTestCase.class, DBTestResult.class );TestResult testResult = new TestResult();suite.run(testResult);System.out.println("测试数量 = " + testResult.runCount());}
测试套件的类
@RunWith(Suite.class)
@Suite.SuiteClasses({ DbTest.class, DemoTest.class })
public class AllTest {//此处不写代码,写了也不会执行
}
@Ignore这个注解可以忽略测试,可放到类上也可以放到方法上。
@Test(timeout=1000)给测试方法添加了暂停时间,超时会测试停止,并不通过。
@Test(expected = XxxxxException.class)为追踪异常的选项,可以测试代码是否它抛出了想要得到的异常。
参数化测试允许开发人员使用不同的值反复运行同一个测试。直接附上官方的代码吧,例子是将预设的参数数据和validate方法进行断言判断是否正确。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;@RunWith(Parameterized.class)
public class ParameterTest {private Integer inputNumber;private Boolean expectedResult;// Each parameter should be placed as an argument here// Every time runner triggers, it will pass the arguments// from parameters we defined in primeNumbers() methodpublic ParameterTest(Integer inputNumber,Boolean expectedResult) {this.inputNumber = inputNumber;this.expectedResult = expectedResult;}@Parameterized.Parameterspublic static Collection primeNumbers() {return Arrays.asList(new Object[][] {{ 2, true },{ 6, false },{ 19, true },{ 22, false },{ 23, true }});}// This test will run 4 times since we have 5 parameters defined@Testpublic void testPrimeNumberChecker() {System.out.println("Parameterized Number is : " + inputNumber);assertEquals(expectedResult,validate(inputNumber));}public Boolean validate(final Integer primeNumber) {for (int i = 2; i < (primeNumber / 2); i++) {if (primeNumber % i == 0) {return false;}}return true;}
}
jUnit执行完主程序会自动结束,就一起将子线程也断掉了。解决这种情况需要用到计数器CountDownLatch。
@Testpublic void testThread() throws InterruptedException {TestClass testClass = new TestClass();//同步计数器int count = 20;CountDownLatch countDownLatch = new CountDownLatch(count);for (int i = 1; i <= count; i++) {new Thread(() -> {//业务处理testClass.write(path, "writeString");countDownLatch.countDown();}).start();}countDownLatch.await();}
由于junit不会将数据真是存入数据库,想要真实入库需要自己加commit提交。
图中图标可去掉test。
光标放到类名上,alt+enter,选择create test,即可在test目录下得到测试类。