211614331 王诚荣
211614354 陈斌
自己挖的坑,就是哭着也要填完。。。
## 一、单元测试
写在前面:我以前写代码,都是一段一段写,先看运行结果是否正确,如果正确就放入程序中,然后就不管了。所以就只能在存入程序前测试一次,到后期程序完工的时候,如果出现问题,就很难分块查找问题,分块单独测试了。所以在本次单元测试中,最让我苦恼的,就是怎么在一个模块中捕捉到一个可以和预期结果相比较的值。因为我的大部分方法都是没有返回值的......
- 在单元测试中,我的想法就是,尽量将每一个类里的方法都测试一遍,通过自动或人工(ps:有的方法,我只能通过人工判断其是否正确运行,因为里面的值都是不定的,比如说随机产生一道二年级的题目...)的方法判断这个方法是否能运行出正确结果。
- 在分析程序运行流程的时候,我大致定下了如下几个测试方向:
- 1.AddOperation类(一年级加法运算类):能否随机产生一道符合要求的一年级加法题目(人工判断)
- 2.Subtraction类(一年级减法运算类):能否随机产生一道符合要求的一年级加法题目;(人工判断)
- 3.Division类(二年级除法运算类):能否随机产生一道符合要求的二年级除法题目;(人工判断)
- 4.Multiplication类(二年级除法运算类):能否随机产生一道符合要求的二年级乘法题目;(人工判断)
- 5.三年级时能否随机产生一道符合要求的三年级四则混合运算题目;(依旧随机性大,人工判断)
- 6.ArithemticS类(四则运算类)中:调度场算法传入题目后能否产生一个正确的后缀表达式(批量数据,自动测试)
- 7.ArithemticS类(四则运算类)中:逆波兰算法能否正确解出一个可能带括号的四则运算式子(批量数据,自动测试)
- 8.命令行输入参数时,对参数合法性检验,能否准确各种输入数据的合法性(批量数据,自动测试)
- 9.在输入各种参数后,整个程序能否正确运行,各个模块能否被准确调用,并最终产生out.txt文档或者错误信息(批量输入数据,自动检验)
- 10.分块测试完成之后,在通过测试套件,把这些测试模块一起运行一遍,看能否通过检验
测试代码(部分)
public class testPartArithemticSForStartP { // 测试Arithemitics中的startProblem能否产生正确的后缀表达式
@Test
public void testStartProblem() {
Object[][] test=new Object[][] { // 存储测试数据,及正确后缀表达式
{"-×+45+83+2515","( 15 + 25 ) - ( 3 + 8 ) × ( 5 + 4 )"},
{"×-23÷415","15 ÷ 4 × ( 3 - 2 )"},
{"÷4×+232","2 × ( 3 + 2 ) ÷ 4"},
{"+÷432","2 + 3 ÷ 4"}
// 二维数组中,第一个是预期的后缀表达式,第二个位置是传入的题目
/*
{"-×+45+83+2515","( 15 + 25 ) - ( 3 + 8 ) × ( 5 + 4 )"},
{"×-23÷415","15 ÷ 4 × ( 3 - 2 )"},
{"÷4×+232","2 × ( 3 + 2 ) ÷ 4"},
{"+÷432","2 + 3 ÷ 4"} //改变正确结果,验证能否被检测出来
*/
};
ArithemticS as=new ArithemticS();
String s1="";
for(int i=0;i<test.length;i++) { // 循环遍历object[][]这个二维数组
s1="";
as.startProblem((String)test[i][1]);// 得到测试数据,并传入调度场算法的方法中
for(int j=0;j<as.postFixStack.size();j++) {
s1=s1+as.postFixStack.get(j);// 得到调度场算法中,分析出的后缀表达式
}
System.out.println("第"+(i+1)+"组数据:"+s1.equals(test[i][0]));
// 判断后缀表达式和正确结果是否相同
assertEquals(test[i][0], s1);// 判断调度场中的后缀表达式和预期表达式是否相同
}// for end 二维数组遍历完成,所有数据测试完毕
}
}
在测试调度场算法的时候,由于我原本程序的返回值并不是一个后缀表达式,所以我只能通过捕捉调度场算法的中间产物postFixStack(用于存储后缀表达式的栈),来判断结果是否与预期值相同。
测试覆盖率截图
## 二、结构与优化 ### UML类图 ![](https://img2018.cnblogs.com/blog/1472368/201809/1472368-20180930023308567-19006877.png)
程序流程图
关于重构
由于我们在前一次作业中,就已经把程序分模块了,所以在结构优化中,修改的不多。我们所做的就是,把判断输入参数是否正确的代码提取了出来,把它写成了一个方法取名为inputTest()返回值为boolean类型,这样就可以在单元测试中,单独测试参数判断这个模块了,而不用每次测试的时候都运行一遍主函数了。
模块介绍(可结合一下上面的UML图)
AddOperation类:随机产生一道符合要求的一年级加法题;
Subtraction类:随机产生一道符合要求的一年级减法题;
Division类:随机产生一道符合要求的二年级除法题;
Multiplication类:随机产生一道符合要求的二年级乘法题;
RandomQuestions类.questionShop():随机产生一道四则运算题目;
ArithemticS类.startProblem():接收四则运算题,并转化为后缀表达式;
ArithemticS类.solveProblem():接收后缀表达式,解出答案,并判断题目是否符合年级限制;
MathExam类.inputTest():接收输入参数,并判断是否符合要求;
OutPutSet类:把出好的所有题目,一次性打印输出到out.txt中;
三、性能调优
-
贴出优化前效能分析工具的结果截图
-
描述程序的性能瓶颈
-
出9999道题目的时间太长,遇到不合要求的题目就要从头再来
-
给出优化方案
-
限制随机数字的范围,减少重复的机会
-
贴出优化后效能分析工具的结果截图