Java Junit 基础笔记

Junit

1. 概念

JUnit是一个Java语言的单元测试框架。
单元测试:单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

2. Junit特性

  • 测试工具
  • 测试套件
  • 测试运行器
  • 测试分类

3. API

注解

序号 注释 描述
1 @Test 依附在Junit的public void方法上,作为一个测试用例。
2 @Before 表示必须在每一个测试之前执行,以便执行测试某些必要的先决条件。
3 @BeforeClass 依附在静态方法上,在类的所有测之前必须执行。一般是测试计算共享配置方法(连接到数据库)。
4 @After 表示在每一个测试后执行,如执行每一个测试后重置或删除某些变量。
5 @AfterClass 在所有测试用例后执行,可用于清理建立方法,如断开数据库连接。和@BeforeClass一样附着的方法必须是静态。
6 @Ignore 当想暂时禁用特定的测试执行的时候可以使用,被注解为@Ignore的方法将不被执行。
  • 代码示例:

    import org.junit.*;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestAnnotation {
    
        //指出这是附着在静态方法必须执行一次并在类的所有测试之前。
        // 发生这种情况时一般是测试计算共享配置方法(如连接到数据库)
        @BeforeClass
        public static void beforeClass(){
            System.out.println("execute beforeClass");
        }
    
        //当需要执行所有的测试在JUnit测试用例类后执行,AfterClass注解可以使用以清理建立方法,
        // (从数据库如断开连接)。注意:附有此批注(类似于BeforeClass)的方法必须定义为静态。
        @AfterClass
        public static void afterClass(){
            System.out.println("execute afterClass");
        }
    
    
        //Before注释表示,该方法必须在类中的每个测试之前执行,以便执行测试某些必要的先决条件。
        @Before
        public void before(){
            System.out.println("execute before");
        }
    
        //After 注释指示,该方法在执行每项测试后执行(如执行每一个测试后重置某些变量,删除临时变量等)
        @After
        public void after(){
            System.out.println("execute after");
        }
    
        //测试注释指示该公共无效方法它所附着可以作为一个测试用例。
        @Test
        public void test(){
            System.out.println("execute test");
        }
    
        @Test
        public void test1(){
            System.out.println("execute test1");
        }
    
        //当想暂时禁用特定的测试执行可以使用忽略注释。每个被注解为@Ignore的方法将不被执行。
        @Ignore
        public void ignoreTest(){
            System.out.println();
        }
    }
    import org.junit.runner.JUnitCore;
    import org.junit.runner.Result;
    import org.junit.runner.notification.Failure;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestRunner2 {
        public static void main(String[] args) {
            Result result= JUnitCore.runClasses(TestAnnotation.class);
            for (Failure failure:result.getFailures()){
                System.out.println(failure.toString());
            }
            System.out.println(result.wasSuccessful());
        }
    }
  • 运行结果:

    execute beforeClass
    execute before
    execute test
    execute after
    execute before
    execute test1
    execute after
    execute afterClass
    true
  • junit的执行过程
    • beforeClass首先执行,只执行一次
    • afterClass最后执行,只执行一次
    • before在每次测试之前执行
    • after在每次测试之后执行
    • 每个test在after和before之间执行

断言

序号 方法 描述
1 assertEquals(boolean expected, boolean actual) 检查两个变量或者等式是否平衡
2 assertTrue(boolean expected, boolean actual) 检查条件是否为真
3 assertFalse(boolean condition) 检查条件是否为假
4 assertNotNull(Object object) 检查变量是否不为空
5 assertNull(Object object) 检查变量是否为空
6 assertSame(Object expected, Object actual) 检查两个引用是否指向同一个对象
7 assertNotSame(Object expected, Object actual) 检查两个引用是否不指向同一个对象
8 assertArrayEquals(expectedArray, resultArray) 检查两个数组是否相等
  • 代码示例

    import org.junit.Test;
    
    import static org.junit.Assert.*;
    
    public class TestAssertions {
    
        @Test
        public void testAssertions(){
            String str1=new String("abc");
            String str2=new String("abc");
            String str3=null;
            String str4="abc";
            String str5="abc";
            int val1=5;
            int val2=6;
            String[] expectedArray={"one","two","three"};
            String[] resultArray={"one","two","three"};
    
            assertEquals(str1,str2);
    
            assertTrue(val1<val2);
    
            assertFalse(val1>val2);
    
            assertNotNull(str1);
    
            assertNull(str3);
    
            assertSame(str4,str5);
    
            assertNotSame(str1,str3);
    
            assertArrayEquals(expectedArray,resultArray);
    
        }
    }

4. 执行测试

测试用例通过JUnitCore类来执行,它是Junit运行测试的外观类。对于只有一次的测试运行,可以使用静态方法:runClasses(Class[])

5. 套件测试

意思就是捆绑几个单元测试用例并一起执行。@RunWith@Suite可一起用于运行套件测试

  • 代码示例

    /**
    * Created by Administrator on 2017/11/1 0001.
    * 被测试类
    */
    public class MessageUtil {
    
        private String message;
    
        public MessageUtil(String message){
            this.message=message;
        }
    
        public String printMessage(){
            System.out.println(message);
            return message;
        }
    
        public String salutationMessage(){
            message="Hi!"+message;
            System.out.println(message);
            return message;
        }
    }
    
    import org.junit.Assert;
    import org.junit.Test;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestJunit {
    
        String message="Robert";
        MessageUtil messageUtil=new MessageUtil(message);
    
        @Test
        public void testPrintMessage(){
    //        message="New Word";
            System.out.println("Inside testPrintMessage()");
            Assert.assertEquals(message,messageUtil.printMessage());
        }
    }
    import org.junit.Assert;
    import org.junit.Test;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestJunit1 {
    
        String message = "Robert";
        MessageUtil messageUtil=new MessageUtil(message);
    
        @Test
        public void testSalutationMessage(){
            System.out.println("Inside testSalutationMessage()");
            message="Hi!"+"Robert";
            Assert.assertEquals(message,messageUtil.salutationMessage());
        }
    }

测试执行类:

```
    import org.junit.runner.JUnitCore;
    import org.junit.runner.Result;
    import org.junit.runner.notification.Failure;

    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestRunner2 {
        public static void main(String[] args) {
            Result result= JUnitCore.runClasses(JunitTestSuite.class);
            for (Failure failure:result.getFailures()){
                System.out.println(failure.toString());
            }
            System.out.println(result.wasSuccessful());
        }
    }
```
  • 运行结果
    Inside testPrintMessage() Robert Inside testSalutationMessage() Hi!Robert true

6. 忽略测试

  • 一个含有@Ignore 注释的测试方法不会被执行
  • 如果一个测试类有@Ignore注释,则它的测试方法将不会被执行

7. 时间测试

  • timeout参数与@Test注释一起使用,当一个测试用例比指定毫秒数花费更多时间,那么Junit将会自动将它标记为失败。
  • 代码示例:

    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class MessageUtil {
    
        private String message;
    
        public MessageUtil(String message){
            this.message=message;
        }
    
        public void printMessage(){
            System.out.println(message);
            while (true);
        }
    
        public String salutationMessage(){
            message="Hi!"+message;
            System.out.println(message);
            return message;
        }
    }
    
    import org.junit.Assert;
    import org.junit.Test;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestJunit4 {
    
        String message = "Robert";
        MessageUtil messageUtil=new MessageUtil(message);
    
    
        @Test(timeout = 1000)
        public void testPrintMessage(){
            System.out.println("Inside testPrintMessage");
            messageUtil.printMessage();
        }
    
        @Test
        public void testSalutationMessage(){
            System.out.println("Inside testSalutationMessage");
            message="Hi!"+"Robert";
            Assert.assertEquals(message,messageUtil.salutationMessage());
        }
    }
    import org.junit.runner.JUnitCore;
    import org.junit.runner.Result;
    import org.junit.runner.notification.Failure;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestRunner2 {
        public static void main(String[] args) {
            Result result= JUnitCore.runClasses(TestJunit4.class);
            for (Failure failure:result.getFailures()){
                System.out.println(failure.toString());
            }
            System.out.println(result.wasSuccessful());
        }
    }
    
  • 运行结果

    Inside testSalutationMessage
    Hi!Robert
    Inside testPrintMessage
    Robert
    testPrintMessage(TestJunit4): test timed out after 1000 milliseconds
    false

8. 异常测试

  • expected参数与@Test注释一起使用,可以测试代码是否抛出你想要得到的异常。

  • 代码示例

    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class MessageUtil {
    
        private String message;
    
        public MessageUtil(String message){
            this.message=message;
        }
    
        public void printMessage(){
            System.out.println(message);
    //        return message;
    //        while (true);
            int a=0;
            int b=1/a;
        }
    
        public String salutationMessage(){
            message="Hi!"+message;
            System.out.println(message);
            return message;
        }
    }
    import org.junit.Assert;
    import org.junit.Test;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestJunit5 {
    
        String message = "Robert";
        MessageUtil messageUtil=new MessageUtil(message);
    
        @Test(expected = ArithmeticException.class)
        public void testPrintMessage(){
            System.out.println("Inside testPrintMessage");
            messageUtil.printMessage();
        }
    
        @Test
        public void testSalutationMessage(){
            System.out.println("Inside testSalutationMessage");
            message="Hi!"+"Robert";
            Assert.assertEquals(message,messageUtil.salutationMessage());
        }
    }
  • 运行结果
    Inside testSalutationMessage Hi!Robert Inside testPrintMessage Robert true

9. 参数化测试

  • 参数化测试允许开发人员使用不同的值反复运行同一个测试用例。
    • @RunWith(Parameterized.class)来注释test类
    • 创建一个由@Parameterized.Parameters注释的公共静态方法,返回一个对象的集合(数组)来作为测试数据集合。
    • 创建一个公共构造函数,用来接收和存储测试数据。
    • 用例会反复运行,为每一组测试数据创建一个实例变量
    • 用实例变量作为测试数据的来源来创建你的测试用例
  • 代码示例
    判断是不是素数:

    public class PrimeNumberChecker {
    
        public Boolean validate(final Integer primeNumber){
            for (int i = 2; i < (primeNumber / 2); i++) {
                if (primeNumber%i==0){
                    return false;
                }
            }
            return true;
        }
    }
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.Parameterized;
    
    import java.util.Arrays;
    import java.util.Collection;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    
    @RunWith(Parameterized.class)
    public class PrimeNumberCheckerTest {
    
        private Integer inputNumber;
        private Boolean expectedResult;
        private PrimeNumberChecker primeNumberChecker;
    
        @Before
        public void initialize(){
            System.out.println("initialize");
            primeNumberChecker=new PrimeNumberChecker();
        }
    
        public PrimeNumberCheckerTest(Integer inputNumber,Boolean expectedResult){
            System.out.println("construct");
            this.inputNumber=inputNumber;
            this.expectedResult=expectedResult;
        }
    
        @Parameterized.Parameters
        public static Collection primeNumbers(){
            return Arrays.asList(new Object[][]{
                    {2,true},
                    {6,true},
                    {19,true},
                    {22,true},
                    {23,true}
            });
        }
    
        @Test
        public void testPrimeNumberChecker(){
            System.out.println("test");
            System.out.println("Parameterized Number is : " + inputNumber);
            Assert.assertEquals(expectedResult,
                    primeNumberChecker.validate(inputNumber));
        }
    }
    
    import org.junit.runner.JUnitCore;
    import org.junit.runner.Result;
    import org.junit.runner.notification.Failure;
    
    /**
    * Created by Administrator on 2017/11/1 0001.
    */
    public class TestRunner2 {
        public static void main(String[] args) {
            Result result= JUnitCore.runClasses(PrimeNumberCheckerTest.class);
            for (Failure failure:result.getFailures()){
                System.out.println(failure.toString());
            }
            System.out.println(result.wasSuccessful());
        }
    }
    
  • 运行结果

    construct
    initialize
    test
    Parameterized Number is : 2
    construct
    initialize
    test
    Parameterized Number is : 6
    construct
    initialize
    test
    Parameterized Number is : 19
    construct
    initialize
    test
    Parameterized Number is : 22
    construct
    initialize
    test
    Parameterized Number is : 23
    testPrimeNumberChecker[1](PrimeNumberCheckerTest): expected:<true> but was:<false>
    testPrimeNumberChecker[3](PrimeNumberCheckerTest): expected:<true> but was:<false>
    false
posted @ 2018-01-22 09:56 戎码之路 阅读(...) 评论(...) 编辑 收藏