目录
1、 junit 是一个开源的 java 语言的单元测试框架
二、使用@beforecss 和@ afterclass 静态方法(过程)
三、@ before 、@ after 、@ beforeclass 、@ afterclass 使用场景
一、什么是单元测试
- 单元测试是针对最小的功能单元编写测试代码- java 程序最小的功能单元是方法
 - 单元测试就是针对单个 java 方法的测试
 
二、为什么要使用单元测试
1、使用main方法测试的缺点
- 只能有一个 main ()方法,不能把测试代码分离;
 - 没有打印出测试结果和希望结果;
 - 需要一种测试框架,帮我们编写测试。
 
2、单元测试的好处
- 确保单个方法运行正常;
 - 如果修改了代码,只需要确保其对应的单元测试通过。
 - 测试代码本身就可以作为实例代码;
 - 可以自动化运行所有测试并获得报告。
 
三、 junit 单元测试框架介绍
1、 junit 是一个开源的 java 语言的单元测试框架
- 专门针对 java 语言设计,使用广泛;
 - junit 是事实上的标准单元测试框架。
 
2、 junit 的特点
- 使用断言( assertion )测试期望结果;﹣可以方便地组织和运行测试
 - 可以方便地查看测试结果
 - 常用 ide (例如 intellij ldea 、 eclipse )都集成了 junit
 - 可以方便地集成到 maven 。
 
四、junit 设计
- testcase :一个 testcase 表示一个测试。
 - testsuite :一个 testsuite 包含一组 testcase ,表示一组测试。
 - testfixture :一个 testfixture 表示一个测试环境。
 - testresult :用于收集测试结果。
 - testrunner :用于运行测试。
 - testlistener :用于监听测试过程,手机测试数据;
 - assert :用于断言测试结果是否正确。
 
1、assert 断言常用方法:
- 断言相等: assertequals (100, x );
 - 断言数组相等: assertarrayequals ((1,2,3, x );
 - 浮点数断言相等:0 assertequals (3.1416, x , 0.0001);
 - 断言为 nul:assertnull ( x );
 - 断言为 true / false:asserttrue ( x >0 ) / assertfalse ( x < 0 )
 - 其它:assertnotequals / assertnotnull
 
五、使用junit测试方法
1、示例程序
public class demo01 {
       public string sum(string d,int...arg){
              int ss=integer.parseint(d.trim());
              int sum=0;
              for(int i=0;i<arg.length;i++){
                     sum=sum+arg[i];
              }
              return sum+""+ss;
       }
} 
对于以上这个用于测试的程序而言,我们要测试它,最土的方法就是使用main函数,如下图所示:

下面我们讨论一下使用junit进行测试的方法:(使用eclipse)
1、首先要建立一个junit的测试包



2、建立测试项目:

3、选择存放目录和确定文件名

4、选择要进行测试的方法

5、使用断言和更改测试的方法的参数


6、运行结果

7、使用多个@test测试
@test
public void testsum() {
        assertequals("125", new demo01().sum("5", 2,4,6));
        assertequals("127", new demo01().sum("7", 2,4,6));
}
@test
public void test02() {
        assertequals("127", new demo01().sum(" 7", 2,4,6));
} 
8、修改主方法
package com.dw.service
    public class demo01 {
        public string sum(string d, int...arg){
            int ss = integer.parseint(d.trim());
            int sum = 0;
            for(int i = 0; i < arg.length; i++){
                sum = sum + arg[i];
            }
        return sum + "" + ss;
    }
} 
六、总结
- 一个 testcase 包含一组相关的测试方法;
 - 使用断言测试结果(注意浮点数 assertequals 要指定 delta )
 - 每个测试方法必须完全独立;
 - 测试代码必须非常简单;
 - 不能为测试代码再编写测试
 - 测试需要覆盖各种输入条件,特别是边界条件。
 
junit 单元测试实战
一、使用@before和@after
同一个单元测试内的多个测试方法:测试前都需要初始化某些对象,测试后可能需要清理资源; junit 使用@before和@after可以实现,在@before方法中初始化测试资源,在@after方法中释放测试资源。
junit 对每个@test 方法:(执行过程)
- 实例化测试用例;
 - 执行@ before 方法;
 - 执行@ test 方法;
 - 执行@ after 方法。
 
示例代码
import org.junit.after;
import org.junit.before;
import org.junit.test;
public class demotest {
   
    public demotest() {
        system.out.println("demotest对象创建");
    }
    @before
    public void before() {
        system.out.println("beforetest方法执行");
    }
    @test
    public void test01() {
        system.out.println("test01方法执行......");
    }
     @test
     public void test02() {
         system.out.println("test02方法执行......");
    }
     @test
     public void test03() {
         system.out.println("test03方法执行......");
    }
     @after
     public void after() {
         system.out.println("after方法执行......");
     }
} 
运行结果:

我们可以用@before创建对象demo,那么每一次@test的执行都会执行@before下的对象的创建。每一个test都是一个独立的单元,然后再使用@after销毁对象,释放资源。
二、使用@beforecss 和@afterclass 静态方法(过程)
- 在执行所有@test 方法前执行@beforedass 标注的静态方法;
 - 执行所有测试
 - 在执行所有@test 方法后执行@afterclass 静态方法。
 
示例代码
import org.junit.afterclass;
import org.junit.beforeclass;
import org.junit.test;
public class demotest02 {
    public demotest02() {
        system.out.println("demotest对象创建");
    }
    @beforeclass
    public static void beforeclass() {
        system.out.println("beforeclass方法执行");
    }
    @test
    public void test01() {
        system.out.println("test01方法执行......");
    }
    @test
    public void test02() {
        system.out.println("test02方法执行......");
    }
    @test
    public void test03() {
        system.out.println("test03方法执行......");
    }
    @afterclass
    public static void afterclass() {
        system.out.println("afterclass方法执行......");
    }
} 
执行结果:
beforeclass方法执行
demotest对象创建
test01方法执行......
demotest对象创建
test02方法执行......
demotest对象创建
test03方法执行......
afterclass方法执行...... 
在这个结果中,@beforeclass和@afterclass就只执行了一次,且@beforeclass的执行早于@demotest对象创建的执行。类中所有的方法或对象共享。而@beforet和 @after是成员对象所独享的。所有@test都会共享@beforeclass里面的内容。我们可以在@beforeclass中申明一个对象,这个对象可以在各@test中使用。
三、@before 、@after 、@beforeclass 、@afterclass 使用场景
- @before:初始化测试对象;例如: input = new filelnputstream();
 - @after:销毁@ before 创建的测试对象;例如: input .close();
 - @beforeclass:初始化非常耗时的资源,例如:创建数据库。
 - @afterclass:清理@ beforeclass 创建的资源,例如:删除数据库。
 
四、总结
理解 junit 执行测试的生命周期
- @before 用于初始化测试对象,测试对象以实例变量存放;
 - @after 用于清理@ before 创建的对象;
 - @beforeclass 用于初始化耗时资源,以静态变量存放;
 - @afterclass 用于清理@ beforeclass 创建的资源。
 
异常测试
1、对可能抛出的异常进行测试:
异常本身是方法签名的一部分。
public static int parselnt() throws numberformatexception 
测试错误的输入是否导致特定的异常。
integer.parselnt ( null );
integer.parselnt (“”);
integer.parselnt (“ xyz”); 
2、如何测试异常
我们可以通过 try - catch测试,但这样会写出很多这样的语句,从而使其变得复杂起
来;更好的方法就是使用 expected 测试异常,具体操作如下:
@test( expected = numberformatexception.class )
public void testnumberformat (){
     integer . parseint ( null);
    //如果测试过程中抛出了以上异常,则测试通过。
} 
总结
- 测试异常可以使用@test ( expected = exception. class )
 - 对可能发生的每种类型的异常进行测试。
 
示例程序一
public class demo03 {
    public void testnumberformat(string num){
        integer.parseint(num);
    }
   public void testextends() {
       object msg=null;
       system.out.println(msg.tostring());
   }
} 
测试程序二
import static org.junit.jupiter.api.assertions.*;
import org.junit.before;
import org.junit.jupiter.api.test;
import static org.junit.jupiter.api.assertions.*;
import org.junit.before;
import org.junit.jupiter.api.test;
public class demo03test {
    demo03 d2;
    @before
    public void before() {
        d2=new demo03();
    }
    @test( expected = numberformatexception.class )
    public void testtestnumberformat() {
        d2.testnumberformat("abc");
    }
    //如果出现运行通过,表示出现异常。如果输入12,则运行不通过,表示没有出现异常。
    @test( expected = numberformatexception.class )
    public void testtestextends() {
        d2.testextends();
    }
    //空指针异常
} 
 
超时测试
可以为 junit 的单个测试设置超时
超时设置为1秒:@test ( timeout =1000)【 timeout 单位是毫秒】
程序示例一
public class demo04 {
    public int culate() {
        int b=100;
        int sum=0;
        for(int i=1;i<=100;i++) {
            sum=sum+i;
        }
        return sum;
    }
    public int culate02(){
        int b=500;
        int sum=0;
        for(int i=1;i<=100;i++) {
            sum=sum+i;
        }
      try {
          thread.sleep(1000);
      } catch(interruptedexception e) {
          //todd auto-generated catch block
          e.printstacktrace();
      }
      return sum;
  }
} 
测试程序二
import static org.junit.jupiter.api.assertions.*;
import org.junit.before;
import org.junit.jupiter.api.test;
import org.junit.jupiter.api.timeout;
  public class demo04test {
   demo04 d4;
   @before
   public void before() {
       d4=new demo04();
   }
   @test
   @timeout(600)
   public void testculate(){
      d4.culate();
   }
   @test
   @timeout(600)
   public void testculate02() {
      d4.culate02();
   }
} 
参数化测试
1、参数化测试
如果待测试的输入和输出是一组数据,可以把测试数据组织起来,用不同的测试数据调用相同的测试方法。
2、参数化测试要求
- 参数必须有静态方法 data()返回,返回类型为 collection <?> ,静态方法必须标记为
 - @parameters ;
 - 测试类必须标记为:@runwith ( parameterized.class );
 - 构造方法参数必须和测试参数对应。
 
示例程序
@runwith(parameterized.class)/
public class  demo05test{
   @parameters
   public static collection<?> data() {
      return arrays.aslist(new object[][]{{0,0},{1,1}, {-1,1}});
   }
    //这是一种固定的结构,我们要做的就是改变其中的数组的参数值。其它的部分//都不能改变
   int input;
   int expected;
    // 参数必须要对应;
   public demo05test(int input, int expected) {
      this.input = input;
      this.expected = expected;
   }
   @test
   public void test() {
      int r=math.abs(this.input);//绝对值
      assertequals(this.expected, r);
   }
    //对应这三组数据会执行三次
}
                
                    
                
            
                                            
                                            
                                            
                                            
                                            
发表评论