小组作业wordCountPro·
基本任务:代码编写+单元测试
(1) Github地址: https://github.com/LongtermPartner/ExtendWordCount
(2) PSP表格:
psp 2.1 | psp阶段 | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 10 | 10 |
Estimate | 估计这个任务需要多少时间 | 10 | 10 |
Deveploment | 开发 | 500 | 630 |
Analysis | 需求分析(包括学习新技术) | 30 | 30 |
Design Spec | 生成设计文档 | 20 | 20 |
Design Review | 设计复审(和同事审核设计文档) | 10 | 10 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 20 | 20 |
Design | 具体设计 | 30 | 30 |
Coding | 具体编码 | 150 | 200 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 150 | 200 |
Reporting | 报告 | 10 | 10 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
合计 | 550 | 630 |
(3)对接口的实现:
对于wordCountPro计数单词优化版,我们小组搭建的框架是:将整个程序分为四个模块,分别是Input,Output,CountAndSort,Main模块,也就是一个包下分别建有对应模块的类,由相应组员完成对应负责的模块,因为考虑到模块间的耦合性,便于各个模块间的单元测试,于是主函数只有三行关键代码,即输入模块调用,返回值文件传给主模块计数并排序模块,主功能模块将处理好的单词排序封装成由Map<String,Integer>集合组成的Arraylist数组,并传给输出模块,并由输出模块写入到输出文本,且输出模块负责只输入前100个高频度单词,超过100不输出。
我负责的是主功能模块的Sort排序函数实现。
该Sort函数接收并对TreeMap中的数据进行排序,TreeMap一般默认为对键值排序,但该数据结构的键值为单词,值为词频,根据需求我们需要对词频排序,词频高的排在前面,词频低的排在后面。若是出现词频出现相同的情况,则按照键值排序。在此函数中键值为字母组成的单词,因此排序按字母顺序排序。故代码中需重写TreeMap默认的排序方法,即Comparator比较器中的compare方法,若是词频值大的就排前面,如果出现词频相等则进行键值比较。getInt()函数主要是将String类型转化成int类型的数值大小。因为compare()方法返回的是int数值型,所以需要将键值String类型比较转化成int类型数值比较。
具体函数实现如下:
//对统计的单词进行词频排序 public static ArrayList<Map.Entry<String, Integer>> Sort(TreeMap<String, Integer> wordsCount){ // 升序比较器 Comparator<Map.Entry<String, Integer>> valueComparator = new Comparator<Map.Entry<String,Integer>>() { @Override public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) { //若是词频相同则比较键值大小即比较将String类型转化成int数值类型的大小 return o2.getValue()-o1.getValue()==0?getInt(o2.getKey())-getInt(o1.getKey()):o2.getValue()-o1.getValue(); } //将String类型转化成数值类型 private int getInt(String key) { int i=0; try{ Pattern pattern=Pattern.compile("^\\d+"); Matcher matcher=pattern.matcher(key); if(matcher.find()){ i=Integer.valueOf(matcher.group()); } }catch(NumberFormatException e){ e.printStackTrace(); } return i; } }; // map转换成list进行排序 ArrayList<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String,Integer>>(wordsCount.entrySet()); // 排序 Collections.sort(list,valueComparator); return list; }
(4)测试用例的设计:
需要测试的模块为上述所贴代码函数,该Sort函数接收并对TreeMap中的数据进行排序,根据需求我们需要对词频排序,词频高的排在前面,词频低的排在后面。若是出现词频出现相同的情况,则按照键值排序。在此函数中键值为字母组成的单词,因此排序按字母前后顺序排序。
整体测试思路:
首先改变需要测试文本的内容,在此我们指的是hMap中的数据,
然后调用CountAndSort的Sort排序函数得到实际执行的actual,
最后调用assertEquals函数将预先排序好的期望值expected与actual比较。
注:因为各个模块之间单独测试,在单词统计功能后不会出现相同单词和除字母及-字符之外的字符数字,但我在此是对自己实现的排序模块进行测试,与计数模块同时进行测试,故为了程序的健壮性,我将相同单词的出现情况和单词中包含其他非‘-’字符如#,数字也加入了测试用例中。
为达到对需求功能的测试,因为实现模块的函数逻辑简单,因此我的测试思路几乎是从黑盒测试出发,也有白盒测试,如排序情况是否选择键值比较。我从以下几个方面设计测试用例:
1.特殊情况:文本为空时 黑盒测试
2.文本中单词个数数量且词频不同 条件测试 有效等价类测试
3.文本中单词不同,词频相同 条件测试 有效等价类测试
4.文本中单词相同,词频相同 无效等价类测试
5.文本中单词含有特殊字符和数字 无效等价类测试
具体测试用例:
expected为存放预期数据的动态数组,actual为接收sort函数的动态数组,即实际运行结果。
Test Case ID 测试用例编号 |
Test Item 测试项 (即功能模块或函数) |
Test Case Title 测 试用例标题 |
Test Criticality 重要级别 |
Pre-condition 预置条件 |
Input 输入 |
Procedure 操作步骤 |
Output 预期结果 |
Result 实际结果 |
Status 是否通过 |
Remark 备注 (在此描述使用的测试方法) |
S_1 | 排序模块 | 文本内容为空 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_2 | 排序模块 | 文本内容为一个字母组成的单词,词频相同 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_3 | 排序模块 | 文本内容为多个字母组成的单词,词频相同 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_4 | 排序模块 | 文本内容为仅由‘-或字母组成的单词,词频相同 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_5 | 排序模块 | 文本内容相同,单词顺序不同,词频相同 | L | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_6 | 排序模块 | 文本内容如上,打乱单词顺序,词频相同 | L | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
s_7 | 排序模块 | 文本内容由字母和‘-’组成的单词,词频相同 | H | hMap集合 | 无 | 无 | expected | actual | 是 | 白盒测试 |
S_8 | 排序模块 | 文本单词相同词频相同 | L | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_9 | 排序模块 | 文本内容由一个字母组成且词频不同 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_10 | 排序模块 | 单词不同词频不同 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 白盒测试 |
S_11 | 排序模块 | 打乱不同单词且词频不同的顺序 | L | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_12 | 排序模块 | 文本含‘-’连接单词 | H | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_13 | 排序模块 | 文本单词(含'-')不同词频不同 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_14 | 排序模块 | 交换相同单词词频不同的顺序 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_15 | 排序模块 | 单词数量多时 | H | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_16 | 排序模块 | 词频大 | H | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_17 | 排序模块 | 单词数量多且词频大 | H | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_18 | 排序模块 | 多个单词且含特殊字符 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_19 | 排序模块 | 多个单词含字母数字 | M | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
S_20 | 排序模块 | 多个单词含有各种特殊字符数字且词频跨度大 | H | hMap集合 | 无 | 无 | expected | actual | 是 | 黑盒测试 |
(5)单元测试的运行截图:
(6)根据小组讨论,自己的小组贡献分为0.28 。
扩展任务:静态测试
(1)邹欣老师博客:现代软件工程讲义 代码规范与代码复审
http://www.cnblogs.com/xinz/archive/2011/11/20/2255971.html
(2)使用该规范分析了学号后5位为17097的代码,
小的代码问题:大括号{ }没有单独占用一行,有的变量名命名不够规范。
遵循好的规范:关键语句都有注释,在复杂的条件表达式中,用括号清楚地表示逻辑优先级。
(3)静态代码检查工具:
我们小组选择的静态代码检查工具为:PMD
工具下载地址: http://pmd.sourceforge.net/eclipse/
(4)工具对于代码扫描结果,界面运行截图:
根据静态代码分析器PMD得出代码存在以下问题:
1.方法参数o1,o2未定义为final类型。
2.变量名字太短,如o1,o2,i。
3.对象的定义在方法内,导致其他对象不可见。
4.代码中类的所有方法属于static类型,建议为类创建私有构造方法。
5.包名含有大写字母。
改进方法:
1.将方法参数o1,o2定义为final类型。
2.将变量o1,o2,i改为word1,word2,integer。
3.将对对象的定义提到方法外。
4.为含有方法全为静态类型的类创建私有构造方法。
5.包名改成全部由小写字母组成。
(5)整个小组代码主要存在的问题就是很多方法均为静态方法,没有为该类创建私有构造方法;很多对象定义和使用放在一起,导致对象定义不明显;变量名的命名不规范。
高级任务:性能测试和优化
(1)测试数据集的设计思路:
给出一个数据量足够大且在一定程度上能给程序造成压力的测试文本,多次改变文本内容但行数维持在1000行左右的包括特殊字符的文本,定义两个变量startTime,endTime(单位为毫秒)分别用来获取程序及各个子模块运行前后系统时间,运行程序,将(endTime-startTime)得到的结果进行分析。
(2)优化前的程序性能指标:程序运行时间即测出的endTime-startTime.
(3)同行评审,组员全部参加,组长主持,其他组员进行评审,对计数和排序模块进行了评审,集体认为计数和排序会占用大多的程序运行时间。
(4)测试结果:
进行多次测试发现程序执行时间为100-200ms左右。
由测试结果可知,影响性能指标的主要因素是计数和排序模块,它们运行所花时间占了程序大部分时间。
与同行评审结论一致。
(5)优化思路:程序花费时间最多的模块就是计数和排序模块,因此需要改进计数和排序模块的时间复杂度,尤其是计数模块,将之前的逐个字母扫描判断改为用正则表达式实现,在一定程度上可以提升程序的性能。
(6)软件开发、软件测试、软件质量之间的关系:
软件开发欲软件测试的关系:在软件开发过程中进行单元测试,软件开发完成进行集成测试,所以在某种程度来说,相比软件开发,软件测试是建立在软件开发基础上的,在测试的同时找出程序存在的问题并改进,提高软件质量。同样若有足够的项目经验,软件开发时所搭建的框架接口也在一定程度上影响软件质量,另一方面,测试用例集的选择与设计是否覆盖全面也影响着软件质量的好坏。