WordCount编码和测试
项目地址:https://github.com/handsomesnail/WordCount
PSP表格
PSP2.1 | PSP阶段 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 10 |
Estimate | 估计任务需要多少时间 | 20 | 10 |
Development | 开发 | 150 | 140 |
Analysis | 需求分析 | 10 | 10 |
Design Spec | 生成设计文档 | 10 | 0 |
Design Review | 设计复审 | 10 | 0 |
Coding Standard | 代码规范 | 10 | 0 |
Design | 具体设计 | 20 | 20 |
Coding | 具体编码 | 60 | 80 |
Code Review | 代码复审 | 10 | 10 |
Test | 测试 | 20 | 20 |
Reporting | 报告 | 60 | 90 |
Test Report | 测试报告 | 30 | 60 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem | 总结 | 10 | 10 |
合计 | 230 | 240 |
解题思路
将问题分解为如下模块:
解析命令行参数
(将输入转化为路径以及各种操作选项如-c -w -l等)I/O操作
(将路径转化为相应路径下文件的字符串内容)字符串统计
(将各种操作选项抽象为各类处理字符串的方法)
程序设计实现
Program类
- void Main(string[] args)
Main函数作为程序入口 - int Entrance(string[] args)
测试入口, 返回值为错误码,正确执行返回0 - string Read(string fileName)
读取相对路径下名为fileName的文件并返回字符串 - string Read(out string fileName)
调用win32 api选取文件并读取返回字符串,同时返回选取的文件名 - void Write(string fileName, string content)
在相对路径下向名为fileName的文件追加内容为content的字符串 - void LogArgumentError(int code)
打印错误信息 - int CountChar(string s)
统计并返回字符串s的字符数 - int CountWord(string s)
统计并返回字符串s的单词数 - int CountWord(string s,HashSet stopList)
根据停用词表stopList统计并返回字符串s的单词数 - int CountLine(string s)
统计并返回字符串s的行数 - void CountMoreAboutLine(string s, out int codeLineCount, out int emptyLineCount, out int commentLineCount)
统计并返回行的详细信息(代码行/空行/注释行)
OpenFileName类
初始化打开或另存为对话框的信息,系统返回关于用户的选择信息到这个结构中
LocalDialog类
- extern bool GetOpenFileName([In, Out] OpenFileName ofn)
链接Comdlg32.dll中打开文件的系统函数
代码说明
/// <summary>统计字符数并打印</summary> private static int CountChar(string s) { return s.Length; //直接返回字符串长度 }
/// <summary>统计单词数并打印</summary> private static int CountWord(string s) { return CountWord(s, new HashSet<string>()); } /// <summary>根据停用词表统计单词数并打印</summary> private static int CountWord(string s,HashSet<string> stopList) { if (s.Length == 0) return 0; int count = 1; int i = -1; StringBuilder sb = new StringBuilder(); foreach (char c in s) { i++; if (splitCharDic.Contains(c)) { if (i < s.Length - 1 && !splitCharDic.Contains(s[i + 1])) { if (!stopList.Contains(sb.ToString())) { count++; //Console.WriteLine(count + ":" + sb.ToString()); sb.Clear(); } else { sb.Clear(); } } } else { sb.Append(c); } } return count; }
/// <summary>统计行数并打印</summary> private static int CountLine(string s) { int count = 0; //遍历直接统计'\n'数量 foreach (char c in s) { if (count == 0) { count++; continue; } if (c == '\n') { count++; } } return count; }
/// <summary>统计行的详细信息</summary> private static void CountMoreAboutLine(string s, out int codeLineCount, out int emptyLineCount, out int commentLineCount) { codeLineCount = 0;//代码行 emptyLineCount = 0;//空行 commentLineCount = 0;//注释行 int charInALine = 0; //当前行可见字符数 int i = -1; CommentLineType CommentLine = CommentLineType.NonCommentLine; bool cancelCommentLine = false; foreach (char c in s) { i++; if (c == '\n'||i==s.Length-1) { if (CommentLine==CommentLineType.SingleCommentLine) { commentLineCount++; CommentLine = CommentLineType.NonCommentLine; } else if ((CommentLine == CommentLineType.SeveralCommentLine|| cancelCommentLine )&& charInALine<=1) { commentLineCount++; } else if (charInALine > 1) { codeLineCount++; } else emptyLineCount++; if (cancelCommentLine) { cancelCommentLine = false; } charInALine = 0; } if (charInALine <= 1 && c == '/' && i > 0 && s[i - 1] == '/') { CommentLine = CommentLineType.SingleCommentLine; } else if (c == '*' && i > 0 && s[i - 1] == '/') { CommentLine = CommentLineType.SeveralCommentLine; } else if (c == '/' && i > 0 && s[i - 1] == '*') { cancelCommentLine = true; CommentLine = CommentLineType.NonCommentLine; } else if (CommentLine == CommentLineType.NonCommentLine && !displayedCharDic.Contains(c)) { charInALine++; } } }
/// <summary>通过图形界面读取文件 </summary> public static string Read(out string fileName) { OpenFileName ofn = new OpenFileName(); ofn.structSize = Marshal.SizeOf(ofn); ofn.file = new string(new char[256]); ofn.maxFile = ofn.file.Length; ofn.fileTitle = new string(new char[64]); ofn.maxFileTitle = ofn.fileTitle.Length; ofn.title = "选择文件"; ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008; if (LocalDialog.GetOpenFileName(ofn)) { fileName = ofn.fileTitle; using (FileStream fs = new FileStream(ofn.file, FileMode.Open, FileAccess.Read)) { using (StreamReader sw = new StreamReader(fs, Encoding.UTF8)) { return sw.ReadToEnd(); } } } throw new System.Exception("用户没有选择文件"); }
测试设计过程
- 如何设计测试用例
保证设计的测试用例应至少覆盖函数中所有的可执行语句 - 哪些地方会导致程序高风险
边界条件,未捕获的异常,未正确初始化的内存空间,空引用等等 - 测试代码如何设计
通过验证测试入口函数和相应分支的返回码覆盖代码的所有分支
namespace UnitTest { [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { string[] input = new string[] { }; Assert.AreEqual(Program.Entrance(input), -1); } [TestMethod] public void TestMethod2() { string[] input = new string[] {"-q", "input.txt" }; Assert.AreEqual(Program.Entrance(input), 2); } [TestMethod] public void TestMethod3() { string[] input = new string[] {"-c", "-c" ,"input.txt"}; Assert.AreEqual(Program.Entrance(input), 1); } [TestMethod] public void TestMethod4() { string[] input = new string[] { "-c", "input.txt", "-a" }; Assert.AreEqual(Program.Entrance(input), 7); } [TestMethod] public void TestMethod5() { string[] input = new string[] { "-c", "input.txt", "-o", "output.txt", "-c" }; Assert.AreEqual(Program.Entrance(input), 4); } [TestMethod] public void TestMethod6() { string[] input = new string[] { "-c", "input.txt","-o" }; Assert.AreEqual(Program.Entrance(input), 5); } [TestMethod] public void TestMethod7() { string[] input = new string[] { "-c", "-w", "-l" ,"example.txt" }; Assert.AreEqual(Program.Entrance(input), 6); } [TestMethod] public void TestMethod8() { string[] input = new string[] { "-c", "-w", "-l", "input.txt" }; Assert.AreEqual(Program.Entrance(input), 0); } [TestMethod] public void TestMethod9() { string[] input = new string[] { "-l", "-w", "-c", "input.txt", "-o" ,"output.txt"}; Assert.AreEqual(Program.Entrance(input), 0); } [TestMethod] public void TestMethod10() { string[] input = new string[] { "-l", "-w", "-c", "-a", "input.txt", "-e", "stopList.txt", "-o", "output.txt" }; Assert.AreEqual(Program.Entrance(input), 0); } [TestMethod] public void TestMethod11() { string[] input = new string[] { "-l", "-w", "-c", "-a", "-s", "*.txt", "-e", "stopList.txt" }; Assert.AreEqual(Program.Entrance(input), 0); } [TestMethod] public void TestMethod12() { string[] input = new string[] { "-x" }; Assert.AreEqual(Program.Entrance(input), 0); } } }
- 测试结果
参考文献链接:
[1]http://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html
[2]http://www.cnblogs.com/xinz/p/5044037.html
[3]http://http://www.cnblogs.com/xinz/archive/2011/11/20/2255830.html
来源:https://www.cnblogs.com/handsomesnail/p/8585505.html