有点难

211606313 李佳 211606381 吴伟华

单元测试

设计单元测试的思路

  • 首先分析每个方法的作用,弄清楚返回值是什么,没有返回值的要弄清楚他修改的是类中的哪个字段,这些就是用来检测方法是否正确
  • 先对有返回值且返回值是基本数据类型或字符串的方法进行测试,这样的方法最好测试,只需要断言返回值和预期结果是否相同即可
  • 对于有返回值但不是基本数据类型的方法,要弄清楚如何去检验这个返回值,拿到返回值后要做那几样断言
  • 对于无返回值的方法就要弄清楚他修改的对象的属性要怎样去检验

单元测试代码

	@Test 
	public void testCalPoland() {
	    // 因为几个测试方法用到的时同一批测试用例,expected2记录了该测试用例是否符合该方法执行的条件
		if(!expected2) {
			boolean f = false; // 当运算过程中出现算术异常时需要捕获,并重新执行一次
			do {
				f = false;
				// 初始化方法执行时所用到的字段
				MathExam.topic = new StringBuffer[] {new StringBuffer()};
				MathExam.standAnswer = new StringBuffer[] {new StringBuffer()};
				int re = 0; // 保存测试的方法返回的结果
				int res = 0; // 保存预期结果
				try {
					res = MathExam.calPoland(t,0,grade);
					String str = MathExam.topic[0].toString().replace(" ", ""); 
					str = str.replace("×", "*"); 
					str = str.replace("÷", "/"); 
					re = (int) new ShuntingYard().shuntYardAlgo(str.toCharArray());
					assertEquals(re , res);

				} catch (ArithmeticException e) {
					f = true;
				}
			}while(f);
		}
	}

因为使用的算法是调用自己修改过的逆波兰表达式算法,计算数字是在运行过程中根据条件生成的,不能预先知道表达式的结果,所以在这里使用了别人正确的调度场,逆波兰算法,计算运算过程中生成的表达式的值,再判断是否和我的逆波兰算法得到的结果相同

单元测试得到的测试覆盖率截图

结构优化

程序的UML类图

程序的重构及原因

  • 在上一次作业中大部分内容都是分为一个一个模块进行白编写的,这次重构的主要目的就是解决面对不同需求时都需要重新修改主类的代码问题
  • 在前两次作业都是不断加深,从小学一、二年级题目到三年级,为避免后续需求变更又要重新修改大量代码而选择重构,将因需求而产生变动的代码分离出来,创建一个接口,以后对于不同的需求,只要继承这个接口,实现对于方法,类名按照固定格式,即可通过反射机制自动创建对象,调用相应方法
  • 主类中有判断用户输入、生成只含有运算符的后缀表达式模板、根据模板生成对于题目并计算答案,文件的输出这几个方法
  • 另有一个需求接口类,要求具体需求类必须提供,生成对于需求的运算符,以及传入一个运算符生成两个符合运算需求的数字这两个方法

性能调优

优化前效能分析工具的结果截图

程序的性能瓶颈


主要在于在出现一些生成的数字计算出现不合理时就抛出异常重新执行一次

优化方案

尽量通过加减乘除去修正不合理数据,只有到真的无法修正的时候才重新来过

优化后效能分析工具的结果截图

总结

  • 相对编写代码来说测试感觉更为艰难,一个是在测试用例的设计上,尽可能的使用较少的用例来检测出很多的bug,这是一个挑战,在编写代码时你就已经将你想到的各种情况做出来逻辑判断,现在等于说是要打破自己原来固有的想法,从另一种角度考虑数据的输入
  • 测试的目的在于验证你没有错,并不是你的代码是正确的,所以在写测试代码时要考虑清楚怎样才是你想要的结果,判断的对象是方法最终产生的影响
  • 对于代码的重构,主要考究一个方法是否太复杂,牵扯到的外部变量是否太多,以后维护时是否会大幅度修改这段代码,尽量让每一个方法功能单一,实现高内聚,低耦合
原文地址:https://www.cnblogs.com/mujinjia/p/9728907.html