根據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