软件质量与测试--第二周作业 WordCount

时间:2022-04-23 18:40:10

软件质量与测试 第二周作业 WordCount

Github地址:

https://github.com/Hu-Peking/WordCount

 

PSP2.1: 

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

解题思路:

  1、将程序的功能需求分为基础功能和拓展功能,按先后顺序分别实现两部分的内容;

  2、先在IDE中实现对电脑中指定目录下的文件的读写操作;

  3、编写程序,实现可以在Main函数的调用下分别正确运行各个基础功能;

  4、编写程序,实现在终端执行该程序时,程序可以获取到终端输入的全部参数,并能对终端所在的目录下的文档进行读写;

  5、调整Main函数中对各个功能的调用机制,使得在终端输入相应的参数时,程序可以正常执行所对应的功能;

  6、确定程序可以正确运行所有的基础功能后,把工程打包成.jar文件,再将.jar文件转换成.exe文件,在终端中运行.exe文件,确保.exe可以正确执行所有基础功能;

  7、基于实现基础功能的程序,进行扩展功能的程序的编写,完成所有的扩展功能;

  8、确定程序可以正确运行所有功能后,把工程打包成.jar文件,再将.jar文件转换成.exe文件,在终端中运行.exe文件,确保.exe可以正确执行所有功能;

 

  本工程的参考资料都是通过百度所查找的,均是博客

  查阅资料:

  http://blog.csdn.net/u012325167/article/details/50856515

  http://blog.csdn.net/chengzhaoan2010/article/details/78344791

 

程序设计实现过程:

  程序包含三个类,分别为Main、Action、Count和FileUtils

  Main:程序的主函数类,实现整个程序的所有功能的调用,其中含有以下方法:

    main():作为主方法。

  Action:实现要执行功能的判断、各种统计功能的调用和最后的信息输出的功能,其中含有以下方法:

    judges(String[] commands):命令分析函数,对终端中传入的参数进行判断,统计需要执行的功能;

    do_thing(String[] orders):对需要执行的功能进行调用;

    write(String[] write_content):对write_content中的内容进行打印;

  Count:此类为本工程的主体,完成了-c, -w, -l, -o, -a, -e这些功能的实现,其中含有以下方法:

    c(File file):统计文件中的字符数;

    w(File file):统计文件的单词数;

    l(File file):统计文件的行数;

    a(File file):统计文件的代码行、空行和注释行的行数;

    we(File file, File stop):统计文件中除去停用词表中的停用词后,剩余的单词总数;

  FileUtils:此类实现了递归处理目录下符合条件的文件,其中含有以下方法:

    getFiles(File dir):递归处理dir目录下的所有文件,对以.c结尾的文件进行命令行中的操作;

 

代码说明:

主函数:建立Action类的实例ac,通过ac调用Action中的命令分析、结果打印和功能调用这些方法;

 1 public static void main(String[] args) {  2 
 3         String[] commands = new String[10];  4         String print_content = null;  5         String[] lastone = new String[2];  6 
 7         Action ac = new Action();  8 
 9         commands = ac.judges(args); 10 
11         if (commands[6].equals("true") && commands[7].endsWith(".c")) { 12             FileUtils fu = new FileUtils(commands); 13             print_content = fu.all_content; 14         } else { 15             print_content = Action.do_thing(commands); 16  } 17 
18 
19         lastone[0] = commands[8]; 20         lastone[1] = print_content; 21 
22  ac.write(lastone); 23 
24     }

命令分析函数:对args[]字符串数组中的参数进行判断,依次获取args[]中的每一个参数并将其与"-c", "-w", "-l", "-o", "-a", "-e", "-s"这7个字符串进行比较,决定程序需要对文件执行-c, -w, -l, -o, -a, -e, -s中的哪些功能;此外通过判断args[]中是否存在相等的字符串判断命令行输入是否有误,选取以".txt"和".c"结尾的,获取.c和.txt文件的文件名,最终将判断后所得的结果返回;

 1 public String[] judges(String[] commands) {  2 
 3         String[] output = new String[10];  4 
 5 // ArrayList<Object> output = new ArrayList<Object>();
 6 
 7         boolean error = false;  8         boolean l = false;       //1
 9         boolean w = false;       //2
 10         boolean c = false;       //3
 11         boolean o = false;       //4
 12         boolean a = false;       //5
 13         boolean e = false;       //6
 14         boolean s = false;       //7
 15 
 16         String in_file = null;   //8
 17         String out_file = null;  //9
 18         String stop_file = null; //10
 19 
 20         String path = null;  21 
 22         //保证输入的参数无重复
 23         for (int i = 0; i < commands.length - 1; i++) {  24             for (int j = i + 1; j < commands.length; j++) {  25                 if (commands[i].equals(commands[j])) {  26                     error = true;  27                     break;  28  }  29  }  30             if (error) {  31                 break;  32  }  33  }  34 
 35         if (!error) {  36             for (int i = 0; i < commands.length; i++) {  37                 if (commands[i].equals("-l")) {  38                     l = true;  39                 } else if (commands[i].equals("-w")) {  40                     w = true;  41                 } else if (commands[i].equals("-c")) {  42                     c = true;  43                 } else if (commands[i].equals("-a")) {  44                     a = true;  45                 } else if (commands[i].equals("-e")) {  46                     e = true;  47                     i = i + 1;  48                     stop_file = commands[i];  49                     if (!stop_file.contains(".txt")) {  50                         error = true;  51                         break;  52  }  53                 } else if (commands[i].equals("-o")) {  54                     o = true;  55                     i = i + 1;  56                     out_file = commands[i];  57                     if (!out_file.endsWith(".txt")) {  58                         error = true;  59                         break;  60  }  61                 } else if (commands[i].equals("-s")) {  62                     s = true;  63                 } else if (commands[i].endsWith(".c")) {  64                     in_file = commands[i];  65                 } else {  66                     error = true;  67                     break;  68  }  69  }  70 
 71 
 72             File directory = new File("");  73             try {  74                 path = directory.getAbsolutePath();  75             } catch (Exception e1) {  76  e1.printStackTrace();  77  }  78 
 79 
 80             //确定要写的文件
 81             if (!o) {  82                 out_file = "result.txt";  83  }  84 
 85 
 86             //确定停用词文件
 87             File file_stop = null;  88             if (e) {  89                 //设置停用词表
 90                 file_stop = new File(path + "/" + stop_file);  91 
 92                 if (!file_stop.exists()) {  93                     error = true;  94                     System.out.println("停用词表不存在!");  95                     System.exit(0);  96  }  97  }  98 
 99             if (l) { 100                 output[0] = "true"; 101             } else { 102                 output[0] = "false"; 103  } 104 
105             if (w) { 106                 output[1] = "true"; 107             } else { 108                 output[1] = "false"; 109  } 110 
111             if (c) { 112                 output[2] = "true"; 113             } else { 114                 output[2] = "false"; 115  } 116 
117             if (o) { 118                 output[3] = "true"; 119             } else { 120                 output[3] = "false"; 121  } 122 
123             if (a) { 124                 output[4] = "true"; 125             } else { 126                 output[4] = "false"; 127  } 128 
129             if (e) { 130                 output[5] = "true"; 131             } else { 132                 output[5] = "false"; 133  } 134 
135             if (s) { 136                 output[6] = "true"; 137             } else { 138                 output[6] = "false"; 139  } 140 
141             output[7] = path + "/" + in_file; 142             output[8] = path + "/" + out_file; 143             output[9] = path + "/" + stop_file; 144 
145 
146         } else { 147             System.out.println("命令行输入有误!"); 148             System.exit(0); 149  } 150         return output; 151     }

结果输出函数:在调用该函数时获取要打印到.txt文件中的内容,通过java.IO.File类的方法将结果打印到.txt文件中;

 1 public void write(String[] write_content) {  2 
 3         //write_content[0] file write_content[1] content  4 
 5         //向文件中写入内容
 6 
 7         File write_file = new File(write_content[0]);  8 
 9         if (!write_file.exists()) { 10             try { 11  write_file.createNewFile(); 12             } catch (Exception e1) { 13  e1.printStackTrace(); 14  } 15  } 16         try { 17 
18             FileWriter fw = new FileWriter(write_file); 19             BufferedWriter bufw = new BufferedWriter(fw); 20             bufw.write(write_content[1]); 21  bufw.close(); 22  fw.close(); 23         } catch (Exception e1) { 24  e1.printStackTrace(); 25  } 26         System.out.println("Succeed!"); 27     }

 

递归处理函数:实现-s操作,以wc.exe所在的文件夹为起点,利用深度优先搜索,遍历wc.exe文件夹所在的目录下所有后缀名为.c的文件,并对这些文件依次进行命令行所输入的操作,具体操作如下:

    1、遍历wc.exe所在的文件夹中的每个文件,判断其是否为文件或是文件夹;

    2、若为文件则对其进行命令行所输入的操作;

    3、若为文件夹则获取其中所有文件,并对每一个文件进行1中操作;

 1 public void getFiles(File dir) {  2         if (dir.exists()) {  3             //判断是否是目录
 4             if (dir.isDirectory()) {  5                 File[] files = dir.listFiles();  6 
 7                 for (File file : files) {  8  getFiles(file);  9  } 10             } else { 11                 String inFile = dir.getAbsolutePath(); 12                 if (inFile.endsWith(".c")) { 13                     arg[7] = inFile; 14                     all_content = all_content + Action.do_thing(arg) + "\n"; 15                     System.out.print("\n"); 16  } 17  } 18  } 19     }

-c, -w, -l, -o, -a, -e等的操作较为雷同,故选取-w所对应的函数进行举例;

单词统计:实现-w的操作,先获取读入文件的所有内容,再调用split()函数在" "和","处对所有内容进行分割,最后统计分割得到的字符串数组的长度,即为该文件中的单词数;

 1 public int w(File file) {  2         //单词数
 3         int word_num = 0;  4 
 5         //文本的全部内容
 6         String content = "";  7 
 8         //file存在,读取内容
 9         if (file.exists()) { 10             try { 11                 FileReader fr = new FileReader(file); 12 
13                 BufferedReader bufr = new BufferedReader(fr); 14                 String s = null; 15 
16                 //获取文本全部内容
17                 while ((s = bufr.readLine()) != null) { 18                     content = content + s; 19  } 20  bufr.close(); 21  fr.close(); 22 
23                 String[] words = content.split("[ ]+|[,]+"); 24                 /*for (int i = 0; i < words.length; i++) { 25  System.out.println(i + words[i]); 26  }*/
27                 //获取单词数
28                 word_num = words.length; 29 // System.out.println(word_num);
30                 System.out.println(file.getName() + ",单词数:" + word_num); 31             } catch (Exception e1) { 32  e1.printStackTrace(); 33  } 34         } else { 35             word_num = -1; 36             System.out.println("文件不存在!"); 37  } 38         return word_num; 39     }

 

测试设计过程:

测试中本着用例覆盖所有分支的目的进行设计

测试用例如下所示: 

 1 //下面测试-c字符统计功能
 2 if while else end  3 
 4 
 5 //下面测试-w的单词统计功能
 6 interest ing  7 interest  8 ing  9 
10 
11 //下面测试-a的空行/代码行/注释行的统计功能 12 //空行测试
13 
14  } 15 t 16 
17 //代码行测试
18 if(){ 19 } else if(){ 20 } else{ 21 } 22 
23 //注释行测试
24 s//
25 //
26      //
27 
28 
29 //下面测试-e的排除停用词表中单词的统计功能
30 typedef struct { 31     int startvex; 32     int endvex; 33     int length; 34 } edge; 35 edge T[M]; 36 
37 void main() { 38     int dist[N][N] = {{0,   6, MAX,  7, MAX}, 39                       {MAX, 0,   5,  8,  -4}, 40                       {MAX, -2,  0, MAX, MAX}, 41                       {MAX, MAX, -3, 0,  9}, 42                       {2,   MAX, 7, MAX, 0}};//图的邻接矩阵
43     int d[N]; 44     int num = 0; 45     num = BellmanFord(dist, d, 0);//计算下标为0的顶点到其它顶点的距离,num用于统计边数
46     for (int i = 0; i < N; i++)//打印到各个顶点之间的距离
47         printf("%d ", d[i]); 48     printf("\n"); 49     for (int j = 0; j < num; j++)//打印考虑过的边
50         printf("start=%d,end=%d,lenth=%d\n", T[j].startvex, T[j].endvex, T[j].length); 51 }

终端命令行输入:

 1 //单个功能测试  2 wc.exe -l file.c  3 wc.exe -c file.c  4 wc.exe -w file.c  5 wc.exe -a file.c  6 wc.exe -o out.txt  7 
 8 //组合功能测试  9 wc.exe -l -c file.c 10 wc.exe -l -w file.c 11 wc.exe -l -a file.c 12 wc.exe -c -w file.c 13 wc.exe -c -a file.c 14 wc.exe -w -a file.c 15 
16 wc.exe -l -w file.c -e stop.txt 17 wc.exe -c -w file.c -e stop.txt 18 wc.exe -w -a file.c -e stop.txt 19 
20 wc.exe -l -c -w -a file.c -e stop.txt 21 
22 wc.exe -l -c -w -a file.c -e stop.txt -o out.txt 23 
24 wc.exe -l -c -w -a -s *.c -e stop.txt 25 wc.exe -l -c -w -a -s *.c -e stop.txt -o out.txt 26 
27 
28 //错误测试 29 //无读取的文件 30 wc.exe -l -c 31 wc.exe -l -w 32 wc.exe -l -a 33 wc.exe -c -w 34 wc.exe -c -a 35 wc.exe -w -a 36 
37 //有-e,但无停用词表文件名 38 wc.exe -l -w file.c -e 39 wc.exe -c -w file.c -e 40 wc.exe -w -a file.c -e 41 
42 //有-o,但无输出文件名 43 wc.exe -l -c -w -a file.c -e stop.txt -o 44 wc.exe -l -c -w -a -s *.c -e stop.txt -o 45 
46 //有-s,但无"*.c"
47 wc.exe -l -c -w -a -s -e stop.txt 48 wc.exe -l -c -w -a -s -e stop.txt -o out.txt

在终端中输入上述测试命令后,程序可以正常运行,且按我自己对需求的理解,运行输出均无误。

此外,在BIN文件夹中加入了.bat的测试脚本文件,双击他运行,通过对控制台的输出的对比,也可进行测试。

 

参考文献链接:

Git教程 - 廖雪峰的官方网站

https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

java获取当前路径的几种方法 - CSDN博客

http://blog.csdn.net/chengzhaoan2010/article/details/78344791

java.io.File类基本使用——遍历某路径的所有文件夹及文件 - CSDN博客

http://blog.csdn.net/u012325167/article/details/50856515

手把手教你如何把java代码,打包成jar文件以及转换为exe可执行文件 - CSDN博客

http://blog.csdn.net/sunkun2013/article/details/13167099