小组github项目地址:https://github.com/Wangmmmm/WordCountPro
一、基本任务:代码编写+单元测试
1、PSP2.1表格
PSP2.1 | PSP 阶段 | 预估耗时 (分钟) | 实际耗时 (分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 10 | 10 |
· Design Spec | · 生成设计文档 | 0 | 0 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
· Design | · 具体设计 | 20 | 10 |
· Coding | · 具体编码 | 60 | 60 |
· Code Review | · 代码复审 | 20 | 20 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 60 |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 30 | 40 |
· Size Measurement | · 计算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 245 | 245 |
2、接口实现
项目开发分为四个模块,分别是输入分析,排序,输出控制和Main函数框架。
输入分析是主要工作是接受读取文件的字符并解析,当满足一个单词的条件时,会将这个单词插入到一个列表中。
排序是分析插入的单词,维护一个带有单词字符串和其出现频率的对象列表,根据自定义的比较方法排序,当列表元素个数少于一百个时,则返还这个列表,如果元素个数超过一百个,则返还前一百个元素。
输出控制,是对这个列表中的元素进行格式化,并将结果输出到目标文件中。
Main函数框架,是分析用户输入的指令,找到待读取文件,并读取文件逐字符读取内容并调用输入分析模块。
我完成的功能模块是输入分析模块
程序接口:
使用的类:
Statistics.class
获取字符:
public void Count(char c)
每次读取一个文件中的字符时,就需要调用这个函数,参数为读取到的字符。
文件读取结束:
public void End()
当文件内容全部读取结束后,需要调用这个函数。
接口的实现方法:
读取字符接口:通过使用一个状态机,把当前的字符状态分为Normal、Stat和OneBar状态,分别代表读取无效字符,读取有效字符和读取到一个横杠的状态,通过使用一个Switch 语句来使用有限状态机,通过各种跳转判断语句来实现状态的切换以及功能的实现。
文件读取结束接口:再次调用读取字符接口,并传入一个无效字符,例如“ ”,从而能够完成之前状态机的最后一步切换。
程序实现:
public void Count(char c) { if (c >= 'A' && c <= 'Z') c = Character.toLowerCase(c); switch (state) { case Normal: if (IsInvalid(c) || IsBar(c)) break; else { if (IsChar(c)) { state = State.Stat; currentWord += c; } break; } case Stat: if (IsChar(c)) { currentWord += c; } else if (IsBar(c)) { currentWord += c; state = State.OneBar; } else if (IsInvalid(c)) { MyString.Insert(currentWord); state = State.Normal; currentWord = ""; } break; case OneBar: { if (IsChar(c)) { currentWord += c; } else if (IsBar(c) || IsInvalid(c)) { currentWord.substring(0, currentWord.length()); MyString.Insert(currentWord); state = State.Normal; currentWord = ""; } } default: break; } } public void End() { Count(' '); }
3、单元测试
我在本模块共写了24个测试用例
测试代码示例
@Test
void getResult2() {
Statistics stat=new Statistics();
stat.Input("abC");
String[] expRes={"abc"};
ArrayList<String> string=stat.GetResult();
int count=string.size();
String[] res=new String[count];
for(int i=0;i<count;i++)
{
res[i]=string.get(i);
}
Assert.assertArrayEquals("error",expRes,res);
}
单元测试结果
小组贡献率
个人认为小组各成员任务分工还是很合理的,而且大家互相交流了许多,大家的贡献率是差不多的。
17052 0.25
二.扩展任务:静态测试
1. 代码规范
使用《阿里巴巴 Java 开发手册》作为代码规范。
2.同组代码分析
分析组员 17041 胡浩楠同学的代码
1.小组成员及分工:
组长:王蒙蒙 U201517052 评审员
组员:胡浩楠 U201517041 讲解员+作者
黄东鹏 U201517047 主持人
胡乐 U201517058 记录员
2.评审目的:对评审模块的功能以及代码规范进行评估,看是否达到预期效果
选择模块预期实现功能:根据输入信息输出一个文件的列表,包含了待统计的所有文件。
3.评审意见:
变量命名不是很规范:一些方法名大写字母开头,而一些是小写字母开头,没有一个统一的规范。
注释:代码注释非常完备和清楚。
异常处理:代码有比较全面的异常处理机制,不过没有实现一些自定义的异常处理类,可能代码的异常定位不够精准。
4.评审不足及困难:在本次评审中,大家交流感觉不是很充分,致使花费了很多不必要的时间。
3.静态测试
工具:FindBugs 下载地址 http://findbugs.sourceforge.net/downloads.html
测试类:OutPut.class
该写法依赖于系统编码,虽然方便,但是一旦使用就变成了一个技术债务,因为系统的默认编码是不可预知的。
小结
通过此次软件测试小组作业,首先学到最多的就是如何合理地在小组成员之间进行任务分工和合作,在使用Git实现代码共享时,一定要建立合理的分支管理不同人的代码,从而减少冲突和合并的次数,然后就是学习了Junit的使用,同时尝试思考如何设计一些全面的,能覆盖到代码各个角落的测试用例。在拓展功能中,首先是熟悉了findBugs的使用,然后就是小组成员进行同行评审的流程。经过这些步骤,的确能查找出代码的各种漏洞以及不足,从而改正自己之前编写代码的一些坏习惯。