#地鐵線路項目-結對編程編程
2019.7.25 完成了模塊開發;填寫PSP實際完成時間;完成了模塊設計;進行單元測試、黑盒測試。數組
PSP表記錄:
PSP2.1 | Personal Software Process Stages | Time | Real Time |
---|---|---|---|
Planning | 計劃 | 1h | 1h |
· Estimate | · 估計這個任務須要多少時間 | 1h | 1h |
Development | 開發 | 21h | 20.5h |
· Analysis | · 需求分析 (包括學習新技術) | 2h | 1.5h |
· Design Spec | · 生成設計文檔 | 2h | 1h |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 1h | 1.5h |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 2h | - |
· Design | · 具體設計 | 2h | 1.5h |
· Coding | · 具體編碼 | 6h | 8h |
· Code Review | · 代碼複審 | 2h | 1h |
· Test | · 測試(自我測試,修改代碼,提交修改) | 4h | 6h |
Reporting | 報告 | 6h | |
· Test Report | · 測試報告 | 2h | - |
· Size Measurement | · 計算工做量 | 2h | - |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 2h | 1.5h |
合計 | 28h |
計算模塊設計與實現過程
1.模塊設計性能
-
命令解析模塊:接受命令行運行時帶入的參數,正確提取參數,而且可以忽略錯誤的參數,必要時給與響應的提示。單元測試
具體流程:遍歷全部參數,判斷是否屬於一種命令,若是是對應的命令,則提取命令後面對應的參數值,若是沒有提取到必須的參數值在提示命令錯誤信息,以此處理完全部的參數,最後返回提取到的命令和對應的參數值。學習
-
地鐵地圖解析模塊:測試
(1)分析項目中涉及到的對象,包括站點、地鐵線、地鐵線路圖、路徑(一條線上的兩個站點),分別定義了以下的結構。編碼
站點spa
class Station { public: string StationName;//站點名稱 vector<string> BelongTo ;//地鐵線的名稱 vector<int> IndexOfLine;//對應的地鐵線上的站序號 bool Visited;//是否已被訪問 };
地鐵線路
template<class T> class Line { public: string LineName; vector<T> Stations; };
地鐵線路圖
class Map { public: //全部的站點 map<string, Station> Stations; //全部的地鐵線 map<string, Line<Station>> Lines; };
路徑
class Path{ public: int Start;//線路段開始序號 int End;//線路段結束序號 int Next;//下一段序號 Line<Station> PathLine;//當前地鐵線 };
(2)讀入地圖文件中的字符串數據,進行字符串分割並建立上面列出的一系列對象,做爲後續線路查詢和線路搜索任務的數據。
-
線路查詢模塊:命令行
輸入線路名稱,獲取到一個線路Line<Station> line。獲取方式爲直接經過Map對象的map<string, Line<Station>>對象Lines,直接經過站點名字查出Line<Station>。設計
-
線路搜索模塊: 接受輸入的起點站和終點站的名字,輸出多段地鐵線路路徑vector<vector<Path>> paths,可能存在多條相同長度的線路。具體的流程以下:
(1)首先經過地鐵線路圖對象的Stations,經過名字直接找到對應的地鐵線路, (2)以對應的站點爲起點進行廣度遍歷:向其所在線路的兩個方向搜索; (3)每一輪標註當前站點爲已訪問,搜索前進一個站點,並更新路徑; (4)經過換乘點時增長新的路徑(換乘線路的兩個方向) (5)直到搜索到對應的終點,或者一條線的終點,或者一個被訪問過的點; (6)記錄通過的每條地鐵線路的路徑,返回一個路徑的數組,便是咱們要搜索的最短路徑。這樣的路徑可能不止一條。
-
最後實現的模塊提供了三個主要接口:
··· //初始化地圖 Map InitMap(string mapFile); //搜索地鐵線 Line<Station> SearchLine(string lineName, Map& map); //搜索線路 vector<vector<Path>> SearchPaths(string startStation, string endStation, Map& map); ···
性能分析
暫時未作性能分析。
單元測試
單元測試的覆蓋率沒法看到,設計了9條單元測試用例,以下:
//測試輸入不存在的地圖文件初始化地圖 TEST_METHOD(TestInvalidMapPath) { // Map map = Core::InitMap(""); Assert::AreEqual((int)map.Lines.size(), 0); } //測試存在的地圖文件初始化地圖 //要檢測每一條線的每個站點太費事了,先只統計數量 TEST_METHOD(TestValidMpathPath) { Map map = Core::InitMap("subway.txt"); Assert::AreEqual((int)map.Lines.size(), 6); Assert::AreEqual((int)map.Stations.size(), 140); } //測試存在的地鐵線路 TEST_METHOD(TestSearchExistLine) { Map map = Core::InitMap("subway.txt"); string lineName = "1號線"; string stations[23] = { "劉園","瑞景新苑","佳園裏","本溪路","勤儉道","洪湖裏","西站","西北角","西南角","二緯路","海光寺","鞍山道","營口道","小白樓","下瓦房","南樓","土城","陳塘莊","復興門","華山裏","財經大學","雙林","李樓" }; Line<Station> line = Core::SearchLine(lineName, map); Assert::AreEqual(lineName, line.LineName); Assert::AreEqual((int)line.Stations.size(), 23); for (int i = 0;i < 23;i++) { Assert::AreEqual(line.Stations[i].StationName, stations[i]); } } //測試不存在的地鐵線路 TEST_METHOD(TestSearchNotExistLine) { Map map = Core::InitMap("subway.txt"); string lineName = "X號線"; Line<Station> line = Core::SearchLine(lineName, map); Assert::AreNotEqual(line.LineName, lineName); } //搜索起點到終點線路,存在於一條線路上 TEST_METHOD(TestSearchExistPathInSingleLine) { Map map = Core::InitMap("subway.txt"); vector<vector<Path>> pathss = Core::SearchPaths("本溪路", "西站",map); string path[4] = { "本溪路","勤儉道","洪湖裏","西站" }; Assert::AreEqual((int)pathss.size(), 1); Assert::AreEqual((int)pathss[0].size(), 1); for (int i = 0;i < 4;i++) { Assert::AreEqual(pathss[0][0].PathLine.Stations[pathss[0][0].Start + i].StationName, path[i]); } } //搜索起點到終點線路,存在於多條線路上 TEST_METHOD(TestSearchExistPathInMultiLines) { Map map = Core::InitMap("subway.txt"); vector<vector<Path>> pathss = Core::SearchPaths("洪湖裏", "復興路", map); string path[2][2] = { { "洪湖裏","西站" }, { "西站","復興路" } }; Assert::AreEqual((int)pathss.size(), 1); Assert::AreEqual((int)pathss[0].size(), 2); for (int i = 0;i < 2;i++) { for (int j = 0;j < 2;j++) { Assert::AreEqual(pathss[0][i].PathLine.Stations[pathss[0][i].Start + j].StationName, path[i][j]); } } } //搜索起點到終點線路,起點不存在 TEST_METHOD(TestSearchNotExistStartStation) { Map map = Core::InitMap("subway.txt"); vector<vector<Path>> pathss = Core::SearchPaths("世紀城", "西站", map); Assert::AreEqual((int)pathss.size(), 0); } //搜索起點到終點線路,終點不存在 TEST_METHOD(TestSearchNotExistEndStation) { Map map = Core::InitMap("subway.txt"); vector<vector<Path>> pathss = Core::SearchPaths("西站", "世紀城", map); Assert::AreEqual((int)pathss.size(), 0); } //搜索起點到終點線路,空地圖 TEST_METHOD(TestSearchEmptyMap) { string empty = ""; Map map = Core::InitMap(""); vector<vector<Path>> pathss = Core::SearchPaths("洪湖裏", "西站", map); Assert::AreEqual((int)pathss.size(), 0); }
異常處理說明
- 參數錯誤異常:對於不支持的命令類型給出響應的提示;對於命令對應參數數量不全的狀況給出響應的提示。
- IO異常:對於文件的操做,先對文件進行存在性檢測,再打開文件;在對文件進行寫入時捕獲響應的異常,並進行提示。
- 空指針異常:對全部指針類型進行空指針檢查,而後再使用。
測試用例
1.測試用例設計
黑盒測試用例的設計方法多種多樣,本次項目主要採用了等價類劃分法、邊界值分析法、錯誤推測法等進行用例的設計。
-
等價類劃分法:將測試的範圍劃分爲幾個不想交的子集,他們的並集就是全集,從每一個子集選出若干具備表明性的值做爲測試用例。
-
邊界值分析法:大量的測試經驗告訴咱們,大量的錯誤是發生在輸入範圍的邊界上,而不是發生在輸入輸出範圍的內部。所以針對各類邊界狀況設計測試用例,能夠查出更多的錯誤。
-
錯誤推測法:在測試程序時,人們能夠根據經驗或直覺推測程序中可能存在的各類錯誤,從而有針對性地編寫檢查這些錯誤的測試用例的方法。 這種方法沒有固定的形式,依靠的是經驗和直覺,不少時候,咱們都會不知不覺的使用到。
2.測試用例
依據上面的用例設計方法,設計了一些測試用例,下表中列舉了部分用例:
序號 | 標題 | 前置條件 | 輸入 | 操做步驟 | 預期結果 |
---|---|---|---|---|---|
1 | 正確查詢線路 | 1.能在當前測試系統上運行<br>2.查詢的線路存在於地圖文件中 | subway.exe -a 1號線 -map subway.txt -o station.txt | 1.輸入命令<br> 2.觀察命令行輸出及程序文件夾目錄的station.txt文件<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行沒有錯誤提示信息<br>3.station.txt文件中正確按格式寫入了1號線的全部站點,而且順序正確(此處省略了全部站點信息) |
2 | 查詢線路錯誤,線路不存在 | 1.能在當前測試系統上運行<br>2.查詢的線路不存在於地圖文件中 | subway.exe -a 20號線 -map subway.txt -o station.txt | 1.輸入命令<br> 2.觀察命令行輸出及程序文件夾目錄的station.txt文件<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行提示"沒有要查找的地鐵線"<br>3.station.txt文件不存在或者數據爲空 |
3 | 查詢線路錯誤,缺乏必要參數-o | 1.能在當前測試系統上運行 | subway.exe -a 1號線 -map subway.txt | 1.輸入命令<br> 2.觀察命令行輸出及程序文件夾目錄的station.txt文件<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行提示"缺乏必要的參數-o"<br>3.station.txt文件不存在或者數據爲空 |
4 | 查詢線路錯誤,缺乏必要參數,地圖文件路徑 | 1.能在當前測試系統上運行 | subway.exe -a 1號線 -map -o station.txt | 1.輸入命令<br> 2.觀察命令行輸出及程序文件夾目錄的station.txt文件<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行提示"缺乏地圖文件路徑"<br>3.station.txt文件不存在或者數據爲空 |
5 | 查詢線路錯誤,缺乏必要參數,輸出結果文件路徑 | 1.能在當前測試系統上運行 | subway.exe -a 1號線 -map subway.txt -o | 1.輸入命令<br> 2.觀察命令行輸出<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行提示"缺乏輸出結果文件路徑"<br> |
6 | 正確搜索路徑,單條地鐵線 | 1.能在當前測試系統上運行 | subway.exe -b 劉園 洪湖裏 -map subway.txt -o routine.txt | 1.輸入命令<br> 2.觀察命令行輸出<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行無錯誤信息<br>3.routine.txt文件中正確按格式輸出了1號線及從劉園到洪湖裏的全部站點信息 |
7 | 正確搜索路徑,兩條地鐵線 | 1.能在當前測試系統上運行 | subway.exe -b 洪湖裏 復興路 -map subway.txt -o routine.txt | 1.輸入命令<br> 2.觀察命令行輸出<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行無錯誤信息<br>3.routine.txt文件中正確按格式輸出了:1號線 洪湖裏 西站 6號線 復興路 |
8 | 正確搜索路徑,沒有可達的線路 | 1.能在當前測試系統上運行 <br>2.地圖文件中新增一條線路20號線,裏面的線路與其餘線路都沒有換乘站,且該線路上有一個站爲世紀城 | subway.exe -b 洪湖裏 世紀城 -map subway.txt -o routine.txt | 1.輸入命令<br> 2.觀察命令行輸出<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行"沒有可達的線路"<br>3.routine.txt文件不存在或者爲空 |
9 | 搜索路徑出錯,缺乏必要參數-o | 1.能在當前測試系統上運行 | subway.exe -b 洪湖裏 復興路 -map subway.txt | 1.輸入命令<br> 2.觀察命令行輸出<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行提示"缺乏必要的參數-o"<br> |
10 | 搜索路徑出錯,缺乏必要參數,輸出結果文件路徑 | 1.能在當前測試系統上運行 | subway.exe -b 洪湖裏 復興路 -map subway.txt | 1.輸入命令<br> 2.觀察命令行輸出<br> 3.對比結果 | 1.程序沒有出錯<br>2.命令行提示"缺乏輸出結果文件路徑"<br> |
我無法百分之百肯定個人程序確定是正確的: (1)經過程序的設計和代碼走查,程序的邏輯上沒有問題; (2)單元測試部分儘量覆蓋了代碼邏輯; (3)功能測試是採用測試用例設計的方法,儘量以最少的用例覆蓋了更多的狀況。
心得體會
經過我的項目和結對編程,我主要有以下的心得: (1)以軟件工程的思想可以開發出耦合度低,複用性強,質量有保證的程序; (2)結對編程可以幫助組隊人互相提升,而且保證產出代碼和軟件的質量; (3)經過邊作邊學的方式可以更好的理解軟件工程思想,對於之後進行相關教學工做提供了靈感; (4)本身當年學習軟件工程過程很痛苦,經過此次的學習,有了新的領悟。