• 简易四则运算生成程序——第一次改进后的单元测试


    测试项目:减一四则运算生成程序

    项目成员:张金生  张政

    工程地址:https://coding.net/u/jx8zjs/p/paperOne/git

    ssh://git@git.coding.net:jx8zjs/paperOne.git

    测试单元概览

    1. Fraction: 分数类,支持分数加减乘除法,约分,取相反数等

    2.QuestionGen:题目生成类,支持生成各种难度的题目,和答案。

    待测单元:

    Fraction类:

     1 public class Fraction {
     2     public int up;
     3     public int down;
     4 
     5     public Fraction(int up, int down) {
     6         if (down == 0 || up == 0) {
     7             System.out.println("divided by zero error");
     8             return;
     9         }
    10         int smaller = up > down ? up : down;
    11         int maxCommonFactor = 1;
    12         for (int i = 1; i <= smaller; i++) {
    13             if (up % i == 0 && down % i == 0) {
    14                 maxCommonFactor = i;
    15             }
    16         }
    17 
    18         this.up = up / maxCommonFactor;
    19         this.down = down / maxCommonFactor;
    20     }
    21 
    22 
    23     public Fraction gcd(Fraction f) {
    24         int smaller = f.up > f.down ? f.up : f.down;
    25         int maxCommonFactor = 1;
    26         for (int i = 1; i <= smaller; i++) {
    27             if (f.up % i == 0 && f.down % i == 0) {
    28                 maxCommonFactor = i;
    29             }
    30         }
    31         f.up = f.up / maxCommonFactor;
    32         f.down = f.down / maxCommonFactor;
    33 
    34         return f;
    35     }
    36 
    37     public String toString() {
    38         if (down == 1)
    39             return "" + up;
    40         if(Math.abs(up)/down>0){
    41             return up>0?up/down+" "+up%down+"/"+down:"-"+Math.abs(up)/down+" "+Math.abs(up)%down+"/"+down;
    42         }
    43         return up + "/" + down;
    44     }
    45 
    46     public Fraction add(Fraction f) {
    47         Fraction a = new Fraction(up, down);
    48         a.up = f.up * a.down + a.up * f.down;
    49         a.down = a.down * f.down;
    50 
    51         return a.gcd(a);
    52     }
    53 
    54     public Fraction minus(Fraction f) {
    55         Fraction a = new Fraction(up, down);
    56         a.up = a.up * f.down - f.up * a.down;
    57         a.down = a.down * f.down;
    58 
    59         return a.gcd(a);
    60     }
    61 
    62     public Fraction multiply(Fraction f) {
    63         Fraction a = new Fraction(up, down);
    64         a.up = a.up * f.up;
    65         a.down = a.down * f.down;
    66         return a.gcd(a);
    67     }
    68 
    69     public Fraction divide(Fraction f) {
    70         Fraction a = new Fraction(up, down);
    71         a.up = a.up * f.down;
    72         a.down = a.down * f.up;
    73         return a.gcd(a);
    74     }
    75 
    76     public Fraction changeSign(){
    77         up = -up;
    78         return this;
    79     }
    80 
    81     public static Fraction getRandiom(int Max) {
    82         return new Fraction((int) (Math.random() * Max / 2) + 1, (int) (Math.random() * Max / 2) + 1);
    83     }
    84 
    85     public static Fraction getRandiom(int Max, boolean isInt) {
    86         return new Fraction((int) (Math.random() * Max / 2) + 1, isInt ? 1 : (int) (Math.random() * Max / 2) + 1);
    87     }
    View Code

    QuestionGen类待测单元:

      1     public String generateSimpleQuestion() {
      2         SupportedOperation[] operation = { SupportedOperation.ADD, SupportedOperation.MINUS };
      3         return generateQuestion(2, 0, 20, operation, false, false);
      4     }
      5 
      6     public String generateCommonQuestion() {
      7         SupportedOperation[] operation = { SupportedOperation.ADD, SupportedOperation.MINUS,
      8                 SupportedOperation.MULTIPLY, SupportedOperation.DIVIDE };
      9         return generateQuestion(4, 0, 20, operation, false, true);
     10     }
     11 
     12     public String generateMediumQuestion() {
     13         SupportedOperation[] operation = { SupportedOperation.ADD, SupportedOperation.MINUS,
     14                 SupportedOperation.MULTIPLY, SupportedOperation.DIVIDE };
     15         return generateQuestion(4, 0, 20, operation, true, true);
     16     }
     17 
     18     public String generateComplexQuestion() {
     19         SupportedOperation[] operation = { SupportedOperation.ALL };
     20         return generateQuestion(6, 0, 20, operation, true, true);
     21     }
     22 
     23     public String answer;
     24 
     25     Stack<SupportedOperation> oplist = new Stack<SupportedOperation>();
     26     Stack<Fraction> numlist = new Stack<Fraction>();
     27     ArrayList<Integer[]> bclist;
     28     TreeMap<Integer, Integer> frequency;
     29     TreeMap<Integer, Integer> direction;
     30 
     31     private void getBcPrint(int numOfOperand) {
     32         bclist = new ArrayList<Integer[]>();
     33         if (numOfOperand > 2) {
     34             int bcnum = (int) (Math.random() * (numOfOperand - 2));
     35             for (int n = 0; n < bcnum; n++) {
     36                 Integer[] bracket = new Integer[2];
     37                 bracket[0] = (int) (Math.random() * (numOfOperand - 2));
     38                 bracket[1] = (int) (Math.random() * (numOfOperand - 2 - bracket[0]) + bracket[0]);
     39                 if (bracket[0] == bracket[1]) {
     40                     bracket[1]++;
     41                 }
     42                 boolean canput = true;
     43                 for (int i = 0; i < bclist.size(); i++) {
     44                     Integer[] tmp = bclist.get(i);
     45                     if (bracket[0] < tmp[0] & bracket[1] >= tmp[0] & bracket[1] < tmp[1]) {
     46                         canput = false;
     47                         break;
     48                     } else if (bracket[1] > tmp[1] & bracket[0] > tmp[0] & bracket[0] <= tmp[1]) {
     49                         canput = false;
     50                         break;
     51                     } else if (bracket[0] == tmp[0] & bracket[1] == tmp[1]) {
     52 
     53                     }
     54                 }
     55                 if (canput) {
     56                     bclist.add(bracket);
     57                 }
     58             }
     59 
     60         }
     61         frequency = new TreeMap<Integer, Integer>();
     62         direction = new TreeMap<Integer, Integer>();
     63         for (int i = 0; i < bclist.size(); i++) {
     64             Integer[] tmp = bclist.get(i);
     65             if (frequency.containsKey(tmp[0])) {
     66                 frequency.put(tmp[0], frequency.get(tmp[0]) + 1);
     67             } else {
     68                 frequency.put(tmp[0], 1);
     69                 direction.put(tmp[0], 0);
     70             }
     71             if (frequency.containsKey(tmp[1])) {
     72                 frequency.put(tmp[1], frequency.get(tmp[1]) + 1);
     73             } else {
     74                 frequency.put(tmp[1], 1);
     75                 direction.put(tmp[1], 1);
     76             }
     77         }
     78     }
     79 
     80     public Fraction getanswer(ArrayList<Fraction> frlist, SupportedOperation[] so) {
     81 
     82         numlist.push(frlist.get(0));
     83         for (int n = 0; n < so.length; n++) {
     84             switch (so[n]) {
     85             case ADD:
     86                 oplist.push(so[n]);
     87                 numlist.push(frlist.get(n + 1));
     88                 break;
     89             case MINUS:
     90                 oplist.push(SupportedOperation.ADD);
     91                 numlist.push(frlist.get(n + 1).changeSign());
     92                 break;
     93             case MULTIPLY: {
     94                 Fraction r = numlist.pop().multiply(frlist.get(n + 1));
     95                 numlist.push(r);
     96             }
     97                 break;
     98             case DIVIDE: {
     99                 Fraction r = numlist.pop().divide(frlist.get(n + 1));
    100                 numlist.push(r);
    101             }
    102                 break;
    103             default:
    104                 System.out.println("不支持的运算");
    105                 break;
    106             }
    107         }
    108 
    109         while (!oplist.isEmpty()) {
    110             Fraction answer = numlist.pop();
    111             switch (oplist.pop()) {
    112             case ADD: {
    113                 answer = answer.add(numlist.pop());
    114                 numlist.push(answer);
    115             }
    116                 break;
    117 //            case MINUS: {
    118 //                answer = answer.minus(numlist.pop());
    119 //                numlist.push(answer);
    120 //            }
    121 //                break;
    122             default:
    123                 System.out.println("不支持的运算");
    124                 break;
    125             }
    126 
    127         }
    128 
    129         return numlist.pop();
    130     }
    View Code

    QuestionGen核心题目生成单元:

      1     public String generateQuestion(int numOfOperand, int rangeMin, int rangMax, SupportedOperation[] operation,
      2             boolean isFractional, boolean hasbracket) {
      3         String question = "";
      4         int[] ioperands = null;
      5         ArrayList<Fraction> af = new ArrayList<Fraction>();
      6         SupportedOperation[] so = null;
      7         if (numOfOperand < 2) {
      8             System.out.println("操作数数量至少为2");
      9             return "";
     10         }
     11         if (rangMax > 500) {
     12             System.out.println("操作数数最大值不能超过500");
     13             return "";
     14         }
     15         getBcPrint(numOfOperand);
     16         if (!isFractional) {
     17             ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript");
     18             ioperands = new int[numOfOperand];
     19             for (int i = 0; i < numOfOperand; i++) {
     20                 ioperands[i] = (int) (Math.random() * rangMax / 2 + 1);
     21 
     22             }
     23             so = new SupportedOperation[numOfOperand - 1];
     24             for (int i = 0; i < operation.length; i++) {
     25                 if (operation[i] == SupportedOperation.ALL) {
     26                     operation = new SupportedOperation[4];
     27                     operation[0] = SupportedOperation.ADD;
     28                     operation[1] = SupportedOperation.MINUS;
     29                     operation[2] = SupportedOperation.MULTIPLY;
     30                     operation[3] = SupportedOperation.DIVIDE;
     31 
     32                 }
     33             }
     34             // 除法運算,保证整除
     35             int value = 0;
     36             for (int j = numOfOperand - 1; j > 0; j--) {
     37                 so[numOfOperand - 1 - j] = operation[(int) (Math.random() * operation.length)];
     38             }
     39             for (int j = numOfOperand - 2; j >= 0; j--) {
     40                 if (so[j] == SupportedOperation.DIVIDE) {
     41                     if (value < 1) {
     42                         ioperands[j] = ioperands[j] * ioperands[j + 1];
     43                         value++;
     44 
     45                     } else {
     46                         so[j] = operation[(int) (Math.random() * (operation.length - 2))];
     47                     }
     48                 }
     49             }
     50             // 输出括号
     51             for (int i = 0; i < numOfOperand - 1; i++) {
     52                 if (frequency.containsKey(i)) {
     53                     if (direction.get(i) == 0) {
     54                         for (int k = 0; k < frequency.get(i); k++) {
     55                             question += "(";
     56                         }
     57                     }
     58                 }
     59                 question += ioperands[i];
     60                 if (frequency.containsKey(i)) {
     61                     if (direction.get(i) == 1) {
     62                         for (int k = 0; k < frequency.get(i); k++) {
     63                             question += ")";
     64                         }
     65                     }
     66                 }
     67                 question += so[i];
     68             }
     69             if (frequency.containsKey(numOfOperand - 1)) {
     70                 if (direction.get(numOfOperand - 1) == 0) {
     71                     for (int k = 0; k < frequency.get(numOfOperand - 1); k++) {
     72                         question += "(";
     73                     }
     74                 }
     75             }
     76             question += ioperands[numOfOperand - 1];
     77             if (frequency.containsKey(numOfOperand - 1)) {
     78                 if (direction.get(numOfOperand - 1) == 1) {
     79                     for (int k = 0; k < frequency.get(numOfOperand - 1); k++) {
     80                         question += ")";
     81                     }
     82                 }
     83             }
     84 
     85             try {
     86                 Integer d = (Integer) se.eval(question);
     87                 answer = "" + d;
     88             } catch (Exception e) {
     89                 generateQuestion(numOfOperand, rangeMin, rangMax, operation, isFractional, hasbracket);
     90             }
     91 
     92         } else {
     93             for (int i = 0; i < numOfOperand; i++) {
     94                 af.add(Fraction.getRandiom(rangMax));
     95             }
     96 
     97             so = new SupportedOperation[numOfOperand - 1];
     98             for (int i = 0; i < operation.length; i++) {
     99                 if (operation[i] == SupportedOperation.ALL) {
    100                     operation = new SupportedOperation[4];
    101                     operation[0] = SupportedOperation.ADD;
    102                     operation[1] = SupportedOperation.MINUS;
    103                     operation[2] = SupportedOperation.MULTIPLY;
    104                     operation[3] = SupportedOperation.DIVIDE;
    105 
    106                 }
    107             }
    108             question += af.get(0);
    109             for (int j = 0; j < numOfOperand - 1; j++) {
    110                 so[j] = operation[(int) (Math.random() * operation.length)];
    111                 question += (so[j] == SupportedOperation.DIVIDE ? "÷" : so[j].toString()) + af.get(j + 1);
    112 
    113             }
    114             answer = getanswer(af, so).toString();
    115             try {
    116             } catch (Exception e) {
    117                 e.printStackTrace();
    118             }
    119 
    120         }
    121 
    122         return question;
    123 
    124     }
    View Code

    测试类:

    FractionTest

     1 public class FractionTest {
     2 
     3     Fraction f1 = new Fraction(9, 4);
     4     Fraction f2 = new Fraction(16, 4);
     5 
     6     @Test
     7     public void testdown0() {
     8         new Fraction(0, 0);
     9     }
    10 
    11     @Test
    12     public void testGcd() {
    13         assertEquals("4", f2.gcd(f2).toString());
    14     }
    15 
    16     @Test
    17     public void testToString() {
    18         assertEquals("2 1/4", f1.toString());
    19     }
    20 
    21     @Test
    22     public void testAddFraction() {
    23         assertEquals(new Fraction(25, 4).toString(), f1.add(f2).toString());
    24     }
    25 
    26     @Test
    27     public void testMinusFraction() {
    28         assertEquals(new Fraction(-7, 4).toString(), f1.minus(f2).toString());
    29     }
    30 
    31     @Test
    32     public void testMultiplyFraction() {
    33         assertEquals(new Fraction(144, 16).toString(), f1.multiply(f2).toString());
    34     }
    35 
    36     @Test
    37     public void testDivideFraction() {
    38         assertEquals(new Fraction(9, 16).toString(), f1.divide(f2).toString());
    39     }
    40 
    41     @Test
    42     public void testChangeSign() {
    43         assertEquals(new Fraction(-9, 4).toString(), f1.changeSign().toString());
    44     }
    45 
    46     @Test
    47     public void testGetRandiomInt() {
    48         Fraction a = Fraction.getRandiom(7);
    49         System.out.println(a.toString());
    50     }
    51 
    52     @Test
    53     public void testGetRandiomIntBoolean() {
    54         Fraction a = Fraction.getRandiom(7, true);
    55         Fraction b = Fraction.getRandiom(7, true);
    56         System.out.println("true = " + a.toString() + "
    false = " + b.toString());
    57     }
    58 
    59 }

    QuestionGenTest:

     1 public class QuestionGenTest {
     2 
     3     QuestionGen qg = new QuestionGen();
     4     ArrayList<Fraction> flt = new ArrayList<Fraction>();
     5     SupportedOperation[] sot = { SupportedOperation.ADD, SupportedOperation.MINUS, SupportedOperation.MULTIPLY,
     6             SupportedOperation.DIVIDE };
     7 
     8     @Test
     9     public void testGetanswer() {
    10 
    11         flt.add(new Fraction(1, 2));
    12         flt.add(new Fraction(1, 3));
    13         flt.add(new Fraction(1, 4));
    14         flt.add(new Fraction(1, 3));
    15         flt.add(new Fraction(1, 2));
    16 
    17         Fraction r = qg.getanswer(flt, sot);
    18         assertEquals("2/3", r.toString());
    19 
    20     }
    21 
    22     @Test
    23     public void testGenerateSimpleQuestion() {
    24         qg.generateSimpleQuestion();
    25     }
    26 
    27     @Test
    28     public void testGenerateCommonQuestion() {
    29         qg.generateCommonQuestion();
    30     }
    31 
    32     @Test
    33     public void testGenerateMediumQuestion() {
    34         qg.generateMediumQuestion();
    35     }
    36 
    37     @Test
    38     public void testGenerateComplexQuestion() {
    39         qg.generateComplexQuestion();
    40     }
    41 
    42 
    43 }

    测试结果:

    Fraction类测试结果:

    QuestionGen类测试结果:

    单元测试总结:

    单元测试时发现了一些功能或方法定义了,但在使用的时候没有用到,有些可能预计不会再用到的则选择注释掉,这样可以增加代码覆盖率。测试过的单元和功能都能成功的达到想要的预期结果。

    代码覆盖率:

    Fraction类测试代码覆盖率:

    QuestionGen类测试代码覆盖率:

    总代吗覆盖率:

    代码覆盖率总结:

    Fraction类的代码覆盖率能达到97.4%,确实非常高,没有测试到的部分为一些复杂的随机分支,或者减少程序出错的校验内容。QuestionGen类的代码覆盖率为74.2%,一部分未测试部分也是由于随机程度够多的时候才能完全覆盖,本次测试也运行了多次测试用例,目前显示未覆盖的部分也是可达的,还有一部分未测试行是保证程序鲁棒性的代码。因此我们认为本次测试基本达到单元测试要求。

    工程地址:https://coding.net/u/jx8zjs/p/paperOne/git

    ssh://git@git.coding.net:jx8zjs/paperOne.git

  • 相关阅读:
    纯CSS3实现3D动画导航,html5 webRTC技术实现免费网页电话拨打
    Base64编解码Android和ios的例子,补充JNI中的例子
    新春寄语
    彩票号码OC呈现
    iOS CFNetwork报错
    Android常用库
    高性能服务端访问设计
    Tomcat的ISO-8859-1
    迅达云s3cmd客户端mac平台部署说明
    Android.os.NetworkOnMainThreadException
  • 原文地址:https://www.cnblogs.com/jx8zjs/p/5914046.html
Copyright © 2020-2023  润新知