本文分别在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秒。
来源:https://www.cnblogs.com/isline/archive/2010/05/05/test2.html