(1)Github项目地址:https://github.com/cosensible/WordCountPlus

(2)PSP表格

PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分钟)
· Planning · 计划 30 30
· Estimate · 估计这个任务需要多少时间 30 30
· Development · 开发 90 120
· Analysis · 需求分析 (包括学习新技术) 30 60
· Design Spec · 生成设计文档 30 30
· Design Review · 设计复审 (和同事审核设计文档) 30 30
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 60
· Design · 具体设计 20 40
· Coding · 具体编码 60 90
· Code Review · 代码复审 30 45
· Test · 测试(自我测试,修改代码,提交修改 30 45
· Reporting · 报告 60 90
· Test Report · 测试报告 30 45
· Size Measurement · 计算工作量 15 15
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 30
· 合计 635 760

(3)代码设计思路

   这次题目的需求明确了很多,也集中在了统计词频上,因此,我们很容易就确定应有一个模块用于统计词频,为此新建一个类WordFrequencyCountUtil及主要方法countWordFrequency如下,输入为文件中提取出的字符串数组,输出为排过序且添加了词频的字符串数组。

public class WordFrequencyCountUtil {
    public static String[] countWordFrequency(String[] resultContents){

   对于符合要求的单词的筛选可以使用正则表达式,利用Matcher.find找到字符串中满足正则表达式的子串,利用substring截取子串。

for(String content:resultContents){
            //按照规则,找出每行中,形如abc(-ab)*这样的单词
            String regex="[a-zA-Z]+(-[a-zA-Z]+)*";
            Pattern pattern=Pattern.compile(regex);
            Matcher matcher=pattern.matcher(content);
            while (matcher.find()){
                input(content.substring(matcher.start(),matcher.end()),resultMap);
            }
        }

   利用map存储单词和对应的词频,为此新建input方法将内容存入map,存入时将单词小写化,同时判断map中是否已有同一单词。

private static void input(String s,Map<String,Integer> map){
        s=s.toLowerCase();
        if(map.containsKey(s)){
            map.put(s,map.get(s)+1);
        }else
            map.put(s,1);
    }

   对于map中的单词进行词频排序,满足题目所需要求,优先比较词频,其次比较字母顺序

List<Map.Entry<String,Integer>> list=new ArrayList<>(resultMap.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                if(o1.getValue()<o2.getValue())
                    return 1;
                if(o1.getValue()>o2.getValue())
                    return -1;
                return o1.getKey().compareTo(o2.getKey());
            }
        });

   将map中的单词和词频拼接成一个字符串,存入字符数组中待用。

String[] results=new String[list.size()];
        int index=0;
        for(Map.Entry<String,Integer> entry:list){
            results[index++]=entry.getKey()+"  "+entry.getValue();
        }
        return results;

(4)测试设计过程

   由于模块逻辑较简单,仅从sort函数角度进行路径覆盖测试,即对大小写分别测试:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int"});
        assertEquals("int  1", result[0]);

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"Int"});
        assertEquals("int  1", result[0]);

   根据输入格式规定设计黑盒测试,
   首先测试一个单词单频的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int"});
        assertEquals("int  1", result[0]);

   测试一个单词多词频的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int int"});
        assertEquals("int  2", result[0]);

   测试多个单词的情况:

 String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int main int"});
        assertEquals("int  2", result[0]);

   测试含有-的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int-"});
        assertEquals("int  1", result[0]);

   测试两个单词由-连接的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int-int"});
        assertEquals("int-int  1", result[0]);

   测试多个单词由-连接的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int-int-int"});
        assertEquals("int-int-int  1", result[0]);

   测试空格和-连接的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int -int-int"});
        assertEquals("int  1", result[0]);

   测试含有,的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int,is"});
        assertEquals("int  1", result[0]);

   测试含有\的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"\"int"});
        assertEquals("int  1", result[0]);

   测试含有数字的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int1"});
        assertEquals("int  1", result[0]);

   测试含有(的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"(int"});
        assertEquals("int  1", result[0]);

   测试含有数字和其他符号的情况:

 String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"1int)"});
        assertEquals("int  1", result[0]);

   测试空字符串的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{" "});
        assertEquals(0, result.length);

   测试null的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{});
        assertEquals(0, result.length);

   测试输入有多个字符串的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int", "int main"});
        assertEquals("int  2", result[0]);

   测试多字符混合的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"(see Box 3–2).8885d_c01_016"});
        assertEquals("box  1", result[0]);

   测试大小写和数字-混合的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"taBlE1-2", "table"});
        assertEquals("table  2", result[0]);

   测试数字和字母混合的多字符串的情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"table1-2", "table112"});
        assertEquals("table  2", result[0]);

   测试首字母相同时的排序情况:

String[] result = WordFrequencyCountUtil.countWordFrequency(new String[]{"int i i int"});
        assertEquals("i  2", result[0]);

(5)测试运行和评价

   测试运行截图:

   测试用例满足需求,测试结果正确,程序代码无误。

(6)静态测试

   IDEA插件下载地址:https://pan.baidu.com/s/1NSJo9yXKmOoP6bM4CyMMig
   插件使用说明:https://github.com/alibaba/p3c/tree/master/idea-plugin
   测试了全部代码,问题如下: