写在开头

合作者 201631062606-张馨艺, 201631062620-杨康
代码地址  https://gitee.com/YKszy/wordCount
本次作业的链接地址  https://edu.cnblogs.com/campus/xnsy/Test/homework/2203

0、代码完成情况

1.变量定义

    private static final ArrayList<String> wordsIgnored = null;//停用词public static String inputFile="test.txt";        //默认输入文件public static String outputFile="result.txt";    //默认输出文件public static int charCount = 0;                //计数变量public static int wordCount = 0;public static int lineCount = 0;public static String comCount = null;public static boolean ifCountChar = false;        //标志变量public static boolean ifCountWord = false;public static boolean ifCountLine = false;public static String stopList;                    //存储停用词private static Component chatFrame;

变量定义

2. 命令行参数解析

for(int i =0 ; i<args.length;i++){            //命令解析if(args[i].contains(".txt")){            //获取输入文件inputFile=args[i];}else if("-c".equals(args[i])){ifCountChar = true;}else if("-w".equals(args[i])){ifCountWord = true;}else if("-l".equals(args[i])){ifCountLine = true;}else if("-o".equals(args[i])){if(i+1 < args.length){                //获取输出文件outputFile = args[i+1];}}else if("-x".equals(args[i])){inputFile=Graphing();}else if("-a".equals(args[i])){comCount = countComponet(inputFile);}else if("-e".equals(args[i])){stopList = args[i+1];getStopList();StopListSelect(outputFile);}else if("-s".equals(args[i])){List<String> resultFileName = new ArrayList<String>();System.out.println("请选择一个地址来判断:");//File file = new File(Graphing());
                File file = new File("C:\\testWC");//选择路径,修改也可以
                typeIstxt(ergodic(file, resultFileName));}else{System.out.println("请输入正确命令");}

命令行参数解析

3. 字符数统计

    public static int CountChar(String fileName){int count = 0;File file = new File(fileName);FileInputStream in = null;InputStreamReader reader = null;//打开文件try{in = new FileInputStream(file);reader = new InputStreamReader(in);int tempChar;while((tempChar = reader.read()) != -1){    //读取文件if((char)tempChar != '\r'){            //注意linux和windows下换行符的区别count++;}}}catch (IOException e) {        //错误补货// TODO: handle exception
            e.printStackTrace();}finally {try {reader.close();} catch (IOException e) {// TODO 自动生成的 catch 块
                e.printStackTrace();}}return count;}

字符数统计

4. 单词数统计

 1 //单词数统计
 2     public static int CountWord(String fileName){
 3         //打开文件
 4         int count = 0;
 5
 6         File file = new File(fileName);
 7         FileReader fr = null;
 8         BufferedReader br = null;
 9
10
11         try{
12             fr = new FileReader(file);
13             br = new BufferedReader(fr);
14
15             String tempStr = "";
16             while((tempStr = br.readLine()) != null){ //按行读取
17
18                 count += tempStr.split("\\s+|,").length;
19             }
20         }catch (Exception e) {
21             e.printStackTrace();
22         }finally{
23             try{
24                 br.close();
25                 fr.close();
26             }catch(Exception e) {
27                 // TODO: handle exception
28                 e.printStackTrace();
29             }
30         }
31
32         return count;
33
34     }

单词数统计

5. 行数统计

 1     //行数统计
 2     public static int CountLine(String fileName){
 3         int count = 0;
 4
 5         File file = new File(fileName);
 6         FileReader fr = null;
 7         BufferedReader br = null;
 8
 9         try{
10             fr = new FileReader(file);
11             br = new BufferedReader(fr);
12
13             String tempStr = "";
14             while((tempStr = br.readLine()) != null){ //按行读取
15                 count++;
16             }
17         }catch (Exception e) {
18             // TODO: handle exception
19             e.printStackTrace();
20         }finally{
21             try{
22                 br.close();
23                 fr.close();
24             }catch(Exception e) {
25                 // TODO: handle exception
26                 e.printStackTrace();
27             }
28         }
29
30         return count;
31     }

行数统计

6. 代码行/空行/注释行统计

 1     //代码行/空行/注释行统计
 2     public static String countComponet(String fileName){
 3
 4         int codeLine = 0;//代码行
 5         int commentaryLine = 0;//注释行
 6         int brankLine = 0;//空行
 7
 8         String currentLine = "";
 9
10         File file = new File(fileName);
11         FileReader fr = null;
12         BufferedReader br = null;
13
14         try{
15             fr = new FileReader(file);
16             br = new BufferedReader(fr);
17
18             while ((currentLine=br.readLine()) != null){    //按行读取
19                 if (currentLine.trim() != "" && !(currentLine.trim().startsWith("//"))){//代码行
20                     codeLine++;
21                 }else if (currentLine.trim().startsWith("//")){//注释行
22                     commentaryLine++;
23                 }else{    //空行
24                     brankLine++;
25                 }
26             }
27         }catch (Exception e) {
28             // TODO: handle exception
29             e.printStackTrace();
30         }finally {
31             try {
32                 br.close();
33             } catch (IOException e) {
34                 // TODO 自动生成的 catch 块
35                 e.printStackTrace();
36             }
37         }
38
39         return fileName + ", 代码行 / 空行 / 注释行: " + codeLine + "/" + brankLine + "/" + commentaryLine;
40     }

代码行/空行/注释行统计

7. 递归处理文件

 1     ///递归读取目录下所有文件
 2     private static  List<String> ergodic(File file,List<String> resultFileName){
 3         File[] files = file.listFiles();
 4         if(files==null)return resultFileName;// 判断目录下是不是空的
 5         for (File f : files) {
 6             if(f.isDirectory()){// 判断是否文件夹
 7                 ergodic(f,resultFileName);// 调用自身,查找子目录
 8             }else{
 9                 if(whetherExistTXTFile(f.getPath())==true){
10                     resultFileName.add(f.getPath());
11                 }
12             }
13         }
14         return resultFileName;
15     }

递归处理文件

8. 停用词表处理

 1     //停用词表
 2     public static void getStopList()
 3     {
 4
 5         try
 6         { // 防止文件未建立或读取失败,用catch捕捉错误并打印,也可以throw
 7
 8             /* 读入stopList */
 9             File filename = new File(stopList); // 要读取以上路径的input。txt文件
10             InputStreamReader reader = new InputStreamReader(new FileInputStream(filename)); // 建立一个输入流对象reader
11             BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
12             String line ;
13             line = br.readLine();
14             while (line != null)
15             {
16                 //将读取的行分割成各个单词
17                 String str[] = line.split(" ");
18
19                 for (String string : str) {
20                       wordsIgnored.add(string);  //将停用词表中的单词放入数组wordsIgnored
21                 }
22
23                 line = br.readLine(); // 一次读入一行数据
24             }
25             br.close();
26         }
27         catch (IOException e)
28         {
29             e.printStackTrace();
30         }
31     }

停用词表处理

最后. 运行结果:

测试文件:

  

基本功能测试:

扩展功能测试:

1、代码互审情况

1.1 约定编码规范

  经需求商议,因为程序主要为对字符串的处理,所以选定开发语言为Java。此外,约定代码规范参照邹欣老师的讲义“现代软件工程讲义3-代码规范与代码评审”

1.2 代码审查并修正

  在交换以及合并各自代码的过程中,发现了如下问题并给予了修正:

  1)对不够充分的注释进行了修改与增加

  2)删除了无意义的注释

  3)统一了我们俩的断行与空白的{}行的代码风格

  4)异常处理,统一在函数内处理而不是抛出到调用者  

  5)增强了程序的容错性,增加了必要的错误输入处理以及用户提示

  5)在进行代码合并时,可以考虑对代码结构进行了优化,将一个包含了命令解析、统计以及文件操作的WordCount类拆分成了三个类

    1. 主程序Program类

    2. WordCount,字符处理类

    3. FileOper,文件操作类

2、静态代码检查情况

2.1 选择静态代码检查工具:

findGug —— FindBugs 是由马里兰大学提供的一款开源 Java 静态代码分析工具。FindBugs 通过检查类文件或 JAR 文件,将字节码与一组缺陷模式进行对比从而发现代码缺陷,完成静态代码分析。FindBugs 既提供可视化 UI 界面,同时也可以作为 Eclipse/MyEclipse 插件使用。Findbugs规则比较简单实用,不注重样式与格式,属于轻量级的工具。

2.2 在eclipse中安装findbugs插件

  参照指南“FindBugs_IDEA插件的使用”

  P.S:记得在show view中添加findbugs explore视图

2.3 findbug常见错误信息:

a. Bad practice 代码中的一些坏习惯

Class names should start with an upper case letter 主要包括类名的命名,以大写字母开头
equals()method does not check for null argument equals()方法应该检查非空
Class defines equals() and uses Object.hashCode() 一个类覆写了equals方法,没有覆写hashCode方法,使用了Object对象的hashCode方法
Method ignores exceptional return value 方法忽略返回值的异常信息
Equals method should not assume anything about the type of its argument equals(Object o)方法不能对参数o的类型做任何的假设。比较此对象与指定的对象。当且仅当该参数不为 null,并且是表示与此对象相同的类型的对象时,结果才为 true。
Comparison of String objects using == or != 用==或者!=去比较String类型的对象

b. Dodgy code 糟糕的代码

Switch statement found where default case is missing Switch没有默认情况下执行的case语句
Switch statement found where one case falls through to the next case Switch语句中一个分支执行后又执行了下一个分支。通常case后面要跟break 或者return语句来跳出。
Dead store to local variable 该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。
Write to static field from instance method 在实例方法写入静态字段
Redundant nullcheck of value known to be non-null 方法中对不为空的值进行为空的判断。
Method uses the same code for two branches 此方法使用相同的代码,以实现两个有条件的分支。检查以确保这是不是一个编码错误

c. Performance 关于代码性能相关方面的

Boxing/unboxing to parse a primitive 类型转换 比如字符串转换成int 应该使用Integer.parseInt(“”) 代替Integer.valueOf(“”)
Method concatenates string using + in aloop
每次循环里的字符串+连接,都会新产生一个string对象,在java中,新建一个对象的代价是很昂贵的,特别是在循环语句中,效率较低
解决办法:使用StringBuffer或者StringBuilder重用对象。

d. Malicious code vulnerability 关于恶意破坏代码相关方面的

May expose internal representation by incorporating reference to mutable object
此代码把外部可变对象引用存储到对象的内部表示。如果实例受到不信任的代码的访问和没有检查的变化危及对象和重要属性的安全。存储一个对象的副本,在很多情况下是更好的办法。
Field isn’t final but should be 此字段前应该加final
Field isn’t final and can’t be protected from malicious code 此字段前应该加final
Field should be package protected
一个静态字段是可以被恶意代码或其他的包访问修改。可以把这种类型的字段声明为final类型的以防止这种错误。

e. Multithreaded correctness 关于代码正确性相关方面的

Static DateFormat DateFormat 在多线程中本身就是不安全的,如果在线程范围中共享一个DateFormat的实例而不使用一个同步的方法在应用中就会出现一些奇怪的行为。
Call to static DateFormat DateFormats多线程使用本事就是不安全的,改进方法:需要创建多实例或线程同步

2.4 执行静态测试:

结果分析:

a.主要是输入输出流的关闭问题,比如代码reader.close(),会有" xx is null guaranteed to be dereferenced in wc.WordCount"错误。

reader是在catch代码块中进行的初始化操作,findbug对该bug说的很明白,说如果出现异常,reader将保证为空,因为很显然如果出现异常,reader将得不到正确的初始化,即便初始化了,因为异常的出现,引用也会被解除,回到一开始定义处的null状态,那么在这里的finally代码块中调用reader的close()方法,将报空指针异常。

b.根据findbug提示" == or != 用==或者!=去比较String类型的对象 b. ",为了避免字符为空而产生异常,修改了使用!=来比较字符对象的情况。

3、单元测试情况

3.1、基础功能测试

1)设计测试用例

  设计测试用例采用的方法及思路:本次单元测试测试用例采用黑盒测试,主要采用等价类划分的方法来设计测试用例

2)测试用例

根据等价类划分结果设计测试用例:

且因为-o和输出文件名必须配合使用,设计测试用例:

  wc.exe -c inputFile.c -o

3.2、扩展功能测试

1)设计测试用例

  设计测试用例采用的方法及思路:本次单元测试测试用例采用黑盒测试,主要采用等价类划分的方法来设计测试用例

2)测试用例

根绝等价类划分结果设计测试用例:

P.S:又因为-e操作的特殊性,其后必须接有效文件名,所以设计以下测试用例

    wc.exe -c inputFile.c -e

3.3、单元测试工具的使用——JUnit

1)JUnit简介:

  Junit 是一个单元测试框架,使用 Junit 能让我们快速的完成单元测试。通常我们写完代码想要测试这段代码的正确性,那么必须新建一个类,然后创建一个 main() 方法,然后编写测试代码。如果需要测试的代码很多呢?那么要么就会建很多main() 方法来测试,要么将其全部写在一个 main() 方法里面。这也会大大的增加测试的复杂度,降低程序员的测试积极性。而 Junit 能很好的解决这个问题,简化单元测试,写一点测一点,在编写以后的代码中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度。

2)JUnit使用:

  a.导入JAR包,eclipse中内部集成了JUnit JAR包,项目-》右键-》构建路径-》添加库,选择JUnit4.0版本

  b.创建测试类:

    新建JUnit测试用例

    

    选择"正在测试的类”

    

    选择要进行测试的方法:

    

    构建结果

  

3)测试结果:

对CountComponet类的测试,因为其返回值是void也就是说,我们无法对方法的返回值进行断言。

但是,既然这个方法是无返回值的方法,那么他一定修改了对象的状态(成员变量),或是进行了输入输出,向某个窗口发送消息,与某个进程通讯,

总之,他是有副作用的。

如果没有任何副作用,并且无返回值,那么这个方法存在也是没有意义的,可以去掉。

那么我们就可以针对产生的副总用来进行断言。

具体测试代码如下

 1 package wc.test;
 2
 3 import static org.junit.Assert.*;
 4
 5 import java.lang.reflect.Field;
 6
 7 import org.junit.Assert;
 8 import org.junit.Test;
 9
10 import wc.WordCount;
11
12 public class WCTest {
13
14     @Test
15     public void testCountChar() {
16         int result = WordCount.CountChar("test.txt");
17         Assert.assertEquals(result, 32);
18     }
19
20     @Test
21     public void testCountWord() {
22         int result = WordCount.CountWord("test.txt");
23         Assert.assertEquals(result, 7);
24     }
25
26     @Test
27     public void testCountLine() {
28         int result = WordCount.CountLine("test.txt");
29         Assert.assertEquals(result, 5);
30     }
31
32     @Test
33     public void testCountComponet() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
34         WordCount wc = new WordCount();
35         Class<?> clazz = wc.getClass();
36         Field field = clazz.getDeclaredField("comCount");
37         field.setAccessible(true);
38         String comCountBefore = (String) field.get(wc);
39
40         assertEquals(null, comCountBefore);
41         WordCount.countComponet("test.txt");
42
43         String comCountAfter = (String) field.get(wc);
44         assertEquals("test.txt, 代码行 / 空行 / 注释行: 3/0/2",comCountAfter);
45     }
46
47
48 }

测试代码

4、测试总结与感悟

  通过本次测试合作,更深切的体会到结对编程提前沟通,相互交流,相互合作的重要性,总得来说我和我的搭档配合的很协调,分工明确,相互协商,最终完成了一个功能完善的wordCount。此外,通过亲自上手实践,了解了静态测试、单元测试的各种工具,熟悉了findBug和JUnit工具的安装和使用,更切身实地的参与到了软件测试中来,体会到软件测试的必要性,同时初步了解了性能测试,个人认为性能测试对于web项目以及高并发项目来讲是至关重要的。

  同时在我们进行代码合并以及优化的过程中,我们花了挺多时间修改各自的代码以使其能够运行到一起。这之中我们深切体会到了模块独立性“高内聚低耦合”的重要性,提前沟通好接口的一致性会为之后的代码合并很大的方便。对我而言是因为使用的是JAVA这种面向对象的语言,每个类有自己的成员变量,对这种面向对象的语言的模块独立性不是很清楚,还要继续学习。

5、参考文献

https://blog.csdn.net/weixin_38648597/article/details/79353875  常见文件操作

http://www.runoob.com/java/java-regular-expressions.html   Java正则表达式

https://blog.csdn.net/feibendexiaoma/article/details/72821781  findBUGs

https://www.cnblogs.com/ysocean/p/6889906.html JUnit入门教程

https://blog.csdn.net/u013803262/article/details/57075052 Java如何编写无返回值的方法的单元测试

转载于:https://www.cnblogs.com/chacha-z/p/9817130.html

软件测试第三次作业-worldCount相关推荐

  1. 软件测试第三次作业junit和Eclemma的使用

    1. 2.将第20行 for(int i = 0; i<=numPrimes-1;i++) 改为 for(int i = 0; i<numPrimes-1;i++) 3.n=2 4.节点覆 ...

  2. 软件测试 第三次作业

    (a) 将就一下锻炼颈椎吧,废了半天劲也没把图片正过来 (b) 改为isDivisiable( primes[0], curPrime) (c) n = 1 (d) Node Coverage: { ...

  3. OO第三单元作业总结

    OO第三次作业总结 一.JML (一)JML语言理论基础 (1)JML表达式: JML表达式包括以下几种: 原子表达式如\result(方法执行后的返回值).\old(表达式在相应方法执行前的取值): ...

  4. 程序设计第三次作业附加 代码规范

    题目:第三次作业附加 myGithub 我的程序设计第三次作业 Calculator.h //==============================// //文件名称:calculator.h ...

  5. JML规格编程——BUAA OO第三单元作业总结

    整体概述 这个单元整体围绕Java Model Language(JML)展开,通过学习JML规格了解契约式编程的过程,课上实验中进行了JML规格的简要编写,课下实验主要通过阅读规格并按照规格的要求正 ...

  6. 2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案

    简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程.所使用的遗传算法是最基本的遗传算法.利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化.对于不同的遗传 ...

  7. 2021年春季学期-信号与系统-第三次作业参考答案-第十一道题

    本文是 2021年春季学期-信号与系统-第三次作业参考答案 中的参考答案. ▌第十一道题 11. 如果已知系统的输入输出关系可以使用二阶常系数 差分方程来描述.如果相应输入为:x[n]=u[n]x\l ...

  8. 2021年春季学期-信号与系统-第三次作业参考答案-第十道题

    本文是 2021年春季学期-信号与系统-第三次作业参考答案 中的参考答案. ▌第十道题 10. 求解差分方程: (1)第一小题 y[n]=−5y[n−1]+ny\left[ n \right] = - ...

  9. 2021年春季学期-信号与系统-第三次作业参考答案-第九道题

    本文是 2021年春季学期-信号与系统-第三次作业参考答案 中的参考答案. ▌第九道题 9. 已知因果线性时不变系统的输入输出之间的微分方程为: ddty(t)+5y(t)=∫−∞∞x(τ)f(t−τ ...

  10. 2021年春季学期-信号与系统-第三次作业参考答案-第八道题

    本文是 2021年春季学期-信号与系统-第三次作业参考答案 中的参考答案. ▌第八道题 8. 某LTI系统,输入信号e(t)=2e−3tu(t)e\left( t \right) = 2e^{ - 3 ...

最新文章

  1. html5 graphics with svg css3,HTML5 GRAPHICS WITH SVG AND CSS3
  2. unity不规则碰撞_Unity UGUI学习系列(二) ------ PolygonCollider2D实现不规则碰撞范围
  3. 页面上一些小icon的制作方法及技术选择
  4. 什么是序列化?python pickle模块
  5. springframework包下的RequestContextHolder类和ServletRequestAttributes类的源码和使用
  6. bootbox显示中文的按钮
  7. Windows基础评测
  8. leetCode 28. Implement strStr() 字符串
  9. 概率校准与Brier分数
  10. 初学者注意:你需要明白编程的意义所在,否则是学不好编程的!
  11. Oracle11gr2新增APPEND_VALUES提示
  12. 设计模式学习总结7 - 行为型2 - Command命令模式
  13. python json转xml_Python实现XML到JSON的转换并编写,python,xml,转化,为,Json,进行,写入
  14. Overlay network
  15. flash读写学习笔记与spi接口及简单测试验证
  16. NetApp存储术语介绍
  17. duplicate from active dg 的 run 脚本 sfile 为完整配置可能导致的一些错误
  18. windows10如何截长图
  19. 国内B2C 26个经典购物网站商城收集
  20. 服务器系统装显卡驱动,GPU服务器安装NVIDIA显卡驱动

热门文章

  1. 最大似然参数估计的求解
  2. mysql 从后往前截取指定个数字符串_「截取字符串」substring从指定字符串开始截取 - seo实验室...
  3. oracle11g和10的区别,同平台升级 oracle 10 到 oracle11g的一些考虑和实际操作
  4. 推荐系统专利:一种信息推荐系统及方法
  5. 编程计算二叉树中某结点的层数
  6. FrameLayout AbsoluteLayout GridLayout用法及实例
  7. oppor17山寨机的特点_国产山寨厂商智慧生生不息:拼多多山寨手机仍在
  8. 随记-Git相关操作
  9. Q-learning和Sarsa
  10. 快速突破面试算法之图篇