基于C#的单元测试(VS2015)
2016-03-19 22:16
555 查看
这次来联系怎么用VS2015来进行C#代码的单元测试管理,首先,正好上次写了一个C#的WordCount程序,就用它来进行单元测试联系吧。
首先,根据VS2015的提示,仅支持在共有类或共有方法中支持创建单元测试。所以,如果我们要测试私有或是保护的类和方法,是要先将他们暂时设定成公有类型。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319211114037-1827710272.png)
在VS2015中创建单元测试非常简单,只要在我们想测试的地方点击右键,就会出现 “创建单元测试” 选项。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319211420037-1433934273.png)
如果发现菜单没有显示,可以参照这篇博客进行设置。http://www.bubuko.com/infodetail-1370830.html
单击 “创建单元测试” 后,会出项如下对话框。不用修改,保持默认选项就可以。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319211918381-1096034626.png)
点击“确定”,耐心等待一会。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319212032053-921372283.png)
创建完成后,会出项一个名为 “WCTests” 的文件,文件初始代码为
在进行单元测试时,主要使用的是 Assert 类,他的用发有很多,详细用法可以参照 https://msdn.microsoft.com/zh-cn/library/microsoft.visualstudio.testtools.unittesting.assert.aspx
下面给出我们要进行测试的代码,为了方便测试,我们对其中代码输出的部分进行了修改,将原先控制台输出的部分改成了函数返回。
接下来,我们对测试代码进行修改,在我们进行单元测试时,某种程度上就是将我们人工给出的程序运行结果与程序实际输出结果进行比较,所以单元测试的过程一般分为 3 步:
给出我们期望的结果 expected
执行需测试代码,返回结果 actual
比较 actual 和 expected
下面以 WC 程序执行 -c 参数对 123.txt 文件进行统计的功能为例进行测试,我们将测试代码修改如下,其中 AreEqual 方法用于对期望值与实际值进行比较。
"123.txt" 文件为
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220310693-1838700072.png)
我们预期的测试结果是此文件有138个字符,所以会输出 “字符数:138” ;我们来看看测试的结果,点击右键,选择 “运行测试” ,选项测试通过了。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220947631-2003805469.png)
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220515881-1237145667.png)
我们现在给出一个错误的预期来看看结果会如何,我们现在认为 "123.txt" 文件有50个字符。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220741381-2119381949.png)
系统会提示出错,并且给出实际值与期望值分别是多少。至此,我们已经完成了简单的C#单元测试。接下来,只需要对测试代码进行修改,测试跟多的样例,来对代码进行测试。
首先,根据VS2015的提示,仅支持在共有类或共有方法中支持创建单元测试。所以,如果我们要测试私有或是保护的类和方法,是要先将他们暂时设定成公有类型。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319211114037-1827710272.png)
在VS2015中创建单元测试非常简单,只要在我们想测试的地方点击右键,就会出现 “创建单元测试” 选项。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319211420037-1433934273.png)
如果发现菜单没有显示,可以参照这篇博客进行设置。http://www.bubuko.com/infodetail-1370830.html
单击 “创建单元测试” 后,会出项如下对话框。不用修改,保持默认选项就可以。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319211918381-1096034626.png)
点击“确定”,耐心等待一会。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319212032053-921372283.png)
创建完成后,会出项一个名为 “WCTests” 的文件,文件初始代码为
using Microsoft.VisualStudio.TestTools.UnitTesting; using wc; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace wc.Tests { [TestClass()] public class WCTests { [TestMethod()] public void WCTest() { Assert.Fail(); } [TestMethod()] public void OperatorTest() { Assert.Fail(); } } }
在进行单元测试时,主要使用的是 Assert 类,他的用发有很多,详细用法可以参照 https://msdn.microsoft.com/zh-cn/library/microsoft.visualstudio.testtools.unittesting.assert.aspx
下面给出我们要进行测试的代码,为了方便测试,我们对其中代码输出的部分进行了修改,将原先控制台输出的部分改成了函数返回。
public class WC { private string sFilename; // 文件名 private string[] sParameter; // 参数数组 private int iCharcount; // 字符数 private int iWordcount; // 单词数 private int iLinecount; // 行 数 private int iNullLinecount; // 空行数 private int iCodeLinecount; // 代码行数 private int iNoteLinecount; // 注释行数 // 初始化 public WC() { this.iCharcount = 0; this.iWordcount = 0; this.iLinecount = 0; this.iNullLinecount = 0; this.iCodeLinecount = 0; this.iNoteLinecount = 0; } // 控制信息 public string Operator(string[] sParameter, string sFilename) { this.sParameter = sParameter; this.sFilename = sFilename; string retrun_str = ""; foreach (string s in sParameter) { if(s == "-x") { string resultFile = ""; OpenFileDialog fd = new OpenFileDialog(); fd.InitialDirectory = "D:\\Patch"; fd.Filter = "All files (*.*)|*.*|txt files (*.txt)|*.txt"; fd.FilterIndex = 2; fd.RestoreDirectory = true; if (fd.ShowDialog() == DialogResult.OK) { resultFile = fd.FileName; //Console.WriteLine("文件名:{0}", resultFile); SuperCount(resultFile); BaseCount(resultFile); retrun_str = DisplayAll(); } break; } // 遍历文件 else if (s == "-s") { try { string[] arrPaths = sFilename.Split('\\'); int pathsLength = arrPaths.Length; string path = ""; // 获取输入路径 for (int i = 0; i < pathsLength - 1; i++) { arrPaths[i] = arrPaths[i] + '\\'; path += arrPaths[i]; } // 获取通配符 string filename = arrPaths[pathsLength - 1]; // 获取符合条件的文件名 string[] files = Directory.GetFiles(path, filename); foreach (string file in files) { //Console.WriteLine("文件名:{0}", file); SuperCount(file); BaseCount(file); retrun_str = Display(); } break; } catch (IOException ex) { //Console.WriteLine(ex.Message); return ""; } } // 高级选项 else if (s == "-a") { //Console.WriteLine("文件名:{0}", sFilename); SuperCount(sFilename); BaseCount(sFilename); retrun_str = Display(); break; } // 基本功能 else if (s == "-c" || s == "-w" || s == "-l") { //Console.WriteLine("文件名:{0}", sFilename); BaseCount(sFilename); retrun_str = Display(); break; } else { //Console.WriteLine("参数 {0} 不存在", s); break; } } Console.WriteLine("{0}", retrun_str); return retrun_str; } // 统计基本信息:字符数 单词数 行数 private void BaseCount(string filename) { try { // 打开文件 FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); StreamReader sr = new StreamReader(file); int nChar; int charcount = 0; int wordcount = 0; int linecount = 0; //定义一个字符数组 char[] symbol = { ' ', ',', '.', '?', '!', ':', ';', '\'', '\"', '\t', '{', '}', '(', ')', '+' ,'-', '*', '='}; while ((nChar = sr.Read()) != -1) { charcount++; // 统计字符数 foreach (char c in symbol) { if(nChar == (int)c) { wordcount++; // 统计单词数 } } if (nChar == '\n') { linecount++; // 统计行数 } } iCharcount = charcount; iWordcount = wordcount + 1; iLinecount = linecount + 1; sr.Close(); } catch (IOException ex) { Console.WriteLine(ex.Message); return; } } // 统计高级信息:空行数 代码行数 注释行数 private void SuperCount(string filename) { try { // 打开文件 FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); StreamReader sr = new StreamReader(file); String line; int nulllinecount = 0; int codelinecount = 0; int notelinecount = 0; while ((line = sr.ReadLine()) != null) { line = line.Trim(' '); line = line.Trim('\t'); // 空行 if (line == "" || line.Length <= 1) { nulllinecount++; } // 注释行 else if(line.Substring(0, 2) == "//" || line.Substring(1, 2) == "//") { notelinecount++; } // 代码行 else { codelinecount++; } } iNullLinecount = nulllinecount; iCodeLinecount = codelinecount; iNoteLinecount = notelinecount; sr.Close(); } catch (IOException ex) { Console.WriteLine(ex.Message); return; } } // 打印信息 private string Display() { string return_str = ""; foreach (string s in sParameter) { if (s == "-c") { //Console.WriteLine("字 符 数:{0}", iCharcount); return_str += "字符数:"+iCharcount.ToString(); } else if (s == "-w") { //Console.WriteLine("单 词 数:{0}", iWordcount); return_str += "单词数:" + iWordcount.ToString(); } else if (s == "-l") { //Console.WriteLine("总 行 数:{0}", iLinecount); return_str += "总行数:" + iLinecount.ToString(); } else if(s == "-a") { //Console.WriteLine("空 行 数:{0}", iNullLinecount); //Console.WriteLine("代码行数:{0}", iCodeLinecount); //Console.WriteLine("注释行数:{0}", iNoteLinecount); return_str += "空行数:" + iNullLinecount.ToString(); return_str += "代码行数:" + iCodeLinecount.ToString(); return_str += "注释行数:" + iNoteLinecount.ToString(); } } //Console.WriteLine(); return return_str; } private string DisplayAll() { string return_str = ""; foreach (string s in sParameter) { //Console.WriteLine("字 符 数:{0}", iCharcount); //Console.WriteLine("单 词 数:{0}", iWordcount); //Console.WriteLine("总 行 数:{0}", iLinecount); //Console.WriteLine("空 行 数:{0}", iNullLinecount); //Console.WriteLine("代码行数:{0}", iCodeLinecount); //Console.WriteLine("注释行数:{0}", iNoteLinecount); return_str += "字符数:" + iCharcount.ToString(); return_str += "单词数:" + iWordcount.ToString(); return_str += "总行数:" + iLinecount.ToString(); return_str += "空行数:" + iNullLinecount.ToString(); return_str += "代码行数:" + iCodeLinecount.ToString(); return_str += "注释行数:" + iNoteLinecount.ToString(); } //Console.WriteLine(); return return_str; } }
接下来,我们对测试代码进行修改,在我们进行单元测试时,某种程度上就是将我们人工给出的程序运行结果与程序实际输出结果进行比较,所以单元测试的过程一般分为 3 步:
给出我们期望的结果 expected
执行需测试代码,返回结果 actual
比较 actual 和 expected
下面以 WC 程序执行 -c 参数对 123.txt 文件进行统计的功能为例进行测试,我们将测试代码修改如下,其中 AreEqual 方法用于对期望值与实际值进行比较。
using Microsoft.VisualStudio.TestTools.UnitTesting; using wc; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace wc.Tests { [TestClass()] public class WCTests { [TestMethod()] public void WCTest() { // arrange string expected = "字符数:138"; WC testwc = new WC(); // act string[] opar = new string[1]; opar[0] = "-c"; string actual = testwc.Operator(opar, @"D:\学习\我的工程\软件工程\wc\wc\wc\123.txt"); // assert Assert.AreEqual(expected, actual); } } }
"123.txt" 文件为
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220310693-1838700072.png)
我们预期的测试结果是此文件有138个字符,所以会输出 “字符数:138” ;我们来看看测试的结果,点击右键,选择 “运行测试” ,选项测试通过了。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220947631-2003805469.png)
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220515881-1237145667.png)
我们现在给出一个错误的预期来看看结果会如何,我们现在认为 "123.txt" 文件有50个字符。
![](http://images2015.cnblogs.com/blog/901252/201603/901252-20160319220741381-2119381949.png)
系统会提示出错,并且给出实际值与期望值分别是多少。至此,我们已经完成了简单的C#单元测试。接下来,只需要对测试代码进行修改,测试跟多的样例,来对代码进行测试。
相关文章推荐
- C# kinect v2学习笔记(三)红外图像展示
- C#中使用TeeChart控件出现 不支持无窗口的Active控件 的解决方法
- c# 委托
- C#中的FTP类
- c#程序的阅读
- 【C#】WM 消息大全
- 软件工程-构建之法 理解C#一小段程序
- 【转】【C#】SendMessage
- C#编程之神奇程序找数
- C#---抽象类与接口
- 第一个C#程序--简易计算器
- C#实现注册码功能编程总结
- c#代码分析
- C# 千分位与两位小数点
- (转)C# 温故而知新:Stream篇(七)
- C#程序分析
- (转)C# 温故而知新:Stream篇(六)
- (转)C# 温故而知新:Stream篇(五)
- (转)C# 温故而知新:Stream篇(四)
- (转)C# 温故而知新:Stream篇(三)