自动化单元测试的意义

系统 1405 0

出处

作者:许式伟
写于:2005年3月
背景: WPS Office 2005 (开发代号: V6)
原文: why-unit-test.pdf (pdf格式)

目录

  • 自动化单元测试的重要特征
  • 单元测试的项目意义
  • 单元测试对设计的意义
  • cppunit for v6
  • 将测试案例写在dll中

常规测试的缺陷

  • 一般是基于手工的,不具备可回归性。因此测试的效率不高。
  • 由于缺乏效率,往往导致测试仅仅针对典型数据,覆盖面往往也很低。

自动化单元测试的重要特征

  • 自动化、可回归性
  • Quiet
  • 案例的执行安全受控

自动化、可回归性

  • 测试的结果是程序直接检测的,而不是 “通过人眼对屏幕上的输出结果的观测”
    • 测试的输入数据和预测结果直接在案例中, 除非结果非预期,否则不需要任何输出
    • 因此,并不推荐屏幕输出,或者写可视化的测试单元。
    • 案例的执行不需要人工干预,可随时回放。
    • 因此,我们可以通过大量典型测试数据进行回归,以确保系统的可靠性。
  • 对比:常规测试典型过程
    • 在屏幕上提示输入数据,然后打印结果,通过查看屏幕显示的结果,确认我们的系统是否存在问题。

Quiet

  • 绝对避免在案例执行过程中弹出对话框或者进行其他UI交互。
  • (调试模式下例外)

案例的执行安全受控

  • 某个测试案例执行的失败(甚至出现了异常),不会导致测试环境的崩溃,也不影响另一个案例的执行结果。

常规测试样例

          
            void
          
          
          
          
            main
          
          
            ()
          
          
            
{
int n ;
for ( ;; )
{
std :: cout << " input n(0 to exit): " ;
std :: cin >> n ;
if ( n == 0 )
break ;
std :: cout << " n! = " << fact ( n ) << std :: endl ;
}
}

cppunit测试案例

          
            class
          
          
          
          
            TestFact
          
          
             : 
          
          
            public
          
          
          
          
            TestCase
          
          
            
{
public :
CPPUNIT_TEST_SUITE ( TestFact ) ;
CPPUNIT_TEST ( test ) ;
CPPUNIT_TEST_SUITE_END () ;

void test ()
{
CPPUNIT_ASSERT ( fact ( 3 ) == 6 ) ;
CPPUNIT_ASSERT ( fact ( 4 ) == 24 ) ;
CPPUNIT_ASSERT ( fact ( 5 ) == 120 ) ;
}
} ;

CPPUNIT_TEST_SUITE_REGISTRATION ( TestFact ) ;

单元测试的项目意义

  • 模块更加可控。
  • 及早发现问题,提高模块质量,降低系统测试成本。
  • 加速开发周期。

单元测试与项目控制

  • 单元测试不应该是程序员的个人行为,而与项目进度控制、质量控制息息相关。
    • 通过监测单元测试的情况,来量化模块开发的进度与质量。
  • 要改善项目的控制,必须“做好单元测试”。
    • 不止是要让单元测试成为每个程序员的例行公事,而且要让它变得规范、变得受控。

单元测试的误区

  • 一个很常见误解是:嗯,单元测试,好事啊,只是最近时间很紧,下回做吧。
  • 实际上 单元测试大家都会去做 ,我们提倡单元测试,更大程度上是要达到:
    • 规范单元测试的编写(手段);
    • 最大程度保留下来我们的测试案例;

加速开发周期

  • 一个系统自动化程度越高,则运营成本越低。
    • 单元(模块)是最容易,也是最应该采用自动化测试的。而集成测试、系统测试虽然也有自动化的方法和支持工具,但需要更高额的代价。
  • 单元测试 将问题的发现周期缩短,降低bug修复成本。
    • 如果问题在集成测试、系统测试期被发现,那么同样一个问题需要花几倍甚至几十倍的时间进行定位、修复。
  • 单元测试降低了集成测试、系统测试的压力和投入成本。

单元测试的主要检查点

  • 案例的覆盖度
  • Bug量与Bug反复情况
  • 案例文档的规范

单元测试对设计的意义

  • 设计应该以可测试性为第一目标。
  • 及时发现模块构架调整引发的潜在Bug。

模块的可测试性

  • 可测试性 = 低耦合
    • 环境模拟(依赖的模块、数据输入)
    • 模块设计应该首先保证可测试性。
    • 坚持进行单元测试可提高设计能力。
  • 一个模块可以很方便地进行测试,那么就可以说它是一个设计优良的模块。

发现模块构架调整的潜在Bug

  • 通常 模块在架构调整期(代码重构)最容易引入Bug。
  • 只有在模块开发中就不断积累经典数据、以案例的形式固化已知Bug,才可能在架构调整等最容易引发问题的情形下获得最佳效果。

cppunit for v6

  • 引入调试模式
  • 通用的调试开关
  • 有选择的运行测试案例
  • 独特的dll测试模式

调试模式

  • 同一套测试代码,两种工作模式。
    • cppunit提供了安全可控的自动化测试平台。
    • 但是是代码总会有bug。为了让测试案例可调试,v6在开源的cppunit基础上,结合kfc的调试策略,引入调试模式。

通用的调试开关

  • /ndebug
    • 进入自动化测试模式。默认为调试模式。
  • /output:<xmlfile>
    • 输出结果到xml文件。注意:/output:后不能有空格。
    • 默认输出到控制台。
  • /run:<testclass>[.<testmethod>]
    • 执行<testclass>类所有案例,或者执行<testclass>的<testmethod>案例。

有选择的运行测试案例

  • 你可以只执行某个TestCase类,或者只是执行某个TestCase中的某个method。
  • 演示rununit程序的参数含义:

<testclass> <testmethod>

  • 演示通用开关:

/run:<testclass>[.<testmethod>]

将测试案例写在dll中

  • 测试案例同步更新
  • 测试dll内部组件
  • 关于rununit工具

基于dll的单元测试

  • 对比
    • 为dll写测试程序(exe方式)
  • 优点
    • 方便测试案例的同步更新
      • 并且强迫你同步更新测试案例
    • 可测试dll的内部组件
    • 去除了建立新工程的过程(有点麻烦)。

关于rununit工具

  • 用rununit调试你的dll
    • rununit程序是一个通用的testcaseRunner,可用于执行(或调试)一个dll中的部分或全部案例。
  • 命令行

rununit testcase[.dll] [testclass] [testmethod] [/ndebug] [/pause] [/output:<xmlfile>]

Visual Studio中调试dll

今天,你“单元测试”了吗?

  • 如果你没有,那么我告诉你,你已经落伍啦!

附录

  • rununit.exe: 参考ksdn中关于该程序的详细说明。
  • CreateCppUnitTestCase宏: 参考KSRule.dsm(macros for Visual Studio)。

自动化单元测试的意义


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论