65.9K
CodeProject 正在变化。 阅读更多。
Home

测试运行器应用程序

1999年12月4日

viewsIcon

108468

downloadIcon

1673

用于执行单元测试的框架。

Sample Image

什么是 Test Runner?

Test Runner 是一款应用程序,它提供了一个用于执行单元测试的框架。Test Runner 允许任何实现了 ITest 接口并且属于 CATID_Test 组件类别(称为测试项)的 COM 组件,成为自动化测试套件的一部分。测试套件是一组测试项和其他测试套件,它们作为一个整体进行测试。

必备组件

  • Microsoft Visual C++ 6.0
  • Internet Explorer 5.0 (用于 msxml.dll)

为什么使用 Test Runner?

单元测试是开发过程中非常重要的一部分,应该易于执行。Test Runner 提供了一个易于使用的图形用户界面,使得创建和执行测试套件更加方便和灵活。

如何使用 Test Runner?

Test Runner 提供了一个易于使用的界面来执行单元测试,这些测试可以组织成一个或多个测试套件。一个测试套件可以包含一个或多个测试套件或测试项。在 Test Runner 中定义的每组测试都可以保存到文件中以供将来使用。

应用程序的用户界面分为三个视图或窗格。用户界面的左侧是“测试视图”,其中包含所有支持 ITest 接口的 COM 对象列表。右上方的视图是“测试套件视图”。该视图包含一个树状结构,其中包含所有测试套件和测试的层次结构。右下方的视图是“结果视图”。该视图包含在“测试套件视图”中显示的测试套件或测试的运行结果。

通过使用“文件/打开”菜单项打开现有文件来选择要运行的测试。打开测试文件后,“测试套件视图”将更新以显示测试套件和测试的层次结构。每个测试套件或测试节点左侧的小勾号表示是否将运行该测试套件或测试。可以通过用鼠标单击复选框或选择节点然后按空格键来切换勾号。未“选择”(即没有勾号)的测试套件或测试将不会执行。

测试运行程序文件的默认扩展名为 '.suite'。测试文件保存为扩展标记语言 (XML)。示例文件如下所示。

    <?xml:stylesheet type='text/xsl' href=
    'TestRunner.xsl'?>
        <TESTSUITES>
            <TESTSUITE> <NAME>Smoke
            Test</NAME>
            <RUNCOUNT>1</RUNCOUNT>
            <SELECTED>1</SELECTED>
                <TEST>
                <NAME>TestComponent1</NAME>
                <SELECTED>1</SELECTED>
            <CLSID>{EC86425F-8321-11D3-ABF8-00508B0D0D6E}</CLSID>
            </TEST>
                <TEST>
                <RUNCOUNT>1</RUNCOUNT><SELECTED>1</SELECTED>
                <CLSID>{EC864261-8321-11D3-ABF8-00508B0D0D6E}</CLSID>
            </TEST>
        </TESTSUITE>
    </TESTSUITES>

创建示例测试套件

  1. 启动 Test Runner。
  2. 通过单击右上方的窗格中的鼠标来选择“测试套件视图”。
  3. 选择“文件/新建套件”菜单项(或按 INS)来创建新套件。应该会出现一个名为“新套件”的新测试套件。
  4. 通过选择“新套件”节点,然后按鼠标右键并选择“重命名”菜单项来为测试套件指定一个新名称(例如,“我的测试”)。也可以通过双击节点并在“编辑测试套件”对话框中更改名称来修改名称。
  5. 通过双击新测试套件节点将“运行次数”从 0 修改为 1。将“运行次数”的值从 0 更改为 1。
  6. 将“测试视图”窗格中的一个测试拖到您刚创建的测试套件中。双击该测试,并将“运行次数”的值从 0 更改为 10。
  7. 通过选择“文件/保存”菜单项来保存测试信息。

运行测试套件

  • 启动 Test Runner。
  • 选择“文件/打开”菜单项以打开测试文件。
  • 在“测试套件视图”中选择一个测试套件。
  • 选择“文件/运行测试(s)”菜单项来执行测试套件。将运行选定节点或其下方的所有测试。在未选定的节点(缺少勾号)下方将不运行任何测试。
  • 测试套件的结果将出现在“结果视图”窗口中。

测试套件视图键盘帮助

  • INS - 创建一个新的测试套件节点。
  • DEL - 删除选定的测试套件或测试节点。
  • 加号 (+) - 增加测试套件或测试运行次数。
  • 减号 (+) - 减少测试套件或测试运行次数。
  • 空格键 - 切换选定测试套件或测试节点的勾号。

《ITest 指南》

引言

ITest?什么是 ITest?嗯,好问题,ITest 是 Test Runner 要求所有测试项实现的接口。Test Runner 使用此接口来测试一个或多个对象,对象被宽泛地定义为任何可执行文件。

测试项(组件)

测试项是任何实现了 ITest 接口并在 CATID_Test 下的组件类别中注册的 COM 组件。CATID_Test 是 GUID {50105161-8295-11d3-ABF6-00508B0D0D6E} 的英文别名,定义在 CTestSuiteItemCollection.cpp 中。

测试项具有以下要求
  • 必须是 COM 组件。
  • 实现 ITest 接口。
  • 使用 ITestOutput 来开始和停止测试计时。
测试项具有以下**可选**要求
  • 使用 ITestOutput::LogResult 记录中间结果。
  • 使用 PropertyTester 对 COM 组件的属性进行自动化测试。(要测试的接口必须实现 IDispatch 接口。)

通过使用组件执行测试,Test Runner 应用程序能够对一组(套件)测试项执行测试,而无需了解这些测试项在测试什么。测试项可以是冒烟测试、黑盒测试或白盒测试。这为生成测试套件提供了极大的灵活性。

ITest 接口

ITest 接口为测试运行程序应用程序提供了一个已知的接口,用于与测试组件通信。因此,任何实现 ITest 接口的组件都可以由测试运行程序应用程序执行。

设置和清理方法

  • HRESULT StartUp([in] ITestOutput* pTestOutput);
  • HRESULT ShutDown([in] ITestOutput* pTestOutput);

这两个方法用于执行测试的初始化和清理。如果一个测试要运行多次,则可能不需要为每个测试进行初始化,而只需为所有测试进行一次初始化。

测试方法

  • HRESULT Run([in] ITestOutput* pTestOutput, [in] VARIANT runParameter);

ITest::Run() 方法是执行测试的地方。在此方法中,将实例化和测试要测试的“对象”。

ITest::Run 的第一个参数是指向 ITestOutput 的指针。ITestOutput 用于将结果记录到文件和 UI。ITest::Run 的第二个参数是 VARIANT。目前未使用,但目的是允许我们使用不同的参数执行相同的测试。

以下是如何定义 ITest::Run 方法的示例

ITest::Run() 示例

STDMETHODIMP CTestComponent1::Run(ITestOutput* 
                  pTestOutput, VARIANT runParameter)
{
   ATLASSERT(pTestOutput != NULL);
   ATLASSERT(!::IsBadReadPtr(pTestOutput, sizeof(ITestOutput*))); 

   // Without a test output there is no way to log the results so, 
   // no reason to conduct the test. 
   if(pTestOutput)
   { 
      // Test a non-COM object, in this case we use a c++ class. 

      // Create a c++ object to be tested.
      Cfoo foo;
      pTestOutput->LogStartTime();
      pTestOutput->LogResult(CComBSTR(L"Tesing CFoo"), S_OK);
      HRESULT hr = S_OK; 

      hr = foo.CheckValue(5); 
      // The actions taken here are the responsibility of the
      // test component writer. 
      if(FAILED(hr)) 
      { 
         // The hr indicates that an error occurred. 
         // Passing in S_OK indicates success. 
         pTestOutput->LogResult(_bstr_t(L"This is a failure"), hr); 
      }
      // Stop the test time clock 
      pTestOutput->LogStopTime();

      //
      // Test a COM object, in this case we use ITestSuiteItem
      //

      // Create a COM component to be tested
      CComPtr<ITESTSUITEITEM> pItem;
      HRESULT hr = pItem.CoCreateInstance(L"TestCore.CTestSuiteItem.1"); 
      if(FAILED(hr)) 
      { 
         pTestOutput->LogResult(L"Creating the ITestSuiteItem failed", hr);
         return hr; 
      } 

      // Start the test time
      pTestOutput->LogStartTime(); 
      pTestOutput->LogResult(CComBSTR(L"Testing ITestSuiteItem"), S_OK); 
      // This how to log a failure.
      pTestOutput->LogResult(_bstr_t(L"This is a failure"), E_FAIL);

      // ITestSuiteItem is an IDispatch interface
      // so perform and automated test of
      // it's properties.
      CPropertyTester ta;
      ta.TestProperties(pTestOutput, static_cast<IDISPATCH*>(pItem)); 
      // Stop the test and log
      it.pTestOutput->LogStopTime();

      // When the test is in a tight loop, be friendly
      // to scripting and sleep once in awhile.
      //::Sleep(1);      
   }
   
   return(S_OK);
}

RGS?我们需要个该死的 RGS 吗?

Test Runner 必须知道哪些组件支持 ITest 接口。这是通过使用组件类别来实现的。组件类别(参见《Essential COM》第 3 章,第 147 页)是 Windows 注册表中的一个位置,支持特定接口或接口集的组件可以作为一组进行注册。

示例

如果有一个名为 ISpellCheck 的接口,则所有拼写检查组件都会在 CLSID_SpellCheck 类别下注册,任何知道如何使用 ISpellCheck 接口的应用程序都可以从此类别中选择一个组件来执行拼写检查。注册是通过更新 .rgs 文件来完成的。以下是更新的 rgs 文件的示例。

HKCR
{
    Test1.TestComponent1.1 = s 'TestComponent1 Class'
    {
        CLSID = s '{EC86425F-8321-11D3-ABF8-00508B0D0D6E}'
    }
    Test1.TestComponent1 = s 'TestComponent1 Class'
    {
        CLSID = s '{EC86425F-8321-11D3-ABF8-00508B0D0D6E}'
        CurVer = s 'Test1.TestComponent1.1'
    }
    NoRemove CLSID
    {
        ForceRemove {EC86425F-8321-11D3-ABF8-00508B0D0D6E} = 
                                    s 'TestComponent1 Class'
        {
            ProgID = s 'Test1.TestComponent1.1'
            VersionIndependentProgID = s 'Test1.TestComponent1'
            ForceRemove 'Programmable'
            'Implemented Categories' = s ''
            {
                {50105161-8295-11d3-ABF6-00508B0D0D6E} = 
                              s 'Automated Test (ITest)'
            }
            InprocServer32 = s '%MODULE%'
            {
                val ThreadingModel = s 'Apartment'
            }
            'TypeLib' = s '{EC864250-8321-11D3-ABF8-00508B0D0D6E}'
            'Test Information' = s ''
            {
                val TestName = s 'TestComponent1'
                val Description = s 'Automated Test for TestComponent1'
            }
        }
    }
    NoRemove 'Component Categories'
    {           
       NoRemove {50105161-8295-11d3-ABF6-00508B0D0D6E} 
       {
          val 409 = s 'Automated Test (ITest)'
       }
    }
}

分步指南

以下步骤用于创建支持 ITest 接口的对象...

必备组件

  1. 必须在计算机上安装 IE 5.0。这是为了支持 msxml.dll(XML 支持)。
  2. 创建一个新的 ATL 对象用作测试组件。
  3. 右键单击类并选择“实现接口”。
  4. 这将弹出“实现接口”对话框。按“添加类型库”按钮。
  5. 通过选中复选框从此列表中选择 TestCore。
  6. 选中 ITest 旁边的复选框,然后按“确定”按钮。
  7. 现在可以向 Run() 添加自定义功能了。
  8. 下面的 rgs 示例显示了需要进行更改的位置
    • 在由“--->”指示的区域进行修改
    • CATID_GUID = {50105161-8295-11d3-ABF6-00508B0D0D6E}
        NoRemove CLSID
        {
            ForceRemove {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn} = s 'xxx'
            {
                ProgID = s 'xxx'
                VersionIndependentProgID = s 'xxx'
                ForceRemove 'Programmable'
    --->        'Implemented Categories' = s ''
    --->        {
    --->            {50105161-8295-11d3-ABF6-00508B0D0D6E} = 
                                     s 'Automated Test (ITest)'
    --->        }
                InprocServer32 = s '%MODULE%'
                {
                    val ThreadingModel = s 'Apartment'
                }
                'TypeLib' = s '{EC864250-8321-11D3-ABF8-00508B0D0D6E}'
    --->        'Test Information' = s ''
    --->        {
    --->            val TestName = s 'A test name'
    --->            val Description =   s
    'A        description'
            --->
        }
    }} --->NoRemove 'Component
    Categories'--->{           
    --->    NoRemove {50105161-8295-11d3-ABF6-00508B0D0D6E}
    --->    {
    --->        val 409 =  s 'Automated Test
    (ITest)'    --->
    }--->}

注释

  1. 409 是英语的 LCID。
  2. 自动化测试 GUID 是 {50105161-8295-11d3-ABF6-00508B0D0D6E}。
© . All rights reserved.