利用单元测试框架进行单元测试

单元测试目的是为了保证代码按照程序员的预期运行,往往关注的是比其他测试更低的层次,从而确定代码的底层功能是否与期望一致。

对于API框架而言,单元测试的一个重要优点在于测试在编译阶段就引入了依赖关系,从而使之更容易确定代码的更改是否会影响API表示的契约。

单元测试程序集与被测代码一般要分离开,这样可以保证在对应用程序代码进行部署时不包含单元测试,因为单元测试代码在产品环境中没有什么用。

代码的独立单元测试越容易,就越容易维护。

所有测试都应该是自主的和独立的,且应该对期望行为和错误情况都进行测试。

假设有以下内容需要被测:

 1 namespace ExtendedMath
 2 {
 3     public static class Functions
 4     {
 5         public static int Fibonacci(int factor)
 6         {
 7             if (factor < 2)
 8             {
 9                 return (factor);
10             }
11             int x = Fibonacci(--factor);
12             int y = Fibonacci(--factor);
13             return x + y;
14         }
15     }
16 }

接下来创建单元测试验证Fibonacci实现,只有包含在独立的test project项目中之后,单元测试才会被称为测试。

创建一个单元测试项目,添加上述代码的命名空间引用,且在测试类最上方添加引用:

1 using ExtendedMath;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;

为了使Visual Studio识别包含单元测试的类,必须给TestClass特性赋值,如果忘记添加TestClass特性,那么将找不到类中的单元测试方法。单元测试需要存放在公有的类中,因此一定要将类标记为public,单元测试方法必须是公有的和非静态的,而且没有参数和返回值,为了区别单元测试方法与普通方法,需要使用TestMethod特性。此时我们看到代码如下:

 1 namespace ExtendedMath
 2 {
 3     [TestClass]
 4     public class FunctionsTest
 5     {
 6         [TestMethod]
 7         public void FibonacciTest()
 8         {
 9         }
10     }
11 }

单元测试是通过抛出异常的方式向Visual Studio指示失败的。未抛出异常的测试都认为是通过的,除非测试针对的是ExpectedException特性,单元测试框架定义了Assert对象。在FibonacciTest()方法中添加代码:

1         [TestMethod]
2         public void FibonacciTest()
3         {
4             const int FACTOR = 8;
5             const int Expected = 21;
6             int actual = ExtendedMath.Functions.Fibonacci(FACTOR);
7
8             Assert.AreEqual(Expected, actual);
9         }

在编写单元测试方法时,3A模式很有帮助——Arrange, Act, Assert. 首先建立变量安排测试,然后测试调用代码,最后断言调用代码是否与期望值一致。对于每个A都应该建立相对独立的代码段。

使用TestInitialize特性创建一个方法,该方法将会在当前类的每个单元测试方法执行之前执行一次。类似的,TestCleanup总是在每个测试执行之后立即执行。与单元测试类似,包含有这些特性的方法必须是公有的和非静态的,并且没有参数和返回值。TestInitialize运行之后立即运行单元测试,单元测试运行之后立即运行TestCleanup。

无论进行多少次单元测试ClassInitialize和ClassCleanup特性均在当前类中只运行一次。这两个方法是静态的,并接受一个TestContext实例作为参数。

可以使用ClassInitialize和ClassCleanup控制类一级的操作,而对于程序集一级的操作则需要用到AssemblyInitialize和AssemblyCleanup特性。例如,用AssemblyInitialize修饰的方法会在当前程序集的任意一个测试执行之前执行,而不是仅仅针对当前类中的测试。这些方法也必须是静态的,且接受一个TestContext类型的参数。

当多个类之间有公共操作时,就可以考虑使用AssemblyInitialize和AssemblyCleanup特性,但此时并不是针对每个类都调用初始化和清除方法,而是使用程序集一级的方法。

确定单元测试成功与否的常用方法是将期望结果与实际结果进行比较。

Assert.AreSame/Asser.AreNotSame常见用法是保证属性返回期望的实例,或集合能正确处理引用,它们用来验证两个参数状态相同的情况下实际上是否指向同一个对象。

通常,单元测试都会有一个TestContext实例的引用,该对象用于向测试提供运行时的功能,如测试本身的详细信息、所用的各种目录以及提供存储在测试结果中详细信息的方法等。

对代码行为进行验证的最好的方法是利用真实的数据执行代码。Visual Studio提供了为单元测试自动绑定数据源作为输入的功能。单元测试将会对每个数据行都运行一次。

如何对类的非公有成员进行测试呢?假如正在编写一个私有函数,它不可以被公开访问,而只能由内部其他成员访问,我们想要测试该方法,但测试代码却无法访问私有成员,通常有4种方法处理:

  1. 将需要测试的私有成员更改为公有成员
  2. 将需要测试的私有成员更改为内部成员,并将测试程序集添加到原始程序集的internalsVisibleTo特性中
  3. 保证需要测试的私有成员能够通过公有成员访问,然后通过那些公有成员进行测试
  4. 在测试中用.NET反射加入并直接调用那些非公有成员

假设要对下面这个类的私有数据字段和方法进行测试:

 1     public class Example
 2     {
 3         public Example()
 4         { }
 5         private string password = "letmein";
 6         private bool VerifyPassword(string password)
 7         {
 8             return (string.Compare(this.password, password, false) == 0);
 9         }
10     }

Visual Studio引入了PrivateObject类,它对反射代码进行了封装,通过这个类可以以一种非常直接的方式访问非公有成员。要使用这个类,首先需要创建该类的一个实例,其参数是所需处理的类的Type对象:

 1 namespace Explorations
 2 {
 3     [TestClass]
 4     public class ExampleTest
 5     {
 6         private PrivateObject privateObject;
 7         const string PASSWORD = "letmein";
 8
 9         [TestInitialize]
10         public void TestInitialize()
11         {
12             privateObject = new PrivateObject(typeof(Example));
13         }
14     }
15 }

接下来就可以创建测试了:

 1 namespace Explorations
 2 {
 3     [TestClass]
 4     public class ExampleTest
 5     {
 6         private PrivateObject privateObject;
 7         const string PASSWORD = "letmein";
 8
 9         [TestInitialize]
10         public void TestInitialize()
11         {
12             privateObject = new PrivateObject(typeof(Example));
13         }
14
15         [TestMethod]
16         public void ComparePrivatePassword()
17         {
18             string password = (string)privateObject.GetField("password");
19             Assert.AreEqual(PASSWORD, password);
20         }
21
22         [TestMethod]
23         public void TestPrivateVerifyPassword()
24         {
25             bool accepted = (bool)privateObject.Invoke("VerifyPassword", PASSWORD);
26             Assert.IsTrue(accepted);
27         }
28     }
29 }

由于PrivateClass使用了反射,因此,必须将调用结果从通用Object类型转换成正确的类型。

PrivateObject用于访问类的实例成员,如果要访问非公有静态成员,则需要用到PrivateType类,它的接口与PrivateObject非常类似,也对反射代码进行了封装。

Visual Studio单元测试功能全面支持代码覆盖,代码覆盖会自动插入跟踪逻辑(插装过程)以监视测试执行过程中哪些代码执行到了。它最重要的作用就是发现那些在测试中没有涉及到的代码段。

说明单元测试的有效性的一条原则是,删除任何一行代码都会导致至少一个单元测试的失败。

启用代码覆盖并选中了要插装的程序集之后,接下来运行测试,从Code Coverage Results窗口中可以浏览覆盖的结果:

100%的代码覆盖并不意味着单元测试已充分了,正确的测试需要使用不同的数据对相同的代码进行多次测试。代码覆盖是测试有效性的一种度量手段,但肯定不是唯一的。

使用测试影响分析可以在修改代码之后浏览哪些测试受到了代码更改的影响,这不仅限于单元测试,甚至适用于那些先前已执行的针对某个生成的手动测试。

在使用测试影响分析之前,首先必须在VS内使用单元测试框架,并将源代码存储在TFS Version Control中,然后在运行单元测试时启用数据收集功能。如果单元测试是在本地或通过MTM(Microsoft Team Manager)运行的,那么就必须将测试结果上传到TFS并将其与一个团队生成相关联之后才能进行测试影响分析。这里不做过多介绍。

时间: 2024-10-02 02:43:22

利用单元测试框架进行单元测试的相关文章

第六章:单元测试框架unittest

单元测试框架unittest 单元测试 单元测试(unit testing)是指对软件中的最小可测试单元进行检查和验证.对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等.总的来说,单元就是人为规定的最小的被测功能模块. 单元测试框架 在单元测试框架出现之前,开发人员在创建可执行测试时饱受折磨.最初的做法是在应用程序中创建一个窗口,配有"测试控制工具(harness)".它只是一

第 6 章 unittest 单元测试框架 - Selenium3 自动化测试

第 6 章 unittest 单元测试框架 单元测试是一项对技术要求很高的工作,只有白盒测试人员和软件开发人员才能胜任但用单元测试框架做单元测试却十分简单,而且单元测试框架不仅可以用来做单元测试,它还适用于不同类型的「自动化」测试. 1.提供测试用例组织和执行在 Python 中,我们编写的代码可以定义类.方法和函数,那么如何定义一条「测试用例」?如何灵活地控制这些「测试用例」的执行?单元测试框架会告诉我们. 2.提供丰富的断言方法当我们进行功能测试时,测试用例需要有预期结果.当测试用例的执行结

Django中的单元测试以及Python单元测试

Python单元测试 是用来对一个模块.一个函数或者一个类进行正确性检验的测试工作. 在Python中unittest是它内置的单元测试框架,单元测试与功能测试都是日常开发中必不可少的部分. 比如对函数abs(),我们可以编写出一下几个测试用例: 输入正数,比如1,1.2,0.99,我们期待返回值与输入相同 输入负数,比如-1,-1.2,-0.99,我们期待返回值与输入值相反 输入0,我们期待返回0 输入非数值类型,比如None,[],{},我们期待抛出TypeError 把上面的测试用例放到一

Selenium基于Python web自动化基础二 -- 免登录、等待及unittest单元测试框架

一.免登录在进行测试的过程中难免会遇到登录的情况,给测试工作添加了工作量,本文仅提供一些思路供参考解决方式:手动请求中添加cookies.火狐的profile文件记录信息实现.人工介入.万能验证码.去掉验证码 1.手动在请求中添加cookies信息 1 url = "http://www.baidu.com" 2 driver = webdriver.Firefox() 3 driver.get(url) 4 time.sleep(3) 5 #添加cookies的方式 6 7 c1 =

如何使用VS2013本地C++单元测试框架

在VS2013中,可以使用VS自带的C++单元测试框架. 在使用该框架前,需要先安装Unit Test Generator(可以通过菜单“工具->扩展和更新”搜索安装). 下边,就阐述一下利用该框架的步骤: 1. 新建空的Win32控制台项目NativeUnitTest 将该工程的"配置类型"改为“动态库(dll)”,如下图: 2. 新建单元测试工程 在解决方案NativeUnitTest下新建单元测试工程,“Visual C++ -> 测试 -> 本机单元测试项目”

单元测试框架

单元测试1框架是软件测试框架2的一种. 包括了xUnit,JUnit,QUnit,NUnit等.而其中的JUnit,QUnit,NUnit都是xUnit家族中的成员. xUnit xUnit是各种代码驱动测试框架的统称,可以测试软件的不同单元.xUnit的特点是:提供了一个自动化测试3的解决方案,无须多次编写重复的测试代码,也无须记住该测试的预期结果. 四要素: 测试Fixtures Fixture指被测试的目标.而测试Fixture是一组单元测试成功的预定条件或预期结果的设定. 测试集 测试集

Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)

本文是Java反射学习总结系列的最后一篇了,这里贴出之前文章的链接,有兴趣的可以打开看看. http://blog.csdn.net/a396901990/article/category/2302221 本文介绍了如何利用反射和注解去简单的模拟JUnit4单元测试框架,之所以选择JUnit4是因为4.0以后最大的改进就是使用了注解.需要注意的是这里并不是完全的模拟,只是简单实现了一下Runner类和JUnit注解相关的工作流程.所以本文的主要目的是介绍反射和注解的使用.废话不多说,直接进入正文

Python+Selenium ----unittest单元测试框架

unittest是一个单元测试框架,是Python编程的单元测试框架.有时候,也做叫做"PyUnit",是Junit的Python语言版本.这里了解下,Junit是Java语言的单元测试框架,Java还有一个很好用的单元测试框架叫TestNG,本系列只学习Python,所以只需要unittest是Python里的一个单元测试框架就可以了.       unittest支持测试自动化,共享测试用例中的初始化和关闭退出代码,在unittest中最小单元是test,也就是一个测试用例.要了解

eclipse上使用JUnit框架进行单元测试

JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写. 先 简单解释一下什么是Annotation,这个单词一般是翻译成元数据.元数据是什么?元数据就是描述数据的数据.也就是说,这个东西在Java里面可以 用来和public.static等关键字一样来修饰类名.方法名.变量名.修饰的作用描述这个数据是做什么用的,差不多和public描述这个数据是公 有的一样.想具体了解可以看Core    Java2.废话不多说了,直接进入正题