WordCount-軟件測試初體驗
github:https://github.com/skz12345/WordCount
PSP2.1 | PSP階段 | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 40 | 60 |
· Estimate | · 估計這個任務需要多少時間 | 40 | 60 |
Development | 開發 | 305 | 510 |
· Analysis | · 需求分析 (包括學習新技術) | 60 | 120 |
· Design Spec | · 生成設計文檔 | 20 | 30 |
· Design Review | · 設計復審 (和同事審核設計文檔) | 20 | 30 |
· Coding Standard | · 代碼規範 (為目前的開發制定合適的規範) | 15 | 20 |
· Design | · 具體設計 | 40 | 60 |
· Coding | · 具體編碼 | 60 | 120 |
· Code Review | · 代碼復審 | 30 | 40 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 60 | 90 |
Reporting | 報告 | 100 | 150 |
· Test Report | · 測試報告 | 30 | 60 |
· Size Measurement | · 計算工作量 | 10 | 30 |
· Postmortem & Process Improvement Plan | · 事後總結, 並提出過程改進計劃 | 60 | 60 |
合計 | 445 | 720 |
代碼部分參考了MasonWater在https://github.com/MasonWater/WCProject所提交的代碼,本次測試基於本程序進行測試。
解題思路
根據作業要求,可以分析出此次作業有多個輸入參數,根據參數的不同,實現一些有嚴格要求的功能。關於多參數的傳遞,選擇使用main函數傳參的方法。通過查閱資料【1】,找到了java如何讀取文件內容,通過此方法,按照作業要求對各項數據進行統計,用代碼得以實現。
程序設計實現過程(以下主要基於http://www.cnblogs.com/hayitutu/p/8613653.html,Wonderkid的博客)
程序包括一個類(wordcount),9個函數,其中包括一個main函數。其余8個函數為:
Operator函數(實現功能)、BaseCount函數(基本功能)、Display函數(設置輸出到文件的字符串)、MoreCount函數(擴展功能)、getStopLisy函數(獲取停詞表中停詞)、outputTxt函數(設置輸出文件)、Bianli(實現遞歸處理)、getAllFile函數(獲得符合要求後綴的文件名)。
main函數獲取到參數後分類,將功能參數和文件參數分別存儲之後用於生成wordcount類的一個對象。之後調用對象的Operator功能,循環遍歷功能數組判斷需要執行那些操作。根據參數判斷來調用對應的函數。如事先判斷是否有啟用停詞表的參數,若有則先調用getStopList函數獲取停用詞表,之後若參數是基本功能的參數,就調用BaseCount函數來統計,同時判斷是否去除停詞。若是擴展功能參數,如復雜行的統計則調用MoreCount函數來統計代碼行,空行和註釋行。若是遞歸調用功能參數則調用BianLi函數,BianLi函數調用getAllfile函數獲取符合要求的文件隊列然後遞歸執行相應的操作(BaseCount、MoreCount等)。在遞歸操作或者Operator執行過程中若有輸出文件指定則將輸出flag調整。最後調用Display函數設置輸出到文件中的內容,之後調用outputTxt函數來根據輸出flag輸出到文件中。當完成基本功能後,將源文件上傳到github倉庫中,commit一次,之後完成程序再次上傳,打包好exe後完成最後的上傳。後續還上傳了測試腳本和測試相關文件。
代碼說明(以下主要基於http://www.cnblogs.com/hayitutu/p/8613653.html,Wonderkid的博客)
代碼說明
BaseCount方法中去除停詞時將文件按行讀入【2】,通過逗號和空格分割單詞後和停用詞數組中詞比較,統計去除詞的個數,每行處理一遍。同時註意行開頭空格的去除【3】
代碼如下:
BufferedReader st2 = new BufferedReader(new FileReader(this.sFilename));//統計單詞數
String read1 = null;
int lengthofSplit=0;
while (( read1 =st2.readLine()) != null)
{
read1=read1.trim();//去除空格
String[] arrSplit =read1.split(" |,");//以空格或者逗號分隔
lengthofSplit=arrSplit.length;
for(String s:arrSplit)
{
if(s.length()==0)
lengthofSplit--;//去除空格
}
wordcount+=lengthofSplit;
if(openStopList==1)
{
for(String s:arrSplit)
{
for(String stop:StopList)
if(s.equals(stop))
stopWordCount++;
}
}
}
st2.close();
MoreCount方法中同樣也是對文件按行讀取,判斷多行註釋的時候和單行註釋一樣要判斷註釋前是否多於一個字符,這通過一個計數變量來實現,以及“/”後有字符則不算註釋行,這也通過計數變量來實現。同時當有“/”開始後,設置多行註釋的flag變量,當遇到“/*”時重置flag
代碼如下:
flagOfword=0;
countOfword=0;
numberOfMLines=0;
BufferedReader brm = new BufferedReader(new FileReader(this.sFilename));
String linem;
int flagOfM=0;//標記是否有/*開始了
int countss=0;//記錄每行字符數以便判斷是否是註釋行
int counts=0;//記錄每行字符數以便判斷是否是註釋行
while ((linem = brm.readLine()) != null)//判斷/**/類型的註釋行
{
String [] sss=new String[10000];
if(flagOfM==1)
numberOfMLines++;
for (int x = 0; x < linem.length(); x++)
{
sss[x]=String.valueOf(linem.charAt(x));
int temp=(x+1)<(linem.length()-1)? x+1:(linem.length()-1);
if(flagOfM==0)
{ countss=0;//
if(x<linem.length()-1&&sss[x].equals("/")&&linem.charAt(temp)==‘*‘)
{
for(int i=0;i<x;i++)
{if(linem.charAt(i)!=‘ ‘)
{ if(linem.charAt(i)==‘\t‘)
continue;
countss++;
}
}
if(countss>1)
{
flagOfM=0;
}
else
{
flagOfM=1;
}
continue;
}
}
if(flagOfM==1)
{counts=0;
if(x<linem.length()-1&&sss[x].equals("*")&&linem.charAt(temp)==‘/‘)
{
for(int i=temp+1;i<linem.length()-1;i++)
{if(linem.charAt(i)!=‘ ‘)
{ if(linem.charAt(i)==‘\t‘)
continue;
counts++;
}
}
if(counts<=1)
{
numberOfMLines++;
flagOfM=0;
}
else
{
flagOfM=0;
}
}
}
}
}
brm.close();
對於擴展功能裏的遞歸讀取符合要求的文件,這通過兩個函數實現,BianLi函數調用getAllFile函數來篩選符合要求的文件之後的操作便是循環執行Operator函數的操作,所以BianLi函數不再贅述。關於getAllFile函數,函數有四個參數:文件路徑、符合要求的文件/文件夾的存儲數組、要篩選的類型以及篩選出來的文件數組。函數通過判斷是否是文件夾來操作,若是文件夾則遞歸調用函數,否則判斷類型後刪選文件。
代碼如下:
private static List<String> getAllFile(File filePath,List<String> filePaths,String type,List<String> finalFiles){
File[] files = filePath.listFiles();//遞歸獲取文件夾以及子目錄下的所有符合條件的文件
if(files == null){
return filePaths;
}
for(File f:files){
if(f.isDirectory()){
filePaths.add(f.getPath());
getAllFile(f,filePaths,type,finalFiles);
}else{
if(f.getName().endsWith(type))
{filePaths.add(f.getPath());
finalFiles.add(f.getPath());}
}
}
/*for(String path:finalFiles){
System.out.println(path);
}*/
return finalFiles;
}
測試設計過程
在線學習2.3節中對測試的判定中提到“要保證測試用例覆蓋函數中的所有可執行路徑”,以此為出發點,我盡可能精簡的設計了10條測試用例。
一、基於基本功能的測試
基本功能是該程序的第一次提交所實現的內容,由以下4條測試用例測試基本功能:
- wc.exe -c -w file1.c
- wc.exe -l file.c -o output.txt
- wc.exe -l -c -w file1.c
- wc.exe -c -l -w file1.c
設計思想
基本功能的實現中,所有指令均為通過flag置位判斷是否執行,flag的值只為0或1,在1,2兩個測試用例中,交叉試驗了-c -w -l -o四個功能,flag為0和為1全部覆蓋。
在3,4兩個測試用例中,測試了需求中要求的順序是否能正確執行。
二、基於擴展功能的測試
擴展功能是該程序的第二次提交所實現的內容,有以下三條測試用例測試擴展功能:
- wc.exe -a file1.c
- wc.exe -s -a *.c
- wc.exe -w file1.c -e stoplist.txt
設計思想
測試用例5測試了返回更復雜的數據,測試用例6測試了遞歸處理,測試用例7測試了啟用停用詞表下統計單詞總數功能是否正確。
三、綜合測試
最後提交將兩種功能疊加,進行總體測試,以下為三條測試用例:
- wc.exe -c -w -a -l file1.c
- wc.exe -w -a -c -l file1.c
- wc.exe -s -c -w -l -a *.c -o output.txt -e stoplist.txt
設計思想
測試用例8和9對於總順序是否能正確執行進行測試,測試用例10對於系統最復雜的功能集合進行了測試。
在對錯誤輸入的處理上,如果處理不當,往往會造成許多無法估計的後果,風險很高。
由於10條測試用例太少,並不能完全說明問題,預想中還應改變不同的代碼,進行一些錯誤處理、臨界值等的測試,將會在未來進行嘗試。
參考文獻
【1】https://blog.csdn.net/sky786905664/article/details/65626886
【2】https://www.cnblogs.com/xyzq/p/7095011.html
【3】http://blog.csdn.net/zhangzehai2234/article/details/73522041
WordCount-軟件測試初體驗