目录

JUnit单元测试

用JUnit进行单元测试

修改配置

举例1

举例2

实验内容

实验结果(个人)

案例一(HelloWorld类测试)

案例二(Calculate类测试)

测试BankAccount类


JUnit单元测试

 JUnithttp://www.junit.orgxUnit便织和运行Java序的单元测试。JUnit源代码是公开的,并具有很强的扩展性,可以进行二次开发,方便地对JUnit进行扩展。JUnit具有如下特点。

  1. 可以使测试代码与产品代码分开,这更有利于代码的打包发布和测试代码的管理。
  2. 对某个类写的试代,以较少改动便可以应用到另个类的测试JUnit      了一个编写测试类的框架,使测试代码的编写更加方便。

易于集成到程序构建的过程中,JUnitAnt的结合还可以实施增量开发。

JUnit 6 junit.awtuijunit.swinguijunit.textuijunit.extensionsjunit.frameworkjunit.runner3个包中包含了JUnit运行时的入口程序以及运行结果显示界面,junit.extensions是扩展包,而junit.frameworkjunit.runner是核心包,分别负责整个测试对象的构建、测试驱动和运行。

         JUnit7个核心类,分别是TestSuiteTestCaseTestResultTestRunnerTestTestListener接口和Assert(断言)类,其关系如图所示。

      Assert用来验证条件是否成立,当条件成立时,assert法保持沉默(测试通过),若条件不成立时就抛出异常。该类所提供的核心方法,主要有assertTrueassertFalse assertEqualsassertNotNullassertNullassertSameassertNotSame等。

      Test接口是单独的测试用例、聚合的测试模式以及测试扩展的共同接口,用来实施测试和收集测试的结果,Test接口采用了Composite设计模式。

      TestCase 类用来义测试的固方法,TestCase Test 的抽象现,由TestCase是一个抽象类,因此不能被实例化,只能被继承。其构造方法可以根据输入的测试名称来创建一个测试用例,设定测试名称的目的在于方便测试失败时查找失败的测

试用例。

      TestSuite是由几个TestCase或其他的TestSuite构成的,从而构成一个树形结构的测试 任务。每个测试任务都由一个或若干个TestSuite来构成。被加入到TestSuite中的测试 在一个线程上依次被执行。

      TestResultTestCase所执行结果,它结果分类分为客户可预测的错误      没有预测的错误,它还将测试结果转发到TestListener处理。

      TestRunner是客户对象调用的起点,负责跟踪整个测试过程,能够显示测试结果,并且 报告测试的进度。

      TestListenter包含4种方法——addError()adaddFailuer()startTest()endTest()。它是  对测试结果的处理和对测试驱动过程的工作特征进行提取。

用JUnit进行单元测试

        下面介绍一下如何在IDEA 2020.1.2JUnit工具完成单元测试。

IDEAJUnitjar包(hamcrest-core-1.3.jarjunit.jarjunit-4.12.jar):于安装目录下的lib内。即:IntelliJ IDEA 2020.1.2\lib
         IDEA自带一个JUnit插件, 该插件可以运行JUnit测试文件,但无法自动生成JUnit测试代码. 如果需要自动生成测试代码,需要安装JUnitGenerator V2.0插件。

         File-->settings-->Plguins-->Browse repositories--> JUnit--> JUnit Generator V2.0安装,安装好后重启 IDEA,即可使用。

PS: IDEAJUnitJUnitGeneratorV2.0若只勾JUnit能导致无法自动生成测试文件,若只勾选JUnitGenerator V2.0可能导致生成的测试文件无法运行。

改配

         1.成的代码java同一maven标准不匹配。

修改方法:

        ${SOURCEPATH}/test/${PACKAGE}/${FILENAME}

        修改为

         ${SOURCEPATH}/../test/java/${PACKAGE}/${FILENAME}
         候会出现个提general/merge/exixt general 就行。

        ${SOURCEPATH}原类的路径,就是你自己写的类;${PACKAGE}原类的包名,java包命名规范就是按照包名一级一级创建的文件夹;${filename}测试类的类名。

        2.修改 Junit4 选项卡中包的申明,把默认的 test 前缀去掉。

         3.生成的测试文件@since位置Date存在乱码,可配置JUnit模板更改日期格式,不影响程序可直接忽略。

修改方法:

        第40行:

        @since <pre>$date</pre>

        修改为

        @since <pre>$today</pre>

1


         下面就让我们从“Helloworld开始第一个单元测试。新建一个项目“JunitTest然后,创建一个Helloworld类,其Java的源代码如下所示。

public class Helloworld{
    public String say(){
        return("Hello World!"); 
    }       
}


        Helloworld类代码编辑框内单击鼠标右键,在弹出的菜单中选择Generate对应快捷键为 Alt+Insert-> Junit Test -> Junit 4, IDEA test HelloworldTest类。将其中的testSay()修改为如下代码:
       

public final void testSay()
{
    Helloworld hi = new Helloworld();
    assertEquals("Hello World!",
        hi.say());       
}


        IDEA中把产品码放src目录中把测试代test目录中,命令行中设置 SOURCEPATH环境变量, IDEA中可以右键单 test目录,在弹出的菜单中选 Mark Directory as->Test Sources Root即可(这时test文件夹图标会变绿)

         鼠标右键点击HelloworldTest类,然后选择Run’HelloworldTest’运行测试类,即可查看测试结果。

2

测试一个四则运算程序,源程序如下所示。

public class Calculator
{
    public int add(int x, int y)
    { //加法
        return x + y;
    }
    public int sub(int x, int y)
    { //减法
        return x - y;
    }
    public int mul(int x, int y)
    { //乘法
        return x * y;
    }
    public int div(int x, int y)
    { //除法
        return x / y;
    }
    public int div2(int x, int y)
    { //除法           做了异常判断
        try
        {
            int z = x / y;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return x / y;
    }
}


         按照之前的步骤生成CalculatorTest 类,并修改其中的testAdd()testSub()testMul()testDiv()testDiv2()方法,如下所示:

public void testAdd() throws Exception
{
    if(calculator.add(8, 2) == 10)
    {
        System.out.println("Test passed!");
    }
    else
    {
        System.out.println("Test failed!");
    }
}
public void testSub() throws Exception
{
    if(calculator.sub(8, 2) == 6)
    {
        System.out.println("Test passed!");
    }
    else
    {
        System.out.println("Test failed!");
    }
}
public void testMul() throws Exception
{
    if(calculator.mul(8, 2) == 16)
    {
        System.out.println("Test passed!");
    }
    else
    {
        System.out.println("Test failed!");
    }
}
public void testDiv() throws Exception
{
    if(calculator.div(8, 2) == 4)
    {
        System.out.println("Test passed!");
    }
    else
    {
        System.out.println("Test failed!");
    }
}@
Rule
public ExpectedException exception = ExpectedException.none();@
Test()
public void testDiv2() throws Exception
{
    exception.expect(Exception.class);
    exception.expectMessage("除数不合法");
    calculator.div2(8, 3);
}


         CalculatorTest类,Run’CalculatorTest with coverage’试类,并可查看测试覆盖率。

验内容

         使JUnit具,针对列代码中BankAccount类编写对的测试类以完成单元测试,最终提交测试代码和测试结果。

public class BankAccount
{
    String AccountNumber;
    String AccountName;
    String ID;
    String Password;
    double TotalMoney;
    public BankAccount(String AccountNumber, String AccountName, String ID, String Password)
    {
        thisAccountNumber = AccountNumber;
        thisAccountName = AccountName;
        this.ID = ID;
        thisPassword = Password;
    }
    public void Balance(String AccountNumber)
    {
        System.out.println("PLEASE FIND YOUR BALANCE INFORMATION");
        Systemout.println("Account name:" + AccountName);
        System.out.println("Account number:" + AccountNumber);
        System.out.println("Your balance:" + TotalMoney);
    }
    public void Deposit(double AddMoney)
    {
        {
            try
            {
                if(AddMoney < 0) throw new RuntimeException();
                this.TotalMoney += AddMoney;
            }
            catch(RuntimeException except)
            {
                Systemout.println("Failed to deposite, money should be larger than 0");
            }
            System.outprintln("Deposited money succeeded, the total money is:" + TotalMoney);
        }
    }
    public void Withdraw(double GetMoney)
    {
        try
        {
            if {
                (GetMoney > this.TotalMoney) throw new RuntimeException();
                this.TotalMoney -= GetMoney;
                System.out.println("You have withdrawed money:" + GetMoney);
            }
            catch(RuntimeException except)
            {
                System.out.println("Error! you don't have enough balance");
            }
        }
    }

实验结果(个人)
案例一(HelloWorld类测试)

案例二(Calculate类测试)

测试覆盖率:

测试BankAccount

测试类BankAccountTest代码如下:

package com.xzp.util;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Assert.*;
import org.junit.Before;
import org.junit.After;
import org.junit.rules.ExpectedException;
/** 
* BankAccount Tester. 
* 
* @author GiperHsiue
* @since <pre>11月 25, 2022</pre> 
* @version 1.0 
*/ 
public class BankAccountTest {
    BankAccount account1;
@Before
public void before() throws Exception {
    account1 = new BankAccount("8008", "xzp", "1",
            "1");
    account1.TotalMoney = 200;
    System.out.println("Before...初始化了账户余额:200");
}

@After
public void after() throws Exception {
    System.out.println("After\n");
}

/**
*
* Method: Balance(String AccountNumber)
*
*/
@Test
public void testBalance() throws Exception {
//TODO: Test goes here...
}

/** 
* 
* Method: Deposit(double AddMoney) 
* 
*/

@Test
public void testDeposit() throws Exception { 
//TODO: Test goes here...
    double tmp = account1.TotalMoney;
    double inp = 1000;
    tmp += inp;
    account1.Deposit(inp);
    org.junit.Assert.assertEquals(tmp, account1.TotalMoney, 0);
} 

/** 
* 
* Method: Withdraw(double GetMoney) 
* 
*/ 
@Test
public void testWithdraw() throws Exception { 
//TODO: Test goes here...
    double tmp = account1.TotalMoney;
    double inp = 100;
    tmp -= inp;
    account1.Withdraw(inp);
    org.junit.Assert.assertEquals(tmp, account1.TotalMoney, 0);
}

@Rule
    public ExpectedException expectedDes = ExpectedException.none();
@Test
    public void testDepositThrow(){
    expectedDes.expect(RuntimeException.class);
    expectedDes.expectMessage("Failed to deposite, money should be larger than 0");
    account1.Deposit(-100);
}


    @Rule
    public ExpectedException expectedWith = ExpectedException.none();
    @Test
    public void testWithdrawThrow(){
        expectedWith.expect(RuntimeException.class);
        expectedWith.expectMessage("Error! you don't have enough balance");
        account1.Withdraw(2000);
    }

} 

运行如下:

测试覆盖率:

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐