Aicken教你做测试之使用并行计算进行单元测试

百般思念 提交于 2019-12-22 12:34:37

   本文分别在VS2008和VS2010 With Parallel,进行了相同代码的单元测试,其中使用Parallel后,性能的提升还是比较令人满意的,示例中包含了使用Parallel(TestStrBTest()用例)和使用普通foreach的测试用例,感兴趣的同学可以下载来跑一下。

    http://files.cnblogs.com/isline/TestApplication.rar

概要

    单元测试是一种辅助开发的测试方法,是在开发阶段进行的,测试人员与开发人员可以分别对需要的模块进行单元测试。

单元测试的对象,在函数式变成语言中可以是过程,在OOP语言中可以是类。

    类的划分与建立是否合理,是单元测试是否能顺利进行的关键,建模很大意义在上决定了单元测试的适应度。

    单元测试是一种白盒与黑盒都适用的方法,与其紧密相关联的环节有代码的复审、走读、静态分析与动态分析,所以单元测试是白盒测试或灰盒测试。开发人员为主要测试实施者,进行白盒测试,测试人员进行灰盒测试。二种角色在实施单元测试时没有过多的交集,且要保持彼此的隔离。我写的是程序人员进行的白盒单元测试。

    这篇文档主要为大家介绍与开发人员相关的动态分析单元测试。

    单元测试是一种偏向白盒测试的方法,由于测试人员很难使用相应的语言编写单元测试用例,并对代码进行高覆盖度的测试,所以单元测试一般由程序人员本着“尽可能早”的原则完成。但一个标准规范的单元测试或是一个由TDD指导的项目开发模型,单元测试用例是测试工程师与程序设计师,在程序设计(概要设计、详细设计)阶段完成的,这些用例将规约编码过程,并作为验收依据之一。

    下面我画了两个图,来说明测试过程和单元测试过程的概要。

    1.测试工作概览:

 

    图 1 测试全程示意图

    测试工作是贯穿软件工程始终的,测试的唯一目的是发现系统bug,系统中永远存在着bug,所以没有发现bug的集成测试不是成功的测试。

    测试工作一般分为用例的设计与开发,测试与系统设计和程序开发的唯一参考是系统分析说明书,测试人员与系统设计人员和开发人员,需要根据系统分析书设计相关工作,不可自己杜撰,《系统分析说明书》是测试的依据、设计与开发的依据,亦是验收的依据。

    用例设计在系统分析环节中、后开始,单元测试用例设计环节在系统设计环节开始,系统经过单元测试—集成测试—确认测试后进行迭代或交付,测试工作截止于输入边界,即至少进行一次迭代。

    从上图中可以看出,单元测试是在详细设计、编码后开始,集成测试前完成的。单元测试又可分为离散单元测试和集成单元测试,本文主要讲解离散单元测试,即上图中桔红色椭圆内的工作。

    单元测试是根据需求与程序行为,编写测试用例,测试用例编写语言,可以与测试标的系统程序相同或不同,但需要通过断言比较的,如果用例运行通过就说明测试通过。这次做这个Demo程序编写与用例编写时间大概是1:5(只包括VS2008下实施),还不包括用例设计时间。

    2.单元测试概览:

    图 2 单元测试全程示意图

    从上图可以看出,衡量单元测试是否完善与确实的一个很重要的体系,是代码覆盖度,语句覆盖为最低,路径覆盖为最高,根据领导要求咱么自己把握。

    单元测试起始于驱动模块终止于桩模块,用例设计、编译、运行、驱导模块、桩模块共同组成了单元测试的配置环境。

单元测试需要涉及对I/O、局部数据、逻辑覆盖、出错处理等目标进行把控,覆盖度从低到高依次为语句覆盖、判定覆盖、条件覆盖、边覆盖、点覆盖、条件组合覆盖、路径覆盖。

    单元测试用例设计、编写后可以考虑引入用例评审环节,然后进行用例测试。

    工具

    Visual Studio与NUnit都可以进行单元测试,NUnit可以集成至Visual Studio中,并可以单独测试DLL方式进行单元测试,所以用的人比较多,但在TFS中会对VS2010的各项测试功能进行集成并获得提升,所以这里着重介绍在Visual Studio中进行单元测试的方法了。

    方法

    使用Visual Studio 2008进行单元测试。

    Step 1.构建代码与单元测试框架

    a.假设我们有如下代码需要测试:

 

 

代码
public class Class1 {    public string TestStrA(string strA)   {      return strA + "TestStrA";   }   public int TesIntB(int i)   {      if (i <= 1000) return 0;      else return i + 1;   }   private string TestStrB(string strB)   {      return strB + "TestStrB";   }   protected string TestStr(string str)   {      return str;   } } 

 

 

    b.在类名上单击右键,创建单元测试:

    c.点击“确定”,这时单元测试框架已经搭好

Step 2.编写单元测试代码

    编写单元测试代码需要根据方法的实际任务去完成单元测试代码,拿“TesIntB”来说,这个方法传入一个参数i,如果i小于等于1000,那么方法将返回0;否则则将i加1后返回。

 

public int TesIntB(int i) {   if (i <= 1000) return 0;   else return i + 1; } 

 

 

    那么,编写单元测试代码时,就需要根据这两种情况进行测试,这个例子中,我使用了两个用例来测试该方法,代码覆盖度100%,即“TesIntBTestLessThan1000()”和“TesIntBTestMoreThan1000()”。

    测试需要一个样本空间,例子中的样本空间实现比较简单,使用一个“EntityForUnitTest”泛型类提供样本,                EntityForUnitTest中字段有标志样本数据类型和样本值,测试用例使用Linq根据具体情况取出测试样本。

    样本空间的建立:

 

代码
//样本实体 public class EntityForUnitTest {   public UnitTestValueType Type { get; set; }   public string ContentValue { get; set; } } //样本值类型 public enum UnitTestValueType {   Integer,   String } public class EventsForUnitTest { //样本赋值 public static List<EntityForUnitTest> GetEntityForUnitTests() {   List<EntityForUnitTest> LEFUT = new       List<EntityForUnitTest>();   EntityForUnitTest eft = new EntityForUnitTest();   for (int i=0; i <= 2000; i++)   {     eft = new EntityForUnitTest();     eft.Type = UnitTestValueType.Integer;     eft.ContentValue = i.ToString();     LEFUT.Add(eft);   }   for (int i=0; i <= 2000; i++)   {     eft = new EntityForUnitTest();     eft.Type = UnitTestValueType.String;     eft.ContentValue = "b2c" + i.ToString();     LEFUT.Add(eft); }   return LEFUT; } } 

 

 

    使用以上样本,这是一个测试用例的代码:

 

代码
//输入小于1000,预期输出0 [TestMethod()] public void TesIntBTestLessThan1000() {   Class1 target = new Class1(); // TODO: 初始化为适当的值   var result = from EntityForUnitTest p in LEFUT   where p.Type == UnitTestValueType.Integer &&   Convert.ToInt32(p.ContentValue) <= 1000 select p;   foreach (EntityForUnitTest efut in result) {   int i = Convert.ToInt32(efut.ContentValue);   int expected = 0;   int actual;   actual = target.TesIntB(i);   Assert.AreEqual(expected, actual); } } //输入大于1000,预期输出为输入+1 public void TesIntBTestMoreThan1000() {   Class1 target = new Class1(); // TODO: 初始化为适当的值   var result = from EntityForUnitTest p in LEFUT where p.Type == UnitTestValueType.Integer &&   Convert.ToInt32(p.ContentValue) > 1000 select p; foreach (EntityForUnitTest efut in result) {   int i = Convert.ToInt32(efut.ContentValue);   int expected = i+1;   int actual;   actual = target.TesIntB(i);   Assert.AreEqual(expected, actual); } } 

 

 

    按照此方法,一次编写需要的测试用例,然后继续。

    Assert方法列表:

方法

解释

AreEqual

测试指定的值是否相等;如果两个值不相等,则测试失败。

AreNotEqual

测试指定的值是否不相等;如果两个值相等,则测试失败。

AreSame

测试指定的对象是否都引用相同的对象;如果两个输入内容引用不同的对象,则测试失败。

AreNotSame

测试指定的对象是否引用不同的对象;如果两个输入内容引用相同的对象,则测试失败。

Fail

断言失败。

Inconclusive

表示无法证明为 true 或 false 的测试结果。

IsTrue

试指定的条件是否为 true;如果该条件为 false,则测试失败。

IsFalse

测试指定的条件是否为 false;如果该条件为 true,则测试失败。

IsNull

测试指定的对象是否为 空引用(在 Visual Basic 中为 Nothing);如果它不为空,则测试失败。

IsNotNull

测试指定的对象是否为非空;如果它为 空引用(在 Visual Basic 中为 Nothing),则测试失败。

    Step 3.运行用例

使用Test--Windows--Test View来查看你的测试用例,无误后,运行用例。

a. 用例执行成功

b. 如果用例执行未通过

最后一行会有未通过的代码行。

c. 执行通过后双击任一Item,显示明细,包含持续时间等信息。

d..Net FrameWork 4.0 并行计算

 

代码
Parallel.ForEach(result, efut =>            {                string strB = efut.ContentValue;                string expected = strB + "TestStrB";                string actual;                actual = target.TestStrB(strB);                Assert.AreEqual(expected, actual);            }

 

 

  运行结果: 

  值得一提的是,使用.Net FrameWork 4.0 新特性中的并行计算进行并行测试,上图中的用例执行时间,可由10秒缩短为3秒。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!