根据VS2015的提示,仅支持在共有类或共有方法中支持建立单元测试。因此,若是咱们要测试私有或是保护的类和方法,是要先将他们暂时设定成公有类型。html
在VS2015中建立单元测试,只要在咱们想测试的地方点击右键,就会出现 “建立单元测试” 选项。数组
若是菜单没有显示 测试,能够参照这篇博客进行设置。http://www.bubuko.com/infodetail-1370830.html函数
单击 “建立单元测试” 后,会出项以下对话框。不用修改,保持默认选项就能够。单元测试
点击“肯定”学习
建立完成后,会出项一个名为 “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.aspxthis
下面给出咱们要进行测试的代码,为了方便测试,咱们对其中代码输出的部分进行了修改,将原先控制台输出的部分改为了函数返回。spa
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 步:3d
下面以 WC 程序执行 -c 参数对 123.txt 文件进行统计的功能为例进行测试,咱们将测试代码修改以下,其中 AreEqual 方法用于对指望值与实际值进行比较。code
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" 文件:
咱们预期的测试结果是此文件有138个字符,因此会输出 “字符数:138” ;咱们来看看测试的结果,点击右键,选择 “运行测试” ,选项测试经过了。
咱们如今给出一个错误的预期来看看结果会如何,咱们如今认为 "123.txt" 文件有50个字符。
系统会提示出错,而且给出实际值与指望值分别是多少。
编写测试方法
单元测试的基本方法是调用被测代码的函数,输入函数的参数值,获取返回结果,而后与预期测试结果进行比较,若是相等则认为测试经过,不然认为测试不经过。
一、Assert类的使用
Assert.Inconclusive() 表示一个未验证的测试;
Assert.AreEqual() 测试指定的值是否相等,若是相等,则测试经过;
AreSame() 用于验证指定的两个对象变量是指向相同的对象,不然认为是错误
AreNotSame() 用于验证指定的两个对象变量是指向不一样的对象,不然认为是错误
Assert.IsTrue() 测试指定的条件是否为True,若是为True,则测试经过;
Assert.IsFalse() 测试指定的条件是否为False,若是为False,则测试经过;
Assert.IsNull() 测试指定的对象是否为空引用,若是为空,则测试经过;
Assert.IsNotNull() 测试指定的对象是否为非空,若是不为空,则测试经过;
二、CollectionAssert类的使用
用于验证对象集合是否知足条件
StringAssert类的使用
用于比较字符串。
StringAssert.Contains
StringAssert.Matches
StringAssert.tartWith