单元测试(201421123088,201421123063)
a. 需求分析:测试上有哪些详细的需求?
1、把计算模块提取出来,单独创建一个类。
2、针对提取出来的计算类的接口函数做单元测试。
3、测试整数运算。
4、测试分数运算。
b. 测试数据:
1、整数运算测试:
2、分数运算测试:
3、代码覆盖率:
部分代码(以分数加法为例)
public string Calculate(string s) { // ToDo if(s.IndexOf("+")>-1){ add(s); }else if(s.IndexOf("-")>-1){ substract(s); }else if(s.IndexOf("*")>-1){ multiply(s); }else if(s.IndexOf("÷")>-1){ divide(s); } return result; } public void add(String s) { String[] str = s.Split(new char[2] { '/', '+' }); numerator = int.Parse(str[0]) * int.Parse(str[3]) + int.Parse(str[1]) * int.Parse(str[2]); denominator = int.Parse(str[1]) * int.Parse(str[3]); divisors = GCD(numerator, denominator); numerator /= divisors; denominator /= divisors; result = numerator + "/" + denominator; }
在做混合运算的时候碰到了点麻烦,索引超出界限。
考虑到是动态数组,我觉得先给他个固定长度,但是仍然没用,F11调试了一下,发现str0,str1的长度仍然由Split控制。
public void multiply(String s) { String[] str = s.Split('*'); if(str[0].IndexOf("/")>-1 || str[1].IndexOf("/")>-1) { string[] str0 = new string[2]; string[] str1 = new string[2]; str0 = str[0].Split('/'); str1 = str[1].Split('/'); if (str0[1] == null) str0[1] = "1"; if (str1[1] == null) str1[1] = "1"; numerator = int.Parse(str0[0]) * int.Parse(str1[0]); denominator = int.Parse(str0[1]) * int.Parse(str1[1]); divisors = GCD(numerator, denominator); numerator /= divisors; denominator /= divisors; result = numerator + "/" + denominator; } else result = int.Parse(str[0]) * int.Parse(str[1]) + ""; Console.Write(result); }
虽然不知道为什么但是还是得继续,那就直接判断长度给数组添加元素,查阅之后发现c#不能这么做,只能利用Concat新建个数组合并 或者利用List,然后ToArray(List功能很强大,不过我这个只是给他添加个分母为1,就直接用Concat了)
public void multiply(String s) { String[] str = s.Split('*'); if(str[0].IndexOf("/")>-1 || str[1].IndexOf("/")>-1) { string[] str0 = str[0].Split('/'); string[] str1 = str[1].Split('/'); if (str0.Length < 2) str0 = str0.Concat(new string[] { "1" }).ToArray(); if (str1.Length < 2) str1 = str1.Concat(new string[] { "1" }).ToArray(); numerator = int.Parse(str0[0]) * int.Parse(str1[0]); denominator = int.Parse(str0[1]) * int.Parse(str1[1]); divisors = GCD(numerator, denominator); numerator /= divisors; denominator /= divisors; result = numerator + "/" + denominator; } else result = int.Parse(str[0]) * int.Parse(str[1]) + ""; }
这样混合运算完成了,做完这个多元的思路也出来了,以数组长度为限量循环多元变两元,等会写吧:)。。。
多元运算写的还是挺快的,但是测试后发现,有点奇怪,这个应该是多元的一部分(多元加,减,乘,除法),只能有一种算法。感觉用递归靠谱点。
public void add(String s) { string[] str = s.Split('+'); string[] str0 = str[0].Split('/'); for (int i = 0; i < str.Length - 1; i++) { if (str[i].IndexOf("/") > -1 || str[i + 1].IndexOf("/") > -1) { string[] str1 = str[i + 1].Split('/'); if (str0.Length < 2) str0 = str0.Concat(new string[] { "1" }).ToArray(); if (str1.Length < 2) str1 = str1.Concat(new string[] { "1" }).ToArray(); numerator = int.Parse(str0[0]) * int.Parse(str1[1]) + int.Parse(str0[1]) * int.Parse(str1[0]); denominator = int.Parse(str0[1]) * int.Parse(str1[1]); divisors = GCD(numerator, denominator); numerator /= divisors; denominator /= divisors; str0[0] = numerator + ""; str0[1] = denominator + ""; result = numerator + "/" + denominator; } else { result = int.Parse(str[i]) + int.Parse(str[i + 1]) + ""; str[i + 1] = result; } } }
加了个递归实现了多元运算,不过要考虑下优先级。还有就是减法和加法在一起要注意一下,这样混合多元运算就全部实现了。
public void add(String s) { string[] str = s.Split('+'); for (int i = 0; i < str.Length; i++) { if (str[i].IndexOf("*") > -1) { multiply(str[i]); str[i] = result; } else if (str[i].IndexOf("÷") > -1) { divide(str[i]); str[i] = result; } else if (str[i].IndexOf("+") > -1) { add(str[i]); str[i] = result; } else if (str[i].IndexOf("-") > -1) { substract(str[i]); str[i] = result; } } string[] str0 = str[0].Split('/'); for (int i = 0; i < str.Length - 1; i++) { if (str[i].IndexOf("/") > -1 || str[i + 1].IndexOf("/") > -1) { string[] str1 = str[i + 1].Split('/'); if (str0.Length < 2) str0 = str0.Concat(new string[] { "1" }).ToArray(); if (str1.Length < 2) str1 = str1.Concat(new string[] { "1" }).ToArray(); numerator = int.Parse(str0[0]) * int.Parse(str1[1]) + int.Parse(str0[1]) * int.Parse(str1[0]); denominator = int.Parse(str0[1]) * int.Parse(str1[1]); divisors = GCD(numerator, denominator); numerator /= divisors; denominator /= divisors; str0[0] = numerator + ""; str0[1] = denominator + ""; result = numerator + "/" + denominator; } else { result = int.Parse(str[i]) + int.Parse(str[i + 1]) + ""; str[i + 1] = result; } } }
public void substract(String s) { String[] str = s.Split('-' ); for (int i = 0; i < str.Length; i++) { if (str[i].IndexOf("*") > -1) { multiply(str[i]); str[i] = result; } else if (str[i].IndexOf("÷") > -1) { divide(str[i]); str[i] = result; } else if (str[i].IndexOf("+") > -1) { if (i == 0) { add(str[i]); str[i] = result; } else { str[i] = str[i].Replace("+", "-"); //当加法在减法后面时,加法变为减法 substract(str[i]); str[i] = result; } } else if (str[i].IndexOf("-") > -1) { substract(str[i]); str[i] = result; } } string[] str0 = str[0].Split('/'); for (int i = 0; i < str.Length - 1; i++) { if (str[i].IndexOf("/") > -1 || str[i + 1].IndexOf("/") > -1) { string[] str1 = str[i+1].Split('/'); if (str0.Length < 2) str0 = str0.Concat(new string[] { "1" }).ToArray(); if (str1.Length < 2) str1 = str1.Concat(new string[] { "1" }).ToArray(); numerator = int.Parse(str0[0]) * int.Parse(str1[1]) - int.Parse(str0[1]) * int.Parse(str1[0]); denominator = int.Parse(str0[1]) * int.Parse(str1[1]); divisors = GCD(numerator, denominator); numerator /= divisors; denominator /= divisors; str0[0] = numerator + ""; str0[1] = denominator + ""; result = numerator + "/" + denominator; } else { result = int.Parse(str[i]) - int.Parse(str[i + 1]) + ""; str[i + 1] = result; } } }
c. 小结与感受:通过测试,是否有效发现了程序计算模块的问题,并给予改进?
这次单元测试其实在弄明白单元测试的基本步骤后是比较容易的,毕竟只是测试了计算模块。
在fork了助教的测试例子后发现了我和大多数同学不一样的地方就是接受参数的方式,我利用datagridvie控件的属性限制了参数的非法输入以及直接使用参数并没有用程序实现,
这些到了单元测试中我不知道如何测试。思考如何用程序实现应该算是一个进步吧
另一个可能就是编码规范了,我是直接在事件中写方法,图形界面写的不多,想到哪里写哪里,还是应该把方法提取出一个类。这次测试确实感觉到了有些麻烦。
当然我还是想测试一下其他模块,例如文件流的功能,不过涉及到vs控件自带的属性方法,不知道怎么测试,暂时也没找到学习方法,暂时搁浅。
每次编程都会学到一些新东西,还是很开心的。
d. 在隔了一周之后再看之前的代码,是否更能体会到下面这些东西
(1) 良好的设计:之前没有分模块写在方法类调用,而是在按钮事件里直接写的方法,故这次作业前先进行了模块划分。
(2) 编码规范:规范的编码格式,有意义的函数名,使得这个时隔一周的代码看起来也不会太麻烦,时间上有一定的节省。
(3) 必要的注释:距离之前写这个代码已经过去一周了,添加必要的注释方便重温代码,大大节省了回忆代码的时间,这是个好习惯,要一直保持。
e.项目开发的coding.net 地址:https://coding.net/u/DzXzz/p/BasicCalculator-unittest/git
f.此次结对作业的PSP:
PSP2.1 | Personal Software Process Stages | Time Senior Student | Time |
Planning | 计划 | ||
Estimate | 估计这个任务需要多少时间 | 6h | 7h |
Development | 开发 | ||
Analysist | 需求分析 (包括学习新技术) | 1.5h | 1.4h |
Design Spec | 生成设计文档 | 0 | 0 |
Design Review | 设计复审 | 0 | 0 |
Coding Standard | 代码规范 | 0.5h | 0.3h |
Design | 具体设计 | ||
Coding | 具体编码 | 2.5h | 3h |
Code Review | 代码复审 | 0.5h | 0.5h |
Test | 测试(自我测试,修改代码,提交修改 | 1h | 1h |
Reporting | 报告 | 1.5h | 1.5h |
测试报告 | 0 | 0 | |
计算工作量 | |||
并提出过程改进计划 |
结对照片: