0328复利软件4.0测试

一、项目简介

项目名称:复利计算软件
  版  本  :4.0
版本类型:java
使用工具:eclipse+swing插件
主要功能:本金,利率,年数及期待值的相互转换以及存款的实现
  备  注  :本代码仅作为学习交流用途,目前不适宜发布,更多功能及后续开发请关注本博客园

 

二、新的功能需求

   以商业标准来要求数据保证万无一失

 

三、实验代码

    本代码多处使用try catch语句保护数据。在此仅使用一个例子测试说明

     

 

    源代码:

 

    else if (b4.getText().equals("") && b1.getText() != null
                && b3.getText() != null && b2.getText() != null) // 求期望值
        {
            try {
                rate = Double.parseDouble(b2.getText());
                if (rate < 0) {
                    JOptionPane.showMessageDialog(null, "利率输入有误,请重新输入数字");
                    rate = 0;
                }
                n = Integer.parseInt(b3.getText());
                if (n < 0) {
                    JOptionPane.showMessageDialog(null, "年份输入有误,请重新输入数字");
                    n = 0;
                }
                principal = Double.parseDouble(b1.getText()); // b1本金
                if (principal < 0) {
                    JOptionPane.showMessageDialog(null, "本金输入有误,请重新输入数字");
                    rate = 0;
                }
            } catch (Exception e2) {
                // TODO: handle exception
                JOptionPane.showMessageDialog(null, "数据输入有误,请重新输入数字");
            }

            double tempprincipal = principal;
            result = JOptionPane.showConfirmDialog(null, "是否每年添加本金");
            if (result == JOptionPane.YES_OPTION) {
//                while (year <= n) {
//                    amount = principal * Math.pow(1 + rate, year)
//                            + tempprincipal;
//                    output += String.valueOf(year) + "\t\t\t"
//                            + currencyformatter.format(amount) + "\n";
//                    year = year + 1;
//                }
                amount=CalculateA(year,n,principal,rate,tempprincipal);
                System.out.println("CalculateA(year,n,principal,rate,tempprincipal)"+year+n+principal+rate+tempprincipal);
                output += String.valueOf(year) + "\t\t\t"
                        + currencyformatter.format(amount) + "\n";
            } else {
                while (year <= n) {
                    amount = principal * Math.pow(1 + rate, year);
                    output += String.valueOf(year) + "\t\t\t"
                            + currencyformatter.format(amount) + "\n";
                    year = year + 1;
                }
            }

            text.setText(output);
            int Isinfo = JOptionPane.showConfirmDialog(null, "是否要进行投资");
            if (Isinfo == JOptionPane.YES_OPTION) {
                a[input] = principal;

                b[input] = amount;
                input += 1;

            }

 

将上面的注释内容分离出来写成一个函数,如下:

public double CalculateA(int years2,int n2,double principal2,double rate2,double tempprincipal2){
        double amount2 = 0;
        while (years2 <= n2) {
            amount2 = principal2 * Math.pow(1 + rate2, years2)
                    + tempprincipal2;
            
            years2 = years2 + 1;
        }
        return amount2;
    }
    

  注意:类放在Text包中

      类名用XXXText结尾

      方法用textMethod命名

这样的方式能让我们保证一目了然,养成一个好习惯

 

测试类的代码如下:

 

public class Fulitext {


    @Test
    public void testFuli() {
        double z=new Fuli().CalculateA(1, 3, 100, 0.03, 100);
        boolean flag=0.0==z-209.2727;
        assertEquals(true, flag);
    }

}

 

 

 

 

 

 

 

 我们可以发现,测试类报错了,原因是:z是一个double型的函数,且输出为209.2727.由此可知这是运行错误,是数据的问题。于是这样修改:

 

 

可以看到,这样它没报错了。测试通过。

 

 

四、相关知识扩展

   

Assert是判断对不对。

 

assertArrayEquals(message,expecteds, actuals);

验证两个数组expectedsactuals是否相等。若相等则断言成功;若不相等则断言失败,提供message时输出message消息。当expectedsactuals均为null,assertArrayEquals认为二者相等

 

static public void assertEquals(String message, Object expected, Object actual)

assertEquals验证expectedactual是否相等。若相等则断言成功;若不相等则断言失败,提供message时输出message消息。当expectedactual均为null时,assertEquals认为二者相等。

 

 

assertTrue(String message, boolean condition)

assertTrue验证condition是否为true。若为true则断言成功;若为false则断言失败,提供message时输出message消息。

 

 

assertFalse(String message, boolean condition)

assertfalse验证condition是否为false。若为false则断言成功;若为true则断言失败,提供message时输出message消息。

 

 

fail(String message)

fail会使测试立即失败,提供message时输出message消息。

 

 

assertNull(String message, Object object)

assertNull验证对象object是否为空。若为空,则断言成功;若非空,则断言失败,提供message时输出message消息。

 

 

assertSame(String message, Object expected, Object actual)

assertSame验证expectedactual所引用的是否是同一对象。若相同,则断言成功;若不同,则断言失败,提供message时输出message消息

 

 

 assertNotSame(String message, Object unexpected, Object actual)

assertSame验证unexpectedactual所引用的是否是不同对象。若不同,则断言成功;若相同,则断言失败,提供message时输出message消息。

 

 

在谷歌下载1.2 FULL hamcrest包,把core和Library 1.2 的jar文件导入可使用hamcrest的Matchers,但是要注意,在导入的时候一定要使用静态的,因为只有静态的才能使用里面的静态方法和静态变量,在JUnit4.7的jar中有更强大的assertThat,它几乎包括了之前所有的方法。

 assertThat有以下方法:

assertThat(n, allOf( greaterThan(8), lessThan(16) ) )    //表示n这个数满足右边所有的条件,这里举个例子大于8,小于16

assertThat( n, anyOf( greaterThan(16), lessThan(8) ) )  //表示n这个数满足任意一个条件就可以了  例如大于16或者小于8

assertThat( n, anything() );              //无论n是一个什么条件都可以成立的数

assertThat(str, is/not ("****") )       //字符串是不是等于****

assertThat(str, containsString( "***" ) );        //字符串是不是包含了***

assertThat( str,  startsWith/endsWith( "***" ) );       //字符串是不是以****开始/结尾

其他更多功能便不再一一列举了。

 

 

五、阅读更多案例

代码部分:

 

public static String wordFormat4DB(String name){
       Pattern p = Pattern.compile("[A-Z]");
       Matcher m = p.matcher(name);
       StringBuffer sb = new StringBuffer();

       while(m.find()){
             m.appendReplacement(sb, "_"+m.group());
       }
          return m.appendTail(sb).toString().toLowerCase();
     }
}

 

  测试代码:

public class TestWordDealUtil {
//测试wordFormat4DB正常运行的情况
@Test public void wordFormat4DBNormal(){
String target = "employeeInfo";
String result = WordDealUtil.wordFormat4DB(target);

assertEquals("employee_info", result);
}
//测试null时的处理情况
@Test public void wordFormat4DBNull(){
String target = null;
String result = WordDealUtil.wordFormat4DB(target);

assertNull(result);
}

//测试空字符串的处理情况
@Test public void wordFormat4DBEmpty(){
String target = "";
String result = WordDealUtil.wordFormat4DB(target);

assertEquals("", result);
}
//测试当首字母大写时的情况
@Test public void wordFormat4DBegin(){
String target = "EmployeeInfo";
String result = WordDealUtil.wordFormat4DB(target);

assertEquals("employee_info", result);
}

//测试当尾字母为大写时的情况
@Test public void wordFormat4DBEnd(){
String target = "employeeInfoA";
String result = WordDealUtil.wordFormat4DB(target);

assertEquals("employee_info_a", result);
}

//测试多个相连字母大写时的情况
@Test public void wordFormat4DBTogether(){
String target = "employeeAInfo";
String result = WordDealUtil.wordFormat4DB(target);

assertEquals("employee_a_info", result);
}
}

 

 

 

六、预期异常处理

1、使用@Test(expected…)

expected允许设置一个Throwable的子类,可以使用canVote()方法验证上面抛出预期的异常

可以使用一个类,可以new一个对象,可以runnable

例如:

@Test(expected = IllegalArgumentException.class)
public void canVote_throws_IllegalArgumentException_for_zero_age() {
      Student student = new Student();
      student.canVote(0);
}

2、ExpectedException

使用JUnit框架中的ExpectedException类,需要声明ExpectedException异常。

例如:

@Rule
public ExpectedException thrown= ExpectedException.none();

 

@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
    Student student = new Student();
    thrown.expect(IllegalArgumentException.class);
    student.canVote(0);
}

这样就不用声明

expect(RuntimeException.class, “Expected exception message”)

  

thrown.expect(IllegalArgumentException.class, “age should be +ve”);

 

3、Try/catch with assert/fail

我比较喜欢使用这种方式,也在我的代码里有多处应用

public void Dcalculate() {

        double principal = 0;
        double amount = 0;
        double rate = 0;
        int n = 0;
        NumberFormat currencyformatter = NumberFormat.getCurrencyInstance(); // 字符串转化为数字
        String output = "年" + "/" + "复利存款";
        int year = 1;
        int result;

        if (b1.getText().equals("") && b2.getText() != null
                && b3.getText() != null && b4.getText() != null) { // 计算本金

            try {
                rate = Double.parseDouble(b2.getText());
                if (rate < 0) {
                    JOptionPane.showMessageDialog(null, "利率输入有误,请重新输入数字");
                    rate = 0;
                }
                n = Integer.parseInt(b3.getText());
                if (n < 0) {
                    JOptionPane.showMessageDialog(null, "年份输入有误,请重新输入数字");
                    n = 0;
                }
                amount = Double.parseDouble(b4.getText());
                if (amount < 0) {
                    JOptionPane.showMessageDialog(null, "期待值输入有误,请重新输入数字");
                    amount = 0;
                }
            } catch (Exception e2) {
                // TODO: handle exception
                JOptionPane.showMessageDialog(null, "数据输入有误,请重新输入数字");

            }

            principal = 0;
            while (year <= n) {
                principal = amount / (Math.pow(1 + rate, year));
                year = year + 1;
            }

            output = "本金" + currencyformatter.format(principal) + "\n";
            text.setText(output);

        }

        else if (b2.getText().equals("") && b1.getText() != null
                && b3.getText() != null && b4.getText() != null) // 求利率
        {
            try {
                principal = Double.parseDouble(b1.getText()); // b1本金
                if (principal < 0) {
                    JOptionPane.showMessageDialog(null, "本金输入有误,请重新输入数字");
                    principal = 0;
                }
                n = Integer.parseInt(b3.getText()); // b3年份
                if (n < 0) {
                    JOptionPane.showMessageDialog(null, "年份输入有误,请重新输入数字");
                    n = 0;
                }
                amount = Double.parseDouble(b4.getText()); // b4期望值
                if (amount < 0) {
                    JOptionPane.showMessageDialog(null, "期待值输入有误,请重新输入数字");
                    amount = 0;
                }
            } catch (Exception e2) {
                // TODO: handle exception
                JOptionPane.showMessageDialog(null, "数据输入有误,请重新输入数字");
            }

            rate = java.lang.StrictMath.pow(amount / principal, 1.0 / n) - 1;
            output = "利率" + rate + "\n";
            text.setText(output);
        }

        else if (b3.getText().equals("") && b1.getText() != null
                && b2.getText() != null && b4.getText() != null) // 求年份
        {
            try {
                principal = Double.parseDouble(b1.getText()); // b1本金
                if (principal < 0) {
                    JOptionPane.showMessageDialog(null, "本金输入有误,请重新输入数字");
                    principal = 0;
                }
                amount = Double.parseDouble(b4.getText()); // b4期望值
                if (amount < 0) {
                    JOptionPane.showMessageDialog(null, "期待值输入有误,请重新输入数字");
                    amount = 0;
                }
                rate = Double.parseDouble(b2.getText());
                if (rate < 0) {
                    JOptionPane.showMessageDialog(null, "利率输入有误,请重新输入数字");
                    rate = 0;
                }
            } catch (Exception e2) {
                // TODO: handle exception
                JOptionPane.showMessageDialog(null, "数据输入有误,请重新输入数字");
            }

            double year2 = Math.log(amount / principal) / Math.log(1 + rate);
            output = "至少年数" + year2 + "\n";
            text.setText(output);
        }

        else if (b4.getText().equals("") && b1.getText() != null
                && b3.getText() != null && b2.getText() != null) // 求期望值
        {
            try {
                rate = Double.parseDouble(b2.getText());
                if (rate < 0) {
                    JOptionPane.showMessageDialog(null, "利率输入有误,请重新输入数字");
                    rate = 0;
                }
                n = Integer.parseInt(b3.getText());
                if (n < 0) {
                    JOptionPane.showMessageDialog(null, "年份输入有误,请重新输入数字");
                    n = 0;
                }
                principal = Double.parseDouble(b1.getText()); // b1本金
                if (principal < 0) {
                    JOptionPane.showMessageDialog(null, "本金输入有误,请重新输入数字");
                    rate = 0;
                }
            } catch (Exception e2) {
                // TODO: handle exception
                JOptionPane.showMessageDialog(null, "数据输入有误,请重新输入数字");
            }

            double tempprincipal = principal;
            result = JOptionPane.showConfirmDialog(null, "是否每年添加本金");
            if (result == JOptionPane.YES_OPTION) {
//                while (year <= n) {
//                    amount = principal * Math.pow(1 + rate, year)
//                            + tempprincipal;
//                    output += String.valueOf(year) + "\t\t\t"
//                            + currencyformatter.format(amount) + "\n";
//                    year = year + 1;
//                }
                amount=CalculateA(year,n,principal,rate,tempprincipal);
                System.out.println("CalculateA(year,n,principal,rate,tempprincipal)"+year+n+principal+rate+tempprincipal);
                output += String.valueOf(year) + "\t\t\t"
                        + currencyformatter.format(amount) + "\n";
            } else {
                while (year <= n) {
                    amount = principal * Math.pow(1 + rate, year);
                    output += String.valueOf(year) + "\t\t\t"
                            + currencyformatter.format(amount) + "\n";
                    year = year + 1;
                }
            }

            text.setText(output);
            int Isinfo = JOptionPane.showConfirmDialog(null, "是否要进行投资");
            if (Isinfo == JOptionPane.YES_OPTION) {
                a[input] = principal;

                b[input] = amount;
                input += 1;

            }
        } else if (b1.getText() != null && b4.getText() != null
                && b3.getText() != null && b2.getText() != null) {
            JOptionPane.showMessageDialog(null, "请删除一个数据");
        } else {
            JOptionPane.showMessageDialog(null, "请增加数据");
        }
    }
    
    

这样再使用JOptionpane。提示错误

 

七、总结

1、以后写代码尽量把模块分得清楚点方便进行测试

2、多使用try catch语句包围保证程序正常运行

3、写代码的要有意识地思考可能会出现哪些情况错误,单元测试不能完全保证无bug。

4、在建立项目的时候要注意起到项目,要有创建包的习惯,把类和测试类分在不同的包,方法也要规范化,尽量,最好别用拼音。

 

八、资源

学习JUnit网站视频:http://www.sxt.cn/course/showdetail-10003-one.html

github代码:https://github.com/hellolaona/text

Junit测试代码参考网址:https://github.com/hellolaona/junitdemo

 

 

 

 

 

posted @ 2016-03-28 20:14  15林志杰  阅读(356)  评论(2编辑  收藏  举报