C++ (Unmanaged) Microsoft Visual Studio 2005

  1. Start Microsoft Visual Studio 2005 and select Create Project from the start page or File->New->Project.
  2. Select Visual C++ ATL project, enter a project name and click OK. Screen Shot 1
  3. Click Finish.
    Screen Shot 2
  4. Right click on the project and select Add->Class.
  5. Select ATL->ATL Simple Object and press Add.
    Screen Shot 3
  6. Enter a short name for your tester creator object and press next.
    Screen Shot 4
  7. Select Free Threading Model and press finish.
    Screen Shot 5
  8. In the class view right click on your tester creator object and select Add->Implement Interface.
  9. Select TestScriptRunner 4.0 Type Library<4.0> in the Available type libraries, add ITesterCreator and ITesterCreator1 interfaces to your class via the > button and press finish.
    Screen Shot 6
  10. In the project solution explorer right click on the project and select Add->Existing Item and add Tester.h and Tester.cpp from the Test Script Runner install directory (usually C:\Program Files\Ideal Systems Consultancy Ltd\Test Script Runner).
  11. Right click on the project and select properties, All Configurations C/C++ Configuration Properties, add the Test Script Runner install directory to the Additional Include Directories box and click OK.
    Screen Shot 7
  12. In the project class view right click on the project, select Add->Class then C++ Class and press Add.
    Screen Shot 8
  13. Enter the name of your tester object and enter Tester as the base class then press finish.
    Screen Shot 9
  14. Open the tester object header file and add the code below before the class definition replacing DemoTester with the name of your tester class:-
         class DemoTester;
         typedef CComObject<DemoTester>
         CComObjectDemoTester;
        
  15. Also within the class add the methods below:-
         virtual Result execute(ULONG ActionId,ULONG numberOfParameters, VARIANT *parameters);
         virtual bool open(ULONG numberOfParameters, VARIANT *parameters);
         virtual bool close();
        
  16. Also add an enumeration to the header containing an entry for each action you intend to provide. In this case this enumeration will be:-
         enum ActionId
         {
             ePass,
             eFail,
             eRandom,
             eRandomValue
         };
        
  17. Open the tester object source file and add Tester(“<your tester object type>”,"<Version>") to the constructor. In this case this will be Tester(“demo”,"2.0")
  18. Inside the braces of the constructor you need to add calls to addAction for each of the actions you intend to implement. The addAction method has the signature:-
         void addAction(unsigned ActionId,
                        const char *actionType,
                        const char *description,
                        ...);
        
    The ActionId is one of your enumeration values, actionType is the name of the action to be used in the script, description is a free format text describing what the action does and the variable parameter list is a the list of parameters and return values for the action each list separated by a 0. In this case these calls are as follows:-
             addAction(ePass,                  //Action Id
                       "Pass",                 //Action name
                       "Return TestPassed",    //Action Description
                       0,                      //End of action parameters
                       0);                     //End of action return values                  
             addAction(eFail,                  //Action Id
                       "Fail".                 //Action name
                       "Return TestFailed",    //Action Description
                       0,                      //End of action parameters
                       0);                     //End of action return values
             addAction(eRandom,                //Action Id
                       "Random",               //Action name
                       "Random Passed/Failed", //Action Description
                       "int value=2",          //int parameter with a default value of 2
                       0,                      //End of action parameters
                       0);                     //End of action return values
             addAction(eRandomValue,           //Action Id
                       "RandomValue",          //Action name
                       "Return a random value",//Action Description
                       "int value=2",          //int parameter with a default value of 2
                       0,                      //End of action parameters
                       "int rndval",           //int return value
                       0);                     //End of action return values
        
  19. Add implementations for the open and close functions. The open function is called after the object is created and is supplied with the parameters from new command within the script. The close function is called when the object is deleted in the script. In this case there is nothing to do and we could have decided not to overload these but there were included in case you do need to implement them. Each function should return true if successful false otherwise.
          bool DemoTester::open(ULONG numberOfParameters, VARIANT *parameters)
          {
              return true;
          }
          bool DemoTester::close()
          {
              return true;
          }
        
  20. Next add the implementation of the execute function. This function actually performs the actions in a big switch statement. Here is the implementation for the demo tester:-
          Result DemoTester::execute(ULONG ActionId, ULONG numberOfParameters, VARIANT *parameters)
          {
              switch(ActionId)
              {
                  case ePass:
                      return TestPassed;
                  case eFail:
                      return TestFailed;
                  case eRandom:
                  {
                      int val = 2; // Default to 2 as per addAction documentation
                      if ((numberOfParameters == 1) && 
                          (parameters[0].vt == VT_I4))
                      {
                          val = parameters[0].intVal;
                      }
                      if (val > 0)
                      {
                          return ((rand() % val) == 0) ? TestFailed : TestPassed;
                      }
                      break;
                  }
                  case eRandomValue:
                  {
                      int val = 2; // Default to 2 as per addAction documentation
                      if ((numberOfParameters == 1) &&
                          (parameters[0].vt == VT_I4))
                      {
                          val = parameters[0].intVal;
                      }
                      if (val > 0)
                      {
                          value(rand() % val);
                          return TestPassed;
                      }
                      break;
                  }
              }
              return TestError;
          }
        
  21. In your tester creator header and implement the three functions create, get_NumberOfTypes and get_Version. Below is the demo implementation for these. Please note you can create multiple tester types from creator object and you need to add a #include statement to each tester object.

          STDMETHOD(create)(unsigned long TesterNumber, ITester * * tester)
          {
              if (0 != tester)
              {
                  if (TesterNumber == 0)
                  {
                      CComObjectDemoTester *temp;
                      CComObjectDemoTester::CreateInstance(&temp);
                      temp->AddRef();
                      *tester = temp;
                      return S_OK;
                  }
                  return E_INVALIDARG;
              }
              return E_POINTER;
          }
          
          STDMETHOD(get_NumberOfTypes)(unsigned long * pVal)
          {
              if (0 != pVal)
              {
                  *pVal = 1;
                  return S_OK;
              }
              return E_POINTER;
          }
          
          STDMETHOD(get_Version)(BSTR * pVal)
          {
              if (0 != pVal)
              {
                  *pVal = CComBSTR("2.0").Detach();
                  return S_OK;
              }
              return E_POINTER;
          }
        
  22. In the header locate the line COM_INTERFACE_ENTRY2(IDispatch, ITesterCreator) and add a 1 to the ITesterCreator. This therefore becomes:-
         COM_INTERFACE_ENTRY2(IDispatch,ITesterCreator1).
       
    Also change the line COM_INTERFACE_ENTRY(ITesterCreator) to COM_INTERFACE_ENTRY2(ITesterCreator,ITesterCreator1).
  23. Compile the code and then select the program identifier from the registry file for your tester creator and add this to the system via the Admin->Add Testers command. The program identifier for the demo tester creator is:-
         Demo_C2005.DemoTesterCreator
       
  24. You can now create objects of your tester in your scripts using the commands such as in the script below:-
          d = new Demo()            # Create a demo tester
          i = 0
          while i < 20 do           # loop for 20 iterations
              d.pass()
              d.fail()
              d.random(5)
              r = d.randomValue(10)
              sleep(r)              # sleep length is random 0 - 9
              i++
          endwhile
        

If you wish to add logging information to your tester object you can call the log method at any point. All logging entries from configuration to sever will be displayed in the logger view window and in the log file. If you wish to add debug log entries then use levels finest, finer and fine levels and change the logging level via the Logging->Set Logging Level option.

You can download the demo plug-in at MS2005 C++ Demo Tester.