本人github地址:  https://github.com/wenthehandsome23

psp阶段

预估耗时

(分钟)

实际耗时

(分钟)

计划 30 10
估计这个任务需要多少时间 20 20
开发 600 660
需求分析 (包括学习新技术) 40 60
生成设计文档 60 30
设计复审 (和同事审核设计文档) 30 20
代码规范  10 0
具体设计 50 30
具体编码 500 600
基本功能实现 150 200
扩展功能实现 350 400
测试(自我测试,修改代码,提交修改) 60 50
报告 300 300
代码复审 30 20
测试报告 60 120
计算工作量 5 5
事后总结, 并提出过程改进计划 10 10
合计    
     

一 . 解题思路

  在拿到题目后,自己回想了一下,自己学过java,以前学习C语言时做过统计字数的作业,但是类似命令行的操作输入我还没做过,相关接触也就只有在使用虚拟机进行命令行操作时有所了解,于是上网查找了如下内容:

    http://blog.csdn.net/mingover/article/details/57083176(java命令行实现的参考)

    http://www.jb51.net/article/83792.htm(java命令行实现的参考)

    http://blog.csdn.net/huawangxin/article/details/53296918(BufferReader参考使用)

  在阅读相关资料后,发觉网上相关程序与题目要求并不符合,比如命令行功能无法实现,以及扩展功能未加入等,但是随后分析了一下需求,发现读取文件进行遍历是最核心的功能,读取文件使用的是BufferReader函数,这也是大部分网上的类似程序普遍使用的函数,因此可以确定我在编程过程中必然会使用到这个函数。

二. 设计过程

    大致思路就是先实现基本功能再实现命令行功能最后实现扩展功能,基本功能模块中的行数,字符数统计较为简单,使用简单的累加就可以实现,然而词数统计一开始设计的也比较简单,再后来添加停用词表功能时发现自己还是太年轻,被教做人了,推倒重来进行重写。命令行的实现则全部放入主函数,对输入进行遍历,以空格进行分割,之后判断句子中的成分,调用不同的类。最后关于扩展功能,每一个都单独一个功能函数进行实现,统计其他行数在统计行数的基础上加了判断,停用词表首先读取相关文档,然后新建一个数组,存放文档中读取到的数据,最后从原文档中取消对停用词表内容的计数。

  关于——s的内容:递归处理

  最后,设计类包括

  1.   countC:字符计数
      countW:单词计数
      countNt 其他行计数
      buildRes 文件名前缀
      List<String>: 停用词表设计
      main 主进程函数

三. 代码说明

  根据我的开发过程我逐步阐述我的代码:

  1. public static int countC(String fn){//统计字符数
  2. BufferedReader reader = null;
  3. int res=0;
  4. try {
  5. reader = new BufferedReader(new FileReader(fn));
  6. String str = null;
  7. while ((str = reader.readLine()) != null) {
  8.  
  9. res += str.length();
  10. }
  11. } catch (FileNotFoundException e) {
  12. e.printStackTrace();
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. }finally {
  16. try {
  17. reader.close();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. return res;
  23.  
  24. }

  这是统计字符数的代码,十分简单,但是值得注意的是一开始我是把基础功能全部写在一个函数里面,但是后来随着停用词表的功能需要完善,原本的函数会因为参数过多无法正常运行,所以只有重新把三个基础功能分别写三个函数,为了方便,统一返回为res,这说明在开发过程中应该不止着眼于眼前的功能的完善,更应该有一个长远的考量。

  1. public static int countW(String fn,List<String> list){//统计单词书目,
  2. BufferedReader reader = null;
  3. int res=0;
  4. try {
  5. reader = new BufferedReader(new FileReader(fn));
  6. String str = null;
  7. while ((str = reader.readLine()) != null) {
  8. String[]temp=str.split(" |,");
  9. for(String s:temp){
  10. if(s!=null&&!list.contains(s)){
  11. ++res;
  12. }
  13. }
  14. }

  当同时在命令行输入-e -w时,若不做处理,把这两个功能写入一个函数中,很有可能出现冲突报错,所以引入List<String>来统计此表内容,单独将对停用词表的处理写作一个函数,包括了读取文件,返回结果添加文件名作为前缀,因此在单词统计中会判断是否有停用词表并做相应处理。

  1. public static List<String> read(String fn){ //取消统计词表
  2. List<String> list=new ArrayList<String>();
  3.  
  4. BufferedReader reader = null;
  5.  
  6. try {
  7. reader = new BufferedReader(new FileReader(fn));
  8. StringBuilder sb=new StringBuilder();
  9. String s=null;
  10. while((s=reader.readLine())!=null){
  11. sb.append(s);
  12. sb.append(" ");
  13. }
  14. String[] arr=sb.toString().split(" ");
  15. Arrays.stream(arr).forEach(x->{
  16. list.add(x);
  17. });
  18.  
  19. } catch (FileNotFoundException e) {
  20. e.printStackTrace();
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }finally {
  24. try {
  25. reader.close();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. return list;
  31. }
  1. public static int[] countNt(String fn){//统计其他行数
  2. BufferedReader reader = null;
  3. int res=0;
  4. int emptyLine=0,codeLine=0,noteLine=0;
  5. try {
  6. reader = new BufferedReader(new FileReader(fn));
  7. String str = null;
  8. while ((str = reader.readLine()) != null) {
  9. str=str.trim();
  10. if(str==null||str.equals("")){
  11. emptyLine++;
  12. }else
  13. if(str.startsWith("//")) {
  14. ++noteLine;
  15. }else{
  16. codeLine++;
  17. }

  鉴于把所有行数统计放入一个函数会大大降低可读性,此处把-a命令行的功能单独写一个函数,并把代码行,空行,注释行都作为返回数组的一部分,在主函数中输出就会方便许多,因为涉及到空行,所以在运行时使用了trim函数,删除每一行中开头和结尾的空格,防止对空格发生误判,把代码行当做空行进行计数。以下为输出函数:

  1. public static String buildRes(String fn,int[] res){//输出部分添加文件名
  2. StringBuilder sb=new StringBuilder();
  3. sb.append(fn+",代码行/空行/注释行:"+res[0]+"/"+res[1]+"/"+res[2]);
  4. return sb.toString();
  5. }
  1. public static void main(String[] args) {//主进程函数
  2.  
  3. int cNum=0,lNum=0,wNum=0;
  4. int aLine[];
  5. List<String>list=new LinkedList<String>();
  6. final String[] p = {"-c", "-a", "-l", "-w", "-o","-s","-e"};
  7. Scanner sc = new Scanner(System.in);
  8. System.out.println("Please Enter Your Command:");
  9. String cmd = sc.nextLine();
  10. sc.close();
  11. String[] parame = cmd.split(" ");
  12. int len = parame.length;
  13. String inName = null;
  14.  
  15. for (int i = 1; i < len; ++i) {
  16. boolean flag = false;
  17. for (int j = 0; j < p.length; ++j) {
  18. if (parame[i].equals(p[j])) {
  19. flag = true;
  20. break;
  21. }
  22. }
  23. if (flag == false) {
  24. inName = parame[i];
  25. break;
  26. }
  27. }
  28. String outName = null;
  29. StringBuilder res=new StringBuilder();
  30.  
  31. try {
  32. for (int i = 1; i < len; ++i) {
  33. if (parame[i].equals("-c")) {
  34. cNum=countC(inName);
  35. res.append(buildRes(inName,'c',cNum));
  36. } else if (parame[i].equals("-l")) {
  37. lNum=countL(inName);
  38. res.append(buildRes(inName,'l',lNum));
  39. } else if (parame[i].equals("-w")) {
  40. if(list.size()==0){
  41. for(int j=i+1;j<len;++j){
  42. if(parame[j].equals("-e")){
  43. list=read(parame[j+1]);
  44. break;
  45. }
  46. }
  47. }
  48. wNum=countW(inName,list);
  49. res.append(buildRes(inName,'w',wNum));
  50. } else if (parame[i].equals("-o")) {
  51. outName = parame[i + 1];
  52. } else if (parame[i].equals("-e")) {
  53. String stopFile = parame[i + 1];
  54. list=read(stopFile);
  55. } else if (parame[i].equals("-s")) {
  56.  
  57. } else if (parame[i].equals("-a")) {
  58. aLine=countNt(inName);
  59. res.append(buildRes(inName,aLine));
  60. }
  61. }
  62.  
  63. outName = outName == null ? "result.txt" : outName;
  64.  
  65. FileWriter writer = new FileWriter(outName);
  66. writer.write(res.toString());
  67. writer.close();
  68.  
  69. } catch (IOException e) {
  70. e.printStackTrace();
  71. }
  72.  
  73. }

  主进程函数,把所有的命令行操作单独列出来供后续输入判断,scan进行输入,以空格作为命令行的分割,输入不同的命令行,调用不同的函数,最后再把结果写入目标文件,如果没有注明目标文件,则默认写入result.txt

三. 测试设计过程

  在这次项目过程中,我设计了15个测试用例,其中包含了单元测试以及功能测试,以下是代码:

  1. public static void testC(){
  2.  
  3. String cmd="wc.exe -l -c 1.txt";
  4. Javatest.execute(cmd.split(" "));
  5. }
  6.  
  7. public static void testW(){
  8.  
  9. String cmd="wc.exe -a -w 1.txt";
  10. Javatest.execute(cmd.split(" "));
  11. }
  12.  
  13. public static void testO(){
  14.  
  15. String cmd="wc.exe 1.txt -a -o 2.txt";
  16. Javatest.execute(cmd.split(" "));
  17. }

  这部分是单个功能模块的测试,主要看基本功能是否可以顺利完成

  1. public static void testTri2(){//对多种功能进行测试
  2. String cmd="wc.exe 1.txt -a -e 3.txt -o 2.txt";
  3. Javatest.execute(cmd.split(" "));
  4. }
  5. public static void testEmptyStopFile(){//对停用词表进行测试
  6.  
  7. String cmd="wc.exe 1.txt -e 3.txt -o 2.txt";
  8. Javatest.execute(cmd.split(" "));
  9. }
  10.  
  11. public static void testE(){//对停用词表以及其他功能进行测试
  12.  
  13. String cmd="wc.exe 1.txt -a -c -w -e 3.txt -o 2.txt";
  14. Javatest.execute(cmd.split(" "));
  15. }
  16.  
  17. public static void testTri1(){//对多种功能进行测试
  18. String cmd="wc.exe 1.txt -l -w -c -o 2.txt";
  19. Javatest.execute(cmd.split(" "));
  20. }
  21.  
  22. public static void testS(){//对遍历功能进行测试
  23. String cmd="wc.exe -s -a -c -w -e 3.txt -o 2.txt";
  24. Javatest.execute(cmd.split(" "));
  25. }

  这是对扩展功能进行测试,覆盖了主要语句,众所周知,测试的高风险点包括代码中包含分支判定及循环的位置,在测试中采用的语句覆盖的方法覆盖到了所有程序代码语句,用以应对高风险点。

  1. public static void testEmptyFile(){//输入文件为空时测试
  2.  
  3. String cmd="wc.exe -a -w -o 2.txt";
  4. Javatest.execute(cmd.split(" "));
  5. }
  6.  
  7. public static void testEmptyStop(){//停用词表为空时测试
  8.  
  9. String cmd="wc.exe 1.txt -e";
  10. Javatest.execute(cmd.split(" "));
  11. }
  12. public static void testEmptyStop(){//停用词表为空时测试
  13.  
  14. String cmd="wc.exe 1.txt -e";
  15. Javatest.execute(cmd.split(" "));
  16. }

  这是出错情况的测试,包括文件输入为空的情况,说明我还有很多需要完成的完善的地方

  1. public static void utestC(){ //字数统计单元测试
  2. String name="1.txt";
  3.  
  4. if (Javatest.countC(name)!=0){
  5. System.out.println("true");
  6. }
  7. }
  8. public static void utestW(){ //单词统计单元测试
  9. String name="1.txt";
  10.  
  11. if (Javatest.countW(name,null)!=0){
  12. System.out.println("true");
  13. }
  14. }
  15. public static void utestL(){ //行数统计单元测试
  16. String name="1.txt";
  17.  
  18. if (Javatest.countL(name)!=0){
  19. System.out.println("true");
  20. }
  21. }
  22. public static void utestA(){ //其他行数统计单元测试
  23. String name="1.txt";
  24.  
  25. if (Javatest.countNt(name)[0]!=0&&Javatest.countNt(name)[1]!=0&&Javatest.countNt(name)[2]!=0){
  26. System.out.println("true");
  27. }
  28. }
  29. public static void utestSL(){ //取消词表单元测试
  30. String name="1.txt";
  31.  
  32. if (Javatest.read(name)!=null){
  33. System.out.println("true");
  34. }
  35. }

  最后是单元测试,确保每一个功能函数可以正常运行,如果该单元正常运行,则返回true,结果如下图:

四. 文献引用:

http://blog.csdn.net/mingover/article/details/57083176(java命令行实现的参考)

    http://www.jb51.net/article/83792.htm(java命令行实现的参考)

    http://blog.csdn.net/huawangxin/article/details/53296918(BufferReader参考使用)

总结:自己还是太菜了,要多学习啊,感觉一路问了很多大佬,尤其感谢OldBook,对他的指导的感激之情无以言表,以后不止要好好学习测试这门课,还很有必要读一下java的源代码!

软件测试第二周作业 WordCount的更多相关文章

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

    github地址: https://github.com/wzfhuster/software_test_tasks psp表格: PSP2.1 PSP 阶段 预估耗时 (分钟) 实际耗时 (分钟) ...

  2. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  3. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  4. Java第二周作业

    Java第二周作业 本周作业: 参考http://www.cnblogs.com/rocedu/p/7911138.html 学习第二三章视频 参考http://www.cnblogs.com/roc ...

  5. C语言--第二周作业评分和总结(5班)

    作业链接:https://edu.cnblogs.com/campus/hljkj/CS2017-5/homework/1026 一.评分要求 要求1 阅读指定博客+阅读收获+例子.(5分) 要求2 ...

  6. 结队第二次作业——WordCount进阶需求

    结队第二次作业--WordCount进阶需求 博客地址 051601135 岳冠宇 博客地址 051604103 陈思孝 博客地址 Github地址 具体分工 队友实现了爬虫功能,我实现了wordco ...

  7. 2017-2018-1 Java小组-1623 第二周作业

    2017-2018-1 Java小组-1623 第二周作业 关于游戏软件的问题 讨论结果 20162301张师瑜 20162305李昱兴 20162306陈是奇 20162308马平川 2016231 ...

  8. 2017-2018-1 JAVA实验站 第二周作业

    2017-2018-1 JAVA实验站 第二周作业 小组成员: 组长 20162318张泰毓 成员 20162303石亚鑫 20162304张浩林 20162307张韵琪 20162321王彪 201 ...

  9. 2017-2018-1 20179205《Linux内核原理与设计》第二周作业

    <Linux内核原理与分析>第二周作业 本周视频学习情况: 通过孟老师的视频教程,大致对风诺依曼体系结构有了一个初步的认识,视频从硬件角度和程序员角度对CPU和Main Memory(内存 ...

随机推荐

  1. 使用MyBatis集成阿里巴巴druid连接池(不使用spring)

    在工作中发现mybatis默认的连接池POOLED,运行时间长了会报莫名其妙的连接失败错误.因此采用阿里巴巴的Druid数据源(码云链接 ,中文文档链接). mybatis更多数据源参考博客链接 . ...

  2. Qt 信号如何自动连接槽函数?

    on_objectName_signal [static] void QMetaObject::connectSlotsByName(QObject *object) void on_<obje ...

  3. 《android开发艺术探索》读书笔记(十四)--JNI和NDK编程

    接上篇<android开发艺术探索>读书笔记(十三)--综合技术 No1: Java JNI--Java Native Interface(java本地接口),它是为了方便java调用C. ...

  4. UVA-714 二分

    把可能的进行二分判断,判断的时候尽量向右取,一直取到不能去为止,这样才有可能成功分割. 判断是否可以把up作为最大值的代码: bool judge(LL up){ if(up < Big) re ...

  5. MySQL基础学习笔记

    一.数据库基本概念 1.1 数据库 - Database 从字面意思看,数据库就是一个存储数据的仓库.从计算机的角度来讲,数据库(Datebase)是按照数据结构来组织.存储和管理数据的仓库. 简单来 ...

  6. python小练习之读取文件写入excel

    文件是个json文件 内容为: 导入excel后的格式为 屡一下思路 一步步怎么实现: 1 首先需要读取json文件 然后将读取的内容转为字典 2 将excel的列名写入一个list中 然后遍历执行写 ...

  7. 搜索引擎case︱从搜索序列文本看高端商务车︱统计之都

    朱雪宁(北京大学光华管理学院)               王汉生(北京大学光华管理学院) 摘要:本文对100万搜索引擎用户的13亿搜索序列文本进行探索分析,对高端车用户以及商学院人群做了描述对比,并 ...

  8. HighCharts中的无主题的2D折线图

    HighCharts中的无主题的2D折线图 1.设计源码 <!DOCTYPE html> <html> <head> <meta charset=" ...

  9. jquery Dialog弹框插件

    function Dialog(options) { var defaults = { // 默认值. title: '', // 标题文本,若不想显示title请通过CSS设置其display为no ...

  10. e.preventDefault()和e.stopPropagation()以及return false的作用和区别

    前段时间开发中,遇到一个父元素和子元素都有事件时,发现会出现事件冒泡现象,虽然知道ev.stopPropagation()和ev.preventDefault()其中一个是阻止事件冒泡和阻止默认行为, ...