IF statement resolving non-existing variables

Hello,

During testing I ran across a point where I wanted to improve the terminal command I run.
In this case I’d like to do an IF statement on a variable that used to be passed as --variable in the terminal.
When the --variable doesn’t exist I want a VAR to be set with the scope GLOBAL, otherwise I want the --variable passed through the terminal to be used.

IF not ${CHECK_DATA_EXISTS} VAR ${CHECK_DATA_EXISTS} N scope=GLOBAL ELSE IF ${CHECK_DATA_EXISTS} VAR ${CHECK_DATA_EXISTS} ${CHECK_DATA_EXISTS} scope=GLOBAL ELSE FAIL Not defined if it should be checked if the data exists

However I get this error and I can’t seem to find a way around it:
Invalid IF condition: Evaluating expression 'not ${CHECK_DATA_EXISTS}' failed: Variable '${CHECK_DATA_EXISTS}' not found.

Hello,

Rather than IF not you could use the Variable Should Exist built in keyword. Then catch the failure with a TRY/EXCEPT block or via Run Keyword And Return Status.

1 Like

You might also be able to do it with the &{OPTIONS} automatic variable.

1 Like

So, I feel like this answer has gotten me a step closer to what I want to achieve, thank you for that!

However, right now my TRY/EXCEPT block only works when it includes a variable that does not exist.
I want it to work at both times, so when a variable does exist and when it does not exist.

TRY
        Variable Should Exist    ${VARIABLE}    msg=False
    EXCEPT    False
        VAR    ${VARIABLE}    ${SUITE_VARIABLE}    scope=SUITE
    EXCEPT    PASS
        VAR    ${VARIABLE}    ${VARIABLE}    scope=SUITE
    ELSE
        FAIL    ${MESSAGE}
    END

Is there a way to do that in this TRY/EXCEPT block?
or should I remove the second EXCEPT and replace the variable setting to the ELSE clause?

Thanks in advance!

Hi,

As you set False in the first except, did you try setting true for the second one instead of PASS?

As Variable Should Exist might return a boolean that should work.
Or check exact return status/value of the keyword when it passes. You override the error message with false so first except fit, but the PASS might not be the right syntax.

Regards
Charlie

So, what I’ve done in the meantime was exactly like I said in my second question.
I removed the original ELSE clause, and replaced the second except to the ELSE clause.

This does work as intended.

1 Like

Yes, if the variable exist, then the Variable Should Exist keyword will not fail and no exception is raised. Therefore, it goes to the ELSE block.

Something like that should work

TRY
    Variable Should Exist    ${VARIABLE}    msg=My Custom Error Message
EXCEPT    My Custom Error Message
    VAR    ${VARIABLE}    ${SUITE_VARIABLE}    scope=SUITE
ELSE  # KW did not fail
    VAR    ${VARIABLE}    ${VARIABLE}    scope=SUITE
END
1 Like

Now I did walk into another problem with setting the variables.

As you can see, when I set the VAR when no variable existed in the first place I try to assign it to a suite scope, however this does not work when it comes to a datalist within a .resource file.

I did try to change the VAR scope to global, but even then the logs show me that the moment the datalist is gathered from the resource file an error occurs because it could not find the variable I set in the TRY/EXCEPT clause.

This clause is always run through a keyword that is included in the suite setup, so I expected this variable to be set in each test when they are in the same suite.

Sounds like it should be working…

I do not quite get what you mean by

this does not work when it comes to a datalist within a .resource file

Can you reproduce with a simple example? I suggest that you share it via the code playground.

Hello Francis, I’ve set up a simple example here: Robotframework Example

I’ve also included log parts where I explained my expectations of what should happen.

Hello,

I had a look at your code, and made a couple of small fixes.

Now the logged text shows the value set because the variable does not exist.

To summarize, the error was due to one of the keyword arguments being named with the same name as the suite scope variable.

Does that close your issue?

Note that if you want to share the same playground code again, make sure to rewrite (copy paste) all the files before clicking share, otherwise the initial code will be there instead of yours.

changed some things I had seem to forgotten, as you can see in the terminal, the ${testrun} isn’t being resolved even though it is being set through the suite setup. could this problem possibly occur because the .resource file is loaded in before the suite setup is ran?

Yes it would seem so, ${TESTRUN} is only set at suite setup, but this occurs after importing the variables.resource file. So that the variables &{TD01} and @{TC001} silent fail to resolve…

I believe it is not great that this import silently fails… Probably @pekkaklarck already knows about this. Why does it not fail at resource import? Is there a way this could work and the ${MY_SUITE_VARIABLE} suite variable is filled in later in the already imported variables? Or make the substitution for this variable more of a last moment thing: when the variable is used rather than atthe resource import?

But to come back to @Leon2699 specific case, I would suggest the following fix if that matches your needs:

  • expand ${TD01} dictionary rather tahn ${TC001} list (which by the way has only one item)
  • pass ${TESTRUN} separately

Another work around could be (needs testing, which I don’t think can be done on the playgroud) to use initialisation files, in there you would run the suite setup in the suite directory, before the import of variables.resource file in the suite file.

Could you clarify what you mean with the import silently failing? I see there failures about creating variables, but that doesn’t mean that the import itself would be considered failed by Robot. Import fails for real, for example, if the file isn’t found at all.

Probably the easiest way to check does a variable exist and to use a default value if it doesn’t is using the BuiltIn keyword Get Variable Value.

${value} =    Get Variable Value    $var    default

Using the $var syntax here isn’t absolutely necessary, but it’s highly recommended as resolving ${var} depends on its value.

We’ve also been thinking about adding a possibility to specify a default value when accessing a variable. The syntax would be ${var=default} that we already support with environment variables.

2 Likes

Yes, this might not be an import issue. But I still think the error is arriving too late.

The code is simple here. But in actual tests it might be tricky to work out why ${VARIABLE_2} is defined but not ${VARIABLE_1}.

Apparently ${VARIABLE_1} is not defined because ${MY_SUITE_VARIABLE} is only defined in the suite setup (so actually available by the time we try to use ${VARIABLE_1}). So I am not quite sure when the issue should be raised if not at import.

Actually, I don’t get why it does not work at all. Scope usage seems good. I don’t know when the variable is actually defined/evaluated.

Do you want me to open an issue on Github, and have a dedicated discussion there?

${VARIABLE_1} cannot be created because ${MY_SUITE_VARIABLE} isn’t available at that time. That’s by design and I don’t think changing the design is feasible.

The following example demonstrates a similar situation. The ${Y} variable is created based on ${X}, but its value isn’t changed if ${X} is changed.

*** Variables ***
${X}    x
${Y}    ${X}

*** Test Cases ***
Example
    Log    ${Y}
    VAR    ${X}    z    scope=suite
    Log    ${Y}
2 Likes