Forum Discussion

kirk_bottomley's avatar
kirk_bottomley
Contributor
10 years ago

Assigning Variable Values to Remote Machines

Our test structure is one authoring machine writing tests using TestComplete, and TestExecute licenses on the machines that will run the tests. Each machine can install the software to any AppPath, and each machine runs the tests in their own sandbox. Consequently, I need to be able to set the variables for each machine.

I know a better solution is to use XML or some file that lists the variable values for each machine and read those in, but until that framework is implemented, I've been trying to do it this way: 

 

In the Project.Variables collection, there is AppPath, Sandbox, SQLServer, etc. Our machines are named like ABCDE-1234. You can't use dashes in variables, so I just strip those out. So I also have AppPath_ABCDE1234, AppPath_FGHIJ5678, etc. 

I have an initialize routine that passes in a variable name, like Sandbox. It then appends _ and hostname to variable name, and uses VariableByName to assign the value. Ideally, this should just need to be run once when a machine connects for the first time, but it's quick enough I just have the routine run at the beginning of our test suite, and just use Project.Variables.Sandbox, for instance, in the tests from then on.

 

Sorry for the length of this question, but the problem is that the strategy works fine on the authoring machine, but when a remote machine using TestExecute runs the routine, the values are not assigned. I'll post the code below, can anyone tell me why this isn't working?

 

function AssignVariables(VarName)
{
var MachineName = aqString.Replace(Sys.HostName, "-", "");
var ConcVar = VarName + "_" + MachineName;
if (Project.Variables.VariableByName(VarName)= Project.Variables.VariableByName(ConcVar))
  {
    Log.Message(Project.Variables.VariableByName(VarName) + " now equals " + Project.Variables.VariableByName(VarName + "_" + MachineName) )
  }
else
  {
    Log.Message(VarName + " not assigned.")
  }
}

As I said, when run on the authoring machine, it works fine. When run with TestExecute, it always returns back with VarName not assigned. 

  • I figured out a solution.

     

    You can't assign the value of a persistent variable to a persistent variable, it seems. But you can assign a temporary variable to one.

     

    So simply...

     

    function AssignVariables(VarName)
    {
    var MachineName = VarName + "_" + aqString.Replace(Sys.HostName, "-", "");
    Project.Variables.VariableByName(VarName) = Project.Variables.VariableByName(MachineName);
    }

    ...allows me to populate the Temporary Variables section with Variable_Machine-0123, call the routine as needed, and pass in the variable name to be assigned. Then I can just continue using the original variable in the rest of the tests and scripts.

     

    I know the better way would be to maintain a database or XML file with the machine names and their needed values, but until that is implemented, this will work.

    Thank you everyone who responded trying to help. Much appreciated.

  • Hi,

    I believe the culprit is the "If" statement.

    It has 2 problems.

    1. you have used "=" operator instead of "==". Is this by accident??

    2. Use a aqString.Compare instead.

     

    please post the updates. thank you,

     

     

    • chrisb's avatar
      chrisb
      Regular Contributor

      Use triple equals to avoid type coercion. Also, you say it runs fine on one machine but not remote machines. Did you put a breakpoint in your script and check the values of the variables to compare and see what you are getting?

       

      What happens when the script fails on the remote machines, do you get the log message in your else statement?

       

      I am also wondering if your Sys.HostName is what you expect on the remote machines?

       

       

      function assignVariables(varName)
      {
      var machineName = aqString.Replace(Sys.HostName, "-", "");
      var concVar = varName + "_" + machineName;
      if (Project.Variables.VariableByName(varName)=== concVar){
          Log.Message(Project.Variables.VariableByName(varNa​me) + " now equals " + Project.Variables.VariableByName(varName + "_" + machineName) )
        }else
        { Log.Message(VarName + " not assigned.")
        }
      }

    • chrisb's avatar
      chrisb
      Regular Contributor

      Use triple equals to avoid type coercion.

      • chrisb's avatar
        chrisb
        Regular Contributor

        I am wondering if you have the project variable concVar saved to the variables object on your 'authoring' machine and it does not exist on the remote machine where you have the issue. Why not just compare varName against the conVar variable whose value you just create on the fly?...

         

        function assignVariables(varName)
        {
        var machineName = aqString.Replace(Sys.HostName, "-", "");
        var concVar = varName + "_" + machineName;
        if (Project.Variables.VariableByName(varName) === conVar)
          { Log.Message(Project.Variables.VariableByName(varNa​me) + " now equals " + Project.Variables.VariableByName(varName + "_" + machineName) )
          }else{
            Log.Message(varName + " not assigned.")
          }
        }

    • kirk_bottomley's avatar
      kirk_bottomley
      Contributor

      "you have used "=" operator instead of "==". Is this by accident??"

       

      Not an accident, that's on purpose. Most operations return a 1 if they're successful, so writing it that way allows an error catch. It performs the operation as desired, and if true logs a success, but if false logs a failure.

       

      Thanks for the feedback! 

       

  • chrisb's avatar
    chrisb
    Regular Contributor

    Run Test Complete on your remote machine and put some breakpoints in your test and verify that your two project variables exist when running the test on your remote machine. If you cant run TC on the rmeote machine then add some logging to write the two project variables in your test to the test logs to verify they actually exists. Perhaps you created them on your 'authoring' machine and they dont exist on the remote.

    • chrisb's avatar
      chrisb
      Regular Contributor

      Put some logging in your test to write the machine name and VarName to your test log to see what they are when test execute runs it.Perhaps also do the same for your project variables.
      Also, I think you could simplify the way you do your logging message in the if statement. You've already verified that it matches the project variable so just write the project variable to the log rather than build the string again.


      function AssignVariables(VarName)
      {
      var MachineName = aqString.Replace(Sys.HostName, "-", "");
      Log.message(MachineName);

      var ConcVar = VarName + "_" + MachineName;
      Log.message(ConcVar);

      if (Project.Variables.VariableByName(VarName) === Project.Variables.VariableByName(ConcVar))
      {
      Log.Message(Project.Variables.VariableByName(VarName) + " now equals " + Project.Variables.VariableByName(ConcVar) )
      }
      else
      {
      Log.Message(VarName + " not assigned.")
      }
      }

      • kirk_bottomley's avatar
        kirk_bottomley
        Contributor

        "Put some logging in your test to write the machine name and VarName"

         

        Thanks for the suggestion!

         

        "Also, I think you could simplify the way you do your logging message in the if statement."

         

        I had considered that, but thought that by rebuilding the string again, I could also verify that it was building the string correctly and eliminate that as a factor. 

    • kirk_bottomley's avatar
      kirk_bottomley
      Contributor

      "Run Test Complete on your remote machine"

       

      I wish I could, that would solve the issue altogether. I could run the automation once on each new machine that will run the tests and use the GUI to assign the local values of the needed variables.

      Unfortunately, we only have the one node-locked license for TC and several licenses for TE for the remote machines, so I have to work out "creative methods" for getting the local values for the project variables right.

      • chrisb's avatar
        chrisb
        Regular Contributor

        Just write all your variables to the test log during the test run and then check the logs. I suspect one of the variables is your problem and it will be obvious when you check the logs. As for triple equals I was suggesting using that in your 'if' statement to avoid type coercion. Something that has certainly caused me an issue at least once.

  • I figured out a solution.

     

    You can't assign the value of a persistent variable to a persistent variable, it seems. But you can assign a temporary variable to one.

     

    So simply...

     

    function AssignVariables(VarName)
    {
    var MachineName = VarName + "_" + aqString.Replace(Sys.HostName, "-", "");
    Project.Variables.VariableByName(VarName) = Project.Variables.VariableByName(MachineName);
    }

    ...allows me to populate the Temporary Variables section with Variable_Machine-0123, call the routine as needed, and pass in the variable name to be assigned. Then I can just continue using the original variable in the rest of the tests and scripts.

     

    I know the better way would be to maintain a database or XML file with the machine names and their needed values, but until that is implemented, this will work.

    Thank you everyone who responded trying to help. Much appreciated.

    • joseph_michaud's avatar
      joseph_michaud
      Moderator

      > You can't assign the value of a persistent variable to a persistent variable, it seems. But you can assign a temporary variable to one.

       

      Huh?  I don't think so.  You can easily verify that you can assign the value of a persistent variable to a persistent variable.  I think it is more likely that the variable named by ConcVar contains the empty string.  Assignment of an empty string evaluates to 'false' so the following:

       

      if (Project.Variables.VariableByName(VarName)= Project.Variables.VariableByName(ConcVar))
        {
          ...
        }
      else
        {
          Log.Message(VarName + " not assigned.")
        }
      }

       

      assigns the empty string to the variable named by VarName, and then falls to the else clause.

       

      • kirk_bottomley's avatar
        kirk_bottomley
        Contributor

        "You can easily verify that you can assign the value of a persistent variable to a persistent variable.  I think it is more likely that the variable named by ConcVar contains the empty string.  Assignment of an empty string evaluates to 'false'."

         

        When I ran it on the TC machine, it worked as intended. When I ran it on the TE machine, it would fail.

         

        In trying all kinds of different ways to do it, this way was the only way that actually worked. It might be unique to my setup here, but the authoring machine usually seems to work different than my TE test machine. When I tried assigning persistent to persistent, it would work on TC, but never on the remote. 

        In checking this again, it appears that I am mistaken on the difference between the persistent and temporary. I believe what I was doing wrong was trying to alter default values and getting sidetracked by several test functions I was writing trying to solve the issue. 

        The code I posted first still seems to work on the TC machine, and I just verified that it still doesn't work on the remote. However, the second function I posted works on both, and works on all variables. It is still advantageous, in this schema, to keep the individual machine's values in temporary and the "root" variables in persistent, though. I can see them easier, and only see the one value that would need to be altered. Ultimately, the best solution would be to strip the individual machine values out of the project variables altogether, but that's for another day.