wordCount总结
1.github地址:https://github.com/husterSyy/SoftTest
2.PSP表格
psp 2.1 | psp阶段 | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 10 | 5 |
Estimate | 估计这个任务需要多少时间 | 10 | 15 |
Deveploment | 开发 | 10 | 5 |
Analysis | 需求分析(包括学习新技术) | 30 | 30 |
Design Spec | 生成设计文档 | 20 | 10 |
Design Review | 设计复审(和同事审核设计文档) | 10 | 5 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 20 | 20 |
Design | 具体设计 | 30 | 50 |
Coding | 具体编码 | 380 | 400 |
Code Review | 代码复审 | 30 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 150 | 200 |
Reporting | 报告 | 10 | 10 |
Test Report | 测试报告 | 20 | 30 |
Size Measurement | 计算工作量 | 5 | 10 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 10 | 20 |
合计 | 745 | 830 |
3.解题思路
根据老师给定的需求,从基本功能开始,实现-c -w -l 功能,完成基本功能后,进行第一次代码commit 到github.
在基本功能基础上,分析扩展功能,由于扩展功能较为复杂,故我将逐个实现 -s -a -e功能,并进行单个测试,最后统一整理,编码运行成功后,进行全部功能测试。
输入均用主函数自带的String args[]参数进行接收,对接收的字符进行判断,从而进行对应操作。
对于输出到文件实现,若未指定具体输出,则默认为result.txt,否则输出到-o后面的文本中。
若用-s *.c命令,则遍历得到的符合条件文本,分别输出各文本的指定输出,如字符,单词,行数等。
4.程序设计实现过程
由于思路是从基本功能出发,进而为扩展功能,故我的程序只有一个类,这个类包含了一个主函数,其他单个功能 -c -w -l -s -a -e 分别在单个函数实现,对应函数命名为:
统计字符数 countCharacters, 统计单词数 countWords ,统计所有行数 countLines ,读取给定目录下的符合条件的文本 readAllFile, 统计给定文本的代码行,空行,注释行 countDLines , 统计除停用文本的单词外其它所有单词总数countWordsS.
函数 countCharacters,countWords,countLines实现:
http://blog.sina.com.cn/s/blog_680288f00100l6a2.html
单词定义为用逗号或空格隔开的,非仅为英文字母组成的,如{ ,}算两个单词,//也算单词。
采取BufferedReader 读取文件,用br.read()函数并用int类型接收该函数返回的数值,返回值是否等于-1判断是否读到文件末尾,
当未读到尾部时,对读取的字符进行判断,当为单词间的空格或逗号时,字符加1,单词加1,当为换行符,单词数,行数分别进行加1,若出现连续的空格且空格不在单词间则跳过,不计入字符数,无意义。
同时对于read函数,经调用发现读取文本最后一行回车换行并另起一行空格,最后才读到-1,文件末尾,故对于此种情况跳过,不能对行数进行加1.
函数countDLines实现:
若空行{或一个字母位置或代码行在注释行内,则此行仅属于注释行,不计入代码行和空行。
对于代码行,空行,注释行判断,定义一个大小为3的数组,利用readline()函数读取一行字符串内容,当读取的内容长度不超过1时,空行加1,当读取的内容以“//”为开始startsWith(),进行注释行加1,当读取的内容以“/*”开始,"*/"结束endsWith(),计算该注释包含的所有行,其他均为代码行。
函数countWordsS实现:
https://www.cnblogs.com/fqfanqi/p/6187085.html
对于除停用词外的单词计数实现,读取源文件和停用文件的字符内容,分别提取对于文本的单词(split()+正则表达式)存到字符串数组,定义可动态增长的数组,遍历源文件,将源文件存到动态数组中,并将其转换成map<String,Integer>数据结构,便于计算单词数,对于停用词动态数组,进行遍历,若map集合键含有该单词,将其从map集合移除,最后遍历map统计得到的单词总数。
函数readAllFile实现:
https://www.cnblogs.com/linuxjava/p/6435911.html
遍历指定格式的文本 实现:对传入的文本进行判断,若为文件目录,继续遍历该目录下的子目录包括文本,若为文本且符合指定格式,则将其添加到存放文件名的动态数组。最后返回得到的存放指定目录下或子目录下的符合格式的文本文件。
5.代码说明
关键代码:
sourceFile为符合条件的文件数组
cflag,wflag,aflag,lfag初始定义为false,当键盘输入的是-c 则cflag置为true,同理对-w -l -a。
遍历从readAllFile得到的文件,根据从键盘输入的字符判断是否需要统计字符数,单词数,总行数,还是代码行/空行/注释行。
因为需求给定输出的内容和输入顺序无关,输出的顺序均为字符-->单词-->行数-->代码行数/空行数/注释行的顺序,依次分行显示,
故文本输出时按照打印输出顺序判断,确保输出到文本的顺序。
当采用 -e命令则不统计停用表中单词,则选用countWordsS函数输出单词数,否则看是否有 -w 命令有则输出总单词数。
while(j<sourceFile.length){ name=sourceFile[j].getName(); if(eflag){ str1=name+", 单词数: "+countWordsS(sourceFile[j], stopFile); bw.write(str1+"\r\n"); } if(cflag){ str1=name+", 字符数: "+countCharacters(sourceFile[j]); bw.write(str1+"\r\n"); } if(!eflag&&wflag){ str1=name+", 单词数: "+countWords(sourceFile[j]); bw.write(str1+"\r\n"); } if(lflag){ str1=name+", 行数: "+countLines(sourceFile[j]); bw.write(str1+"\r\n"); } //注释行代码行空行 if(aflag){ str1=name+", 代码行/空行/注释行: "; int[] lines=countDLines(sourceFile[j]); str1+=""+lines[0]+"/"+lines[1]+"/"+lines[2]; bw.write(str1+"\r\n"); } j++; }
6.测试设计过程
关于测试,我选择了以下测试方案:
(1)对同一命令行采取对多个具有不同内容的文本测试,且文本写入的内容具有程序针对性。
(2)对同一文本采取多个命令行随机测试。
(3)根据程序给定的需求进行多组测试。
(4)对程序其他方面异常测试,如文件路径不存在和用户恶意输入测试等。
如下选择了较为典型的测试用例:
需求功能测试:
测试命令:
基本功能:
1) -c -w -l f:\c.txt
测试文本:磁盘F路径下的c.txt
#$Vs w int main,this printf
输出文本:未指定则为result.txt
c.txt,字符数:25 c.txt,单词数:6 c.txt,行数:4
2) 基本命令: -c -w -l file1.c -o output.txt
测试文本:
file1.c
int main
{
return
}
//
/**/
输出文本:output.txt
file1.c,字符数:22 file1.c,单词数:7 file1.c,行数:6
扩展功能:
3) 测试命令:-l -s *.c -w -e stop.txt
测试文本内容:
源文本:
file.c
int main
{
return
}
//
/*
int main()
a
*/
file1.c
int main
{
int a=1;
return
}
//
/**/
停用词文本:stop.txt
int main
输出文件:默认result.txt
file.c,单词数:8 file.c,行数:9 file1.c,单词数:6 file1.c,行数:7
4) 测试命令: -l -c -a wordCount.c -o output.txt
测试文本内容: wordCount.c
#include <stdio.h> //主函数 /*int a() { int b=1; } */ int main() { printf ("hello"); return 0; }//函数结束
输出文本:output.txt
wordCount.c,字符数:88 wordCount.c,行数:12 wordCount.c,代码行/空行/注释行:4/3/7
5) 测试命令:-s -l -c -w *.c -e stop.txt -o output.txt -a
符合条件的测试文本:
file.c
int main { return } // /* int main() a */
file1.c
int main { return } // /**/
停用词文本:stop.txt
int main
输出文本:output.txt
file.c,字符数:33 file.c,单词数:11 file.c,行数:9 file.c,代码行/空行/注释行:2/3/5 file1.c,字符数:22 file1.c,单词数:5 file1.c,行数:6 file1.c,代码行/空行/注释行:2/2/2
非需求测试:
6) 安全测试:
对不存在的文本进行测试
-c file.o
输出:文件或路径不存在
---------------------------------------------------------------------------------
单元测试代码:
public class WordCountTest extends TestCase{ File file=null; File sourceFile=null; //源文件 File stopFile=null; //停用文本 int actual=0; //存放统计单词数或字符数行数 int[] actuals=new int [3]; //存放统计代码行空行注释行的数量 int expected=0; //存放统计单词数或字符数行数 int[] expecteds=new int [3]; //存放统计代码行空行注释行的数量 ArrayList<String> filePath=new ArrayList<String>(); //测试统计字符数函数 public void testCharacter() throws FileNotFoundException, IOException { file=new File("file.c"); actual=wordCount.countCharacters( file); expected=33; assertEquals(expected, actual); } // 测试统计单词数函数 public void testWord() throws FileNotFoundException, IOException { file=new File("file.c"); actual = wordCount.countWords(file); expected=10; assertEquals(expected, actual); } // 测试统计行数函数 public void testLine() throws FileNotFoundException, IOException { file=new File("file.c"); actual = wordCount.countLines(file); expected=9; assertEquals(expected, actual); } // 测试统计代码行,空行,注释行数函数 public void testDLine() throws FileNotFoundException, IOException { file=new File("wordCount.c"); actuals = wordCount.countDLines(file); expecteds[0]=4; expecteds[1]=1; expecteds[2]=7; assertArrayEquals(expecteds, actuals); } // 测试采用停用文本后统计单词数函数 public void testEStop() throws Exception { sourceFile=new File("wordCount.c"); stopFile=new File("stop.txt"); actual = wordCount.countWordsS(sourceFile, stopFile); expected=8; assertEquals(expected, actual); } }
程序集成测试:
//测试程序功能 修改参数args内容 public class testMain extends TestCase{ String[] args=null; File actual=null; //实际运行结果文件 File expected=null; //测试前将正确的结果存入expected文件 //有效等价类测试 public void test1() throws Exception{ args=new String[2]; args[0]="-c"; args[1]="wordCount.c"; wordCount.main(args); actual=new File("result.txt"); expected=new File("cresult.txt"); assertEquals(expected, actual); } public void test2() throws Exception{ args=new String[2]; args[0]="-w"; args[1]="wordCount.c"; wordCount.main(args); actual=new File("result.txt"); expected=new File("wresult.txt"); assertEquals(expected, actual); } public void test3() throws Exception{ args=new String[2]; args[0]="-l"; args[1]="wordCount.c"; wordCount.main(args); actual=new File("result.txt"); expected=new File("lresult.txt"); assertEquals(expected, actual); } public void test4() throws Exception{ args=new String[2]; args[0]="-a"; args[1]="wordCount.c"; wordCount.main(args); actual=new File("result.txt"); expected=new File("aresult.txt"); assertEquals(expected, actual); } public void test5() throws Exception{ args=new String[2]; args[0]="-s"; args[1]="wordCount.c"; wordCount.main(args); actual=new File("result.txt"); expected=new File("sresult.txt"); assertEquals(expected, actual); } public void test6() throws Exception{ args=new String[4]; args[0]="-c"; args[1]="wordCount.c"; args[2]="-o"; args[3]="output.txt"; wordCount.main(args); actual=new File("output.txt"); expected=new File("coresult.txt"); assertEquals(expected, actual); } //基础功能综合测试 public void test7() throws Exception{ args=new String[4]; args[0]="-w"; args[1]="wordCount.c"; args[2]="-c"; args[3]="-l"; wordCount.main(args); actual=new File("result.txt"); expected=new File("wclresult.txt"); assertEquals(expected, actual); } //拓展功能综合测试 public void test8() throws Exception{ args=new String[5]; args[0]="-s"; args[1]="-e"; args[2]="stop.txt"; args[3]="wordCount.c"; args[4]="-a"; wordCount.main(args); actual=new File("result.txt"); expected=new File("aseresult.txt"); assertEquals(expected, actual); } //基础加拓展功能综合测试 public void test9() throws Exception{ args=new String[8]; args[0]="-w"; args[1]="wordCount.c"; args[2]="-c"; args[3]="-l"; args[4]="-s"; args[5]="-e"; args[6]="stop.txt"; args[7]="-a"; wordCount.main(args); actual=new File("result.txt"); expected=new File("beresult.txt"); assertEquals(expected, actual); } //基础加拓展加输出测试 public void test10() throws Exception{ args=new String[10]; args[0]="-s"; args[1]="-e"; args[2]="stop.txt"; args[3]="wordCount.c"; args[4]="-a"; args[5]="-w"; args[6]="-c"; args[7]="-l"; args[8]="-o"; args[9]="output.txt"; wordCount.main(args); actual=new File("output.txt"); expected=new File("beoresult.txt"); assertEquals(expected, actual); } }
---------------------------------------------------------------------------------------
7.参考文献链接
[1]:http://blog.sina.com.cn/s/blog_680288f00100l6a2.html
[2]:https://www.cnblogs.com/xiadongqing/p/6235833.html
[3]:https://www.cnblogs.com/fqfanqi/p/6187085.html
[4]:https://www.cnblogs.com/linuxjava/p/6435911.html
[5]:http://blog.csdn.net/sunkun2013/article/details/13167099