#地铁线路项目-结对编程编程
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)本身当年学习软件工程过程很痛苦,经过此次的学习,有了新的领悟。