軟體質量與測試 第二周作業 WordCount Github地址: https://github.com/Hu-Peking/WordCount PSP2.1: 解題思路: 1、將程式的功能需求分為基礎功能和拓展功能,按先後順序分別實現兩部分的內容; 2、先在IDE中實現對電腦中指定目錄下的文件的讀 ...
軟體質量與測試 第二周作業 WordCount
Github地址:
https://github.com/Hu-Peking/WordCount
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