1.基础概念
1.1单元测试
单元测试:针对程序的某个单元模块进行的测试 (某个方法、某个类型、某个逻辑单元、某个逻辑块)
notes:
(1). 单元测试在单元模块完成后进行,而测试用例却往往在单元模块完成之前就被确定下来
(2). TDD(测试驱动开发): 需求确定下来之后,开始编写测试用例。后续的编辑工作逐渐使得测试
用例全部通过后,开发工作随即完成,单元测试也随之结束,模块可立即交付。
单元测试优点:
1. 验证模块功能:每一项功能靠测试保证其正确性
2. 优化了系统设计:程序易于调试和可测试,解除了软件中的耦合
3. 另一种文档方式:展示函数/类如何使用的最佳文档
4. 具有回归性:编写完成可快速测试
2.TDD开发方式的流程
2.1测试驱动开发的基本过程
(1).明确当前要完成的功能,可以记录成一个功能列表
(2).快速编写针对此功能的测试用例
(3).测试代码编译不通过
(4).编写对应的功能代码
(5).测试通过
(6).对代码进行重构,并保证测试通过
(7).循环完成所有功能的开发
2.2 TDD的具体实例
需求:接受一字符串,并且对其进行翻转(可利用StringReverse类型实现此功能)
设计:定义一个名为StringHandler的类型代表此动作,其包含一个字符串内部成员和公开一个公共方法
Reverse实现翻转,该方法返回一个字符串类型的对象来存储翻转的结果。
测试用例:
//一个测试方法 [Test] public void TestStringRevertNormal() { String input="abcde"; StringHandler handler=new StringHandler(input); String result=handler.Reverse(); //测试两个变量是否相等 Assert.AreEqual("edcba",result); Assert.AreEqual("edcba",result); }
分析: 上面的用例测试了类型的常规功能:翻转字符串。
测试用例连续两次调用了同一个测试方法,目的是确保重复调用方法不会影响到同一个模块的功能。
写完了正常流程的测试用例,就需要做边界测试了。
1).当传入的参数是null时, 期望该类型抛出一个ArgumentException类型的异常:
////// 空引用测试用例,希望抛出一个ArgumentException异常 /// [Test, ExpectedException(typeof(ArgumentException))] public void TestStringRevertNullArgument() { String input=null; //希望在构造方法中就抛出异常 StringHandler handler=new StringHandler(input); }
2).当传入的参数是空字符时,期望的结果也是返回一个空字符串
////// 空字符串测试用例 /// [Test] public void TestStringRevertEmptyArgument() { String input = String.Empty; StringHandler handler=new StringHandler(input); String result=handler.Reverse(); Assert.AreEqual(String.Empty,result); }
这样就大致已经写完了覆盖所有功能和边界的测试用例了,接下来就可以编写程序的架构来使得所有这些用例能够进行编译。 这里只编写架构,而不进行任何功能实现的编码。
////// 类型的框架,不包含具体功能的实现 /// class StringHandler { public StringHandler(String input) { //需要被填充 } public String Reverse() { //需要被修改 return String.Enpty; } }