首页 > 代码库 > 简易四则运算生成程序——第一次改进后的单元测试
简易四则运算生成程序——第一次改进后的单元测试
测试项目:减一四则运算生成程序
项目成员:张金生 张政
工程地址: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 }
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 }
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 = http://www.mamicode.com/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 }
测试类:
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 @Test12 public void testGcd() {13 assertEquals("4", f2.gcd(f2).toString());14 }15 16 @Test17 public void testToString() {18 assertEquals("2 1/4", f1.toString());19 }20 21 @Test22 public void testAddFraction() {23 assertEquals(new Fraction(25, 4).toString(), f1.add(f2).toString());24 }25 26 @Test27 public void testMinusFraction() {28 assertEquals(new Fraction(-7, 4).toString(), f1.minus(f2).toString());29 }30 31 @Test32 public void testMultiplyFraction() {33 assertEquals(new Fraction(144, 16).toString(), f1.multiply(f2).toString());34 }35 36 @Test37 public void testDivideFraction() {38 assertEquals(new Fraction(9, 16).toString(), f1.divide(f2).toString());39 }40 41 @Test42 public void testChangeSign() {43 assertEquals(new Fraction(-9, 4).toString(), f1.changeSign().toString());44 }45 46 @Test47 public void testGetRandiomInt() {48 Fraction a = Fraction.getRandiom(7);49 System.out.println(a.toString());50 }51 52 @Test53 public void testGetRandiomIntBoolean() {54 Fraction a = Fraction.getRandiom(7, true);55 Fraction b = Fraction.getRandiom(7, true);56 System.out.println("true = " + a.toString() + "\nfalse = " + 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 @Test23 public void testGenerateSimpleQuestion() {24 qg.generateSimpleQuestion();25 }26 27 @Test28 public void testGenerateCommonQuestion() {29 qg.generateCommonQuestion();30 }31 32 @Test33 public void testGenerateMediumQuestion() {34 qg.generateMediumQuestion();35 }36 37 @Test38 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
简易四则运算生成程序——第一次改进后的单元测试