基于C#的单元测试(VS2015)

这次来联系怎么用VS2015来进行C#代码的单元测试管理,首先,正好上次写了一个C#的WordCount程序,就用它来进行单元测试联系吧。

首先,根据VS2015的提示,仅支持在共有类或共有方法中支持创建单元测试。所以,如果我们要测试私有或是保护的类和方法,是要先将他们暂时设定成公有类型。

在VS2015中创建单元测试非常简单,只要在我们想测试的地方点击右键,就会出现 “创建单元测试” 选项。

如果发现菜单没有显示,可以参照这篇博客进行设置。http://www.bubuko.com/infodetail-1370830.html

单击 “创建单元测试” 后,会出项如下对话框。不用修改,保持默认选项就可以。

点击“确定”,耐心等待一会。

创建完成后,会出项一个名为 “WCTests” 的文件,文件初始代码为

 1 using Microsoft.VisualStudio.TestTools.UnitTesting;
 2 using wc;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8
 9 namespace wc.Tests
10 {
11     [TestClass()]
12     public class WCTests
13     {
14         [TestMethod()]
15         public void WCTest()
16         {
17             Assert.Fail();
18         }
19
20         [TestMethod()]
21         public void OperatorTest()
22         {
23             Assert.Fail();
24         }
25     }
26 }

在进行单元测试时,主要使用的是 Assert 类,他的用发有很多,详细用法可以参照 https://msdn.microsoft.com/zh-cn/library/microsoft.visualstudio.testtools.unittesting.assert.aspx

下面给出我们要进行测试的代码,为了方便测试,我们对其中代码输出的部分进行了修改,将原先控制台输出的部分改成了函数返回。

  1 public class WC
  2 {
  3     private string sFilename;    // 文件名
  4     private string[] sParameter; // 参数数组
  5     private int iCharcount;      // 字符数
  6     private int iWordcount;      // 单词数
  7     private int iLinecount;      // 行  数
  8     private int iNullLinecount;  // 空行数
  9     private int iCodeLinecount;  // 代码行数
 10     private int iNoteLinecount;  // 注释行数
 11
 12     // 初始化
 13     public WC()
 14     {
 15         this.iCharcount = 0;
 16         this.iWordcount = 0;
 17         this.iLinecount = 0;
 18         this.iNullLinecount = 0;
 19         this.iCodeLinecount = 0;
 20         this.iNoteLinecount = 0;
 21     }
 22     // 控制信息
 23     public string Operator(string[] sParameter, string sFilename)
 24     {
 25         this.sParameter = sParameter;
 26         this.sFilename = sFilename;
 27
 28         string retrun_str = "";
 29
 30         foreach (string s in sParameter)
 31         {
 32             if(s == "-x")
 33             {
 34                 string resultFile = "";
 35                 OpenFileDialog fd = new OpenFileDialog();
 36                 fd.InitialDirectory = "D:\\Patch";
 37                 fd.Filter = "All files (*.*)|*.*|txt files (*.txt)|*.txt";
 38                 fd.FilterIndex = 2;
 39                 fd.RestoreDirectory = true;
 40                 if (fd.ShowDialog() == DialogResult.OK)
 41                 {
 42                     resultFile = fd.FileName;
 43                     //Console.WriteLine("文件名:{0}", resultFile);
 44                     SuperCount(resultFile);
 45                     BaseCount(resultFile);
 46                     retrun_str = DisplayAll();
 47                 }
 48                 break;
 49             }
 50             // 遍历文件
 51             else if (s == "-s")
 52             {
 53                 try
 54                 {
 55                     string[] arrPaths = sFilename.Split(‘\\‘);
 56                     int pathsLength = arrPaths.Length;
 57                     string path = "";
 58
 59                     // 获取输入路径
 60                     for (int i = 0; i < pathsLength - 1; i++)
 61                     {
 62                         arrPaths[i] = arrPaths[i] + ‘\\‘;
 63
 64                         path += arrPaths[i];
 65                     }
 66
 67                     // 获取通配符
 68                     string filename = arrPaths[pathsLength - 1];
 69
 70                     //  获取符合条件的文件名
 71                     string[] files = Directory.GetFiles(path, filename);
 72
 73                     foreach (string file in files)
 74                     {
 75                         //Console.WriteLine("文件名:{0}", file);
 76                         SuperCount(file);
 77                         BaseCount(file);
 78                         retrun_str = Display();
 79                     }
 80                     break;
 81                 }
 82                 catch (IOException ex)
 83                 {
 84                     //Console.WriteLine(ex.Message);
 85                     return "";
 86                 }
 87             }
 88             // 高级选项
 89             else if (s == "-a")
 90             {
 91                 //Console.WriteLine("文件名:{0}", sFilename);
 92                 SuperCount(sFilename);
 93                 BaseCount(sFilename);
 94                 retrun_str = Display();
 95                 break;
 96             }
 97             //  基本功能
 98             else if (s == "-c" || s == "-w" || s == "-l")
 99             {
100                 //Console.WriteLine("文件名:{0}", sFilename);
101                 BaseCount(sFilename);
102                 retrun_str = Display();
103                 break;
104             }
105             else
106             {
107                 //Console.WriteLine("参数 {0} 不存在", s);
108                 break;
109             }
110         }
111         Console.WriteLine("{0}", retrun_str);
112         return retrun_str;
113     }
114
115     // 统计基本信息:字符数 单词数 行数
116     private void BaseCount(string filename)
117     {
118         try
119         {
120             // 打开文件
121             FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
122             StreamReader sr = new StreamReader(file);
123             int nChar;
124             int charcount = 0;
125             int wordcount = 0;
126             int linecount = 0;
127             //定义一个字符数组
128             char[] symbol = { ‘ ‘, ‘,‘, ‘.‘, ‘?‘, ‘!‘, ‘:‘, ‘;‘, ‘\‘‘, ‘\"‘, ‘\t‘, ‘{‘, ‘}‘, ‘(‘, ‘)‘, ‘+‘ ,‘-‘,
129                   ‘*‘, ‘=‘};
130             while ((nChar = sr.Read()) != -1)
131             {
132                 charcount++;     // 统计字符数
133
134                 foreach (char c in symbol)
135                 {
136                     if(nChar == (int)c)
137                     {
138                         wordcount++; // 统计单词数
139                     }
140                 }
141                 if (nChar == ‘\n‘)
142                 {
143                     linecount++; // 统计行数
144                 }
145             }
146             iCharcount = charcount;
147             iWordcount = wordcount + 1;
148             iLinecount = linecount + 1;
149             sr.Close();
150         }
151         catch (IOException ex)
152         {
153             Console.WriteLine(ex.Message);
154             return;
155         }
156     }
157
158     // 统计高级信息:空行数 代码行数 注释行数
159     private void SuperCount(string filename)
160     {
161         try
162         {
163             // 打开文件
164             FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
165             StreamReader sr = new StreamReader(file);
166             String line;
167             int nulllinecount = 0;
168             int codelinecount = 0;
169             int notelinecount = 0;
170             while ((line = sr.ReadLine()) != null)
171             {
172                 line = line.Trim(‘ ‘);
173                 line = line.Trim(‘\t‘);
174                 //   空行
175                 if (line == "" || line.Length <= 1)
176                 {
177                     nulllinecount++;
178                }
179                //   注释行
180                else if(line.Substring(0, 2) == "//" || line.Substring(1, 2) == "//")
181                {
182                     notelinecount++;
183                }
184                // 代码行
185                else
186                {
187                     codelinecount++;
188                }
189             }
190             iNullLinecount = nulllinecount;
191             iCodeLinecount = codelinecount;
192             iNoteLinecount = notelinecount;
193             sr.Close();
194         }
195         catch (IOException ex)
196         {
197             Console.WriteLine(ex.Message);
198             return;
199         }
200     }
201     // 打印信息
202     private string Display()
203     {
204         string return_str = "";
205
206         foreach (string s in sParameter)
207         {
208             if (s == "-c")
209             {
210                 //Console.WriteLine("字 符 数:{0}", iCharcount);
211                 return_str += "字符数:"+iCharcount.ToString();
212             }
213             else if (s == "-w")
214             {
215                 //Console.WriteLine("单 词 数:{0}", iWordcount);
216                 return_str += "单词数:" + iWordcount.ToString();
217             }
218             else if (s == "-l")
219             {
220                 //Console.WriteLine("总 行 数:{0}", iLinecount);
221                 return_str += "总行数:" + iLinecount.ToString();
222             }
223             else if(s == "-a")
224             {
225                 //Console.WriteLine("空 行 数:{0}", iNullLinecount);
226                 //Console.WriteLine("代码行数:{0}", iCodeLinecount);
227                 //Console.WriteLine("注释行数:{0}", iNoteLinecount);
228                 return_str += "空行数:" + iNullLinecount.ToString();
229                 return_str += "代码行数:" + iCodeLinecount.ToString();
230                 return_str += "注释行数:" + iNoteLinecount.ToString();
231             }
232         }
233         //Console.WriteLine();
234         return return_str;
235     }
236     private string DisplayAll()
237     {
238         string return_str = "";
239         foreach (string s in sParameter)
240         {
241             //Console.WriteLine("字 符 数:{0}", iCharcount);
242             //Console.WriteLine("单 词 数:{0}", iWordcount);
243             //Console.WriteLine("总 行 数:{0}", iLinecount);
244             //Console.WriteLine("空 行 数:{0}", iNullLinecount);
245             //Console.WriteLine("代码行数:{0}", iCodeLinecount);
246             //Console.WriteLine("注释行数:{0}", iNoteLinecount);
247             return_str += "字符数:" + iCharcount.ToString();
248             return_str += "单词数:" + iWordcount.ToString();
249             return_str += "总行数:" + iLinecount.ToString();
250             return_str += "空行数:" + iNullLinecount.ToString();
251             return_str += "代码行数:" + iCodeLinecount.ToString();
252             return_str += "注释行数:" + iNoteLinecount.ToString();
253         }
254         //Console.WriteLine();
255         return return_str;
256     }
257 }

接下来,我们对测试代码进行修改,在我们进行单元测试时,某种程度上就是将我们人工给出的程序运行结果与程序实际输出结果进行比较,所以单元测试的过程一般分为 3 步:

  • 给出我们期望的结果 expected
  • 执行需测试代码,返回结果 actual
  • 比较 actual 和 expected

下面以 WC 程序执行 -c 参数对 123.txt 文件进行统计的功能为例进行测试,我们将测试代码修改如下,其中 AreEqual 方法用于对期望值与实际值进行比较。

 1 using Microsoft.VisualStudio.TestTools.UnitTesting;
 2 using wc;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8
 9 namespace wc.Tests
10 {
11     [TestClass()]
12     public class WCTests
13     {
14         [TestMethod()]
15         public void WCTest()
16         {
17             // arrange
18             string expected = "字符数:138";
19             WC testwc = new WC();
20
21             // act
22             string[] opar = new string[1];
23             opar[0] = "-c";
24
25             string actual =  testwc.Operator(opar, @"D:\学习\我的工程\软件工程\wc\wc\wc\123.txt");
26
27             // assert
28             Assert.AreEqual(expected, actual);
29         }
30     }
31 }

"123.txt" 文件为

我们预期的测试结果是此文件有138个字符,所以会输出 “字符数:138” ;我们来看看测试的结果,点击右键,选择 “运行测试” ,选项测试通过了。

我们现在给出一个错误的预期来看看结果会如何,我们现在认为 "123.txt" 文件有50个字符。

系统会提示出错,并且给出实际值与期望值分别是多少。至此,我们已经完成了简单的C#单元测试。接下来,只需要对测试代码进行修改,测试跟多的样例,来对代码进行测试。

时间: 2024-10-12 08:09:47

基于C#的单元测试(VS2015)的相关文章

单元测试和白盒测试相关总结

一.  软件测试方法 1.        软件测试方法包括:白盒测试(White  Box  Testing).黑盒测试(Black  Box Testing).灰盒测试.静态测试.动态测试. 2.        白盒测试:是一种测试用例设计方法,在这里盒子指的是被测试的软件,白盒,顾名思义即盒子是可视的,你可以清楚盒子内部的东西以及里面是如何运作的,因此白盒测试需要你对系统内部的结构和工作原理有一个清楚的了解,并且基于这个知识来设计你的用例. 白盒测试技术一般可被分为静态分析和动态分析两类技术

使用 Spring 进行单元测试

单元测试和集成测试在我们的软件开发整个流程中占有举足轻重的地位,一方面,程序员通过编写单元测试来验证自己程序的有效性,另外一方面,管理者通过持续自动的执行单元测试和分析单元测试的覆盖率等来确保软件本身的质量.这里,我们先不谈单元测试本身的重要性,对于目前大多数的基于 Java 的企业应用软件来说,Spring 已经成为了标准配置,一方面它实现了程序之间的低耦合度,另外也通过一些配置减少了企业软件集成的工作量,例如和 Hibernate.Struts 等的集成.那么,有个问题,在普遍使用 Spri

Android studio 怎么使用单元测试(不需要device)

关于单元测试的使用,写代码过程中有时候需要检测下代码逻辑的可行性与正确性,又不想通过设备运行,那么就可以通过单元测试跑下代码~ 1.首先建立一个Android studio的Android项目: 2. 可以看到有3个不同类别的代码文件夹 第一个是真正的项目文件夹,第二个是基于Android设备单元测试的文件夹,第三个是基于java虚拟机的单元测试文件夹 3.添加测试代码,用于测试 选中[test]文件夹,直接 Ctrl + shift + F10 运行(或者进入ExampleUnitTest类,

数据访问层的单元测试

出处:http://www.cnblogs.com/wintersun/ 数据访问层在分层结构,比较常见. 有时可能是数据访问模块. 假设数据访问层后端是数据库,那我们如何测试他们的呢? 有时实际这种测试是集成测试了.有时数据库里还有一些逻辑,触发器,约束等. 个人十分不建议把业务逻辑放在数据库里实现. 最常见的数据库表的操作create, read, update和delete(简称CRUD), 例如我们需要测试某个Add方法,在这个测试方法完成后, 希望这条测试数据清除掉. 这样做是 为了不

领域驱动设计之单元测试最佳实践(二)

领域驱动设计之单元测试最佳实践(一) 介绍完了DDD案例,我们终于可以进入主题了,本方案的测试代码基于Xunit编写,断言组件采用了FluentAssertions,类似的组件还有Shouldly.另外本案例使用了Code Contracts for .NET,如果不安装此插件,可能有个别测试不能正确Pass. 为了实现目标中的第二点:"尽量不Mock,包括数据库读取部分”,我尝试过3种方案: 1.测试代码连接真实数据库,只需要将测试数据库配置到测试项目中的web.config中,即可达到这一目

Spring 单元测试的学习

单元测试和集成测试在我们的软件开发整个流程中占有举足轻重的地位,一方面,程序员通过编写单元测试来验证自己程序的有效性,另外一方面,管理者通过持续自动的执行单元测试和分析单元测试的覆盖率等来确保软件本身的质量.这里,我们先不谈单元测试本身的重要性,对于目前大多数的基于 Java 的企业应用软件来说,Spring 已经成为了标准配置,一方面它实现了程序之间的低耦合度,另外也通过一些配置减少了企业软件集成的工作量,例如和 Hibernate.Struts 等的集成.那么,有个问题,在普遍使用 Spri

测试篇——初探单元测试

初探单元测试 目录: 单元测试的核心意义 单元测试的特点 一个简单的单元测试demo 构建可测试的代码以及初探Mock框架NSubstitute 单元测试的核心意义 验证代码健壮性,无 Bug 项目升级,重构后涉及到旧的逻辑,保证以旧逻辑的稳定运行 单元测试的特点 单元测试可重复运行 单元测试持续长期有效,并且返回结果一致 单元测试在内存中运行,不会依赖外部组建(例如真实的数据库,真实的文件等) 单元测试可以快速返回结果 一个测试方法只测试一个问题(最小的粒度) 一个简单的单元测试demo 这里

基于Jenkins Pipeline的ASP.NET Core持续集成实践

原文:基于Jenkins Pipeline的ASP.NET Core持续集成实践 最近在公司实践持续集成,使用到了Jenkins的Pipeline来提高团队基于ASP.NET Core API服务的集成与部署,因此这里总结一下. 一.关于持续集成与Jenkins Pipeline 1.1 持续集成相关概念 互联网软件的开发和发布,已经形成了一套标准流程,最重要的组成部分就是持续集成(Continuous integration,简称 CI) . 持续集成指的是,频繁地 (一天多次) 将代码集成到

对于ESP32开发版单元测试源码分析

源码目录结构 ESP32官方提供的源码资源很丰富,有兴趣的开发者可选择下载,参见下图.另外也提供了ESP32的IOT解决方案. 可以看出,整个目录结构完全按照功能模块来划分,每个功能模块都有自己的CMakeList.txt文件,main文件夹,Makefile文件,以及README.md文件. 分别代表: CMakeList.txt: CMake 是一个跨平台的自动化建构系统,它使用CMakeLists.txt文件来描述构建过程,可以产生标准的构建文件,如 Unix 的 Makefile 或Wi