Robot Framework: Check that Run Keyword If enters branches - robotframework

I have a keyword which contains several Run Keyword If branches, like:
main keyword with ${condition}
Run Keyword If ${condition}=="1" keyword1
Run Keyword If ${condition}=="2" keyword2
I'm looking for a mechanism to check that a branch gets executed.
I tried:
main keyword with ${condition}
${result1}= Run Keyword If ${condition}=="1" keyword1
${result2}= Run Keyword If ${condition}=="2" keyword2
Should Be True ${result1} is not None or ${result2} is not None
but I always get result1 and result2 None, even if keyword1 or keyword2 are executed.
Please give me a hint on this or how I could achieve my goal in a better way.
LE:
I tried out the second option suggested by Bence Kaulics.
My keywords now look like this:
*** Keywords ***
main keyword ${condition}
${result1} = run keyword if '${condition}'=='test_1' run keyword and return status keyword1
${result2} = run keyword if '${condition}'=='test_2' run keyword and return status keyword2
should be true ${result1} or ${result2}
keyword1
log "executed keyword1"
keyword2
log "executed keyword1"
And they work as expected. I get a fail in Robot if no branch is executed.
Thank you for the solution! :)

Your keyword1 and keyword2 probably do not have any return value, otherwise ${result1} and ${result2} should store the return values of your keywords.
So either add return values to your keywords:
*** Test Cases ***
Test
${result1}= Run Keyword If 1==1 Keyword1
Log Result1:${result1}
*** Keywords ***
Keyword1
No Operation
[return] Anything can be returned
Output:
Or to have status results you can use the Run Keyword And Return Status like below. If you have keywords without return values this is the way to go.
*** Test Cases ***
Test
${result1}= Run Keyword If 1==1 Run Keyword And Return Status Log 1
${result2}= Run Keyword If 2==3 Run Keyword And Return Status Log 2
Log Result1:${result1}
Log Result2:${result2}
This would give the following outputs:

Related

How to skip remaining steps in a test case 1 and continue with other Test cases in Robot Frame work

*** Test Case ***
Test Case 1
step 1
step 2
error handling $value
step 3
step 4
Test Case 2
....
....
....
*** Keyword ***
error handling
Run Keyword if $value=='Text'
"execute this steps" #after matching how to skip remaining steps in test Case 1 and continue with Test Case 2
ELSE
Continue with next steps
i want to skip "step3 & step 4" if "$value == Text" in "error handling" keyword
Use Pass Execution inside the if clause, if you want to skip the rest.
It does just that, marks the case as passed without running what remains in it (apart from the teardown). And the same can be achieved with failing status by the Fail keyword call.
Try below code, it will not mark status as skip
*** Variables ***
${status}= ${False}
*** Tasks ***
Conditional task: Skip if a response matches
Skip If ${status}
Log to console Task is skipped
*** Tasks ***
Main task
Log to console Task is completed
Try this. It will skip all rest of the steps when condition match
*** Test Case ***
Test Case 1
${value}= Set Variable Text
${Text}= Set Variable Text
Log To Console message1
Log To Console message2
${status}= error handling ${value} ${Text}
BuiltIn.Skip if '${status}' == '${True}'
Log To Console message3
Log To Console message4
*** Keyword ***
error handling
[Arguments] ${value} ${Text}
IF '${value}' == '${Text}'
Return From Keyword ${True}
ELSE
Continue with next steps
END

Unable to see Set Test Message log value after test case marked as fail

I have the below code:
*** Settings ***
Library OperatingSystem
Library Process
Library String
*** Variables ***
#{MyList}= item items items2
${LogStr1} *HTML*
*** Test Cases ***
#Start Test#
[xxxxx] My tests
FOR ${item} IN #{MyList}
General test.out testProfile ${item}
[Template] Run Test
[Tags] TestTags
END
*** Keywords ***
Run Test
[Documentation] Run the test
[Arguments] ${type} ${profile} ${file} ${test}
When suite config is updated
And updated the config in directory ${test}
Then publish test status
suite config is updated
[Documentation] Get the variables list
Log to Console "Updating get suite config file"
updated the config in directory ${test}
[Documentation] Get the variables list
Run keyword if "${test}" == "items" Stop Test "This is stop called"
publish test status
[Documentation] Create and check if any issue found
${LogStr}= Catenate Test Passed : Log created: Hello
Log to Console ${LogStr}
${LogStr1}= Catenate ${LogStr1} ${LogStr}\n
Set Test Variable ${LogStr1}
Set Test Message ${LogStr1}
Stop Test
[Documentation] Stop Execution
[Arguments] ${FIALUREMSG}
Log To Console ${FIALUREMSG}
${LogStr1}= Catenate ${LogStr1} ${FIALUREMSG}
Fail ${LogStr1}
As per the code the test can be pragmatically made to fail at 1st second or third run. So when I have the code like:
Run keyword if "${test}" == "item" Stop Test "This is stop called"
in mentioned keyword, there are 2 test cases that passes for a suite but report states:
Now if I make the second test case to fail I get below test message logs:
Run keyword if "${test}" == "items" Stop Test "This is stop called"
in mentioned keyword, there are 2 test cases that passes for a suite but report states:
Similarly if
Run keyword if "${test}" == "items2" Stop Test "This is stop called"
And so on - hence it seems that "Set Test Message" log values are ignored in report message when a test case is marked as Fail. Note that below is the log.html content when I ran the code to mark the very first test case as failure:
Run keyword if "${test}" == "item" Stop Test "This is stop called"
In all my question is thus that if I want report.html file to show logs for all fail and passed test cases how can I achieve it?
If you check the documentation of the Set Test Message keyword it says that any failure will override the messages, but you have the option to override the failure message from the teardown.
In test teardown this keyword can alter the possible failure message,
but otherwise failures override messages set by this keyword. Notice
that in teardown the message is available as a built-in variable
${TEST MESSAGE}.
So what you can do is instead of calling Set Test Message, you could just save the messages into a test variable. Then you should add a teardown in which you call the Set Test Message and concatenate your test variable with the ${TEST MESSAGE}. For example:
*** Test Cases ***
Test
[template] Template
[setup] Set Test Variable ${MSG} ${EMPTY} # create empty test variable to store messages
1
3
2
5
6
4
6
[teardown] Set Test Message ${MSG}\n${TEST MESSAGE} # concatenate failure messages to normal test messages
*** Keywords ***
Template
[arguments] ${number}
No Operation
Run Keyword If ${number} == 2 Fail fail message ${number}
Run Keyword If ${number} == 4 Fail fail message ${number}
Set Test Variable ${MSG} ${MSG}\nMy test message ${number} # concatenate next test message
This example produces the following report:
With this approach you could have only the template tests in the particular robot suite as all test listed in the Test Cases table will invoke the template.
Other, completely different solution can be to get rid of the FOR loop as elements in #{MyList} are static. If you move the template into the Settings table and then manually list all iterations, you could separate each one of them into an independent test case. This way failure in one iteration won't affect the test message set in an other iteration. For example:
*** Settings ***
Test Template Template
*** Test Cases ***
Test1 1
Test2 2
Test3 3
Test4 4
Test5 5
Test6 6
*** Keywords ***
Template
[arguments] ${number}
No Operation
Run Keyword If ${number} == 2 Fail fail message ${number}
Run Keyword If ${number} == 4 Fail fail message ${number}
Set Test Message My test message ${number}
This would produce the following report:
You have a third option in addition to my other answer but it is a bit more advanced solution so I have decided to post it as a separate answer.
You can write a small test library in Python that would also act as a listener. In this listener library you would need three functions out of which two would be keyword and one would be a listener function.
First function is _log_message which is described in the listener API 2. This function will be called by the framework if any logging happens. So when a test fails this keyword will receive the log entry of the failure which can be saved for later use. This function, as it starts with _ is not available in a robot suite as keyword.
def _log_message(self, message):
if message['level'] == 'FAIL':
self.test_message = f"{self.test_message}\n{message['message']}" # concatenate failure message
Second function add_test_message will replace the Set Test Message keyword in your code. Its purpose will be similar, which is to append the messages you want to set as test messages. This can be called from a robot suite as a keyword.
def add_test_message(self, message):
self.test_message = f"{self.test_message}\n{message}" # concatenate normal test message
The last function set_final_test_message will set the actual test message for you. This keyword has to be called at the end of the test teardown to ensure no other failure will override your test message. It simply calls the Set Test Message keyword internally and sets the string created by the previous two functions. This can be called from a robot suite as a keyword.
def set_final_test_message(self):
"""
Call this keyword at the end of the test case teardown.
This keyword can only be used in a test teardown.
"""
BuiltIn()._get_test_in_teardown('Set Final Test Message') # Check if we are in the test teardown, fail if not.
BuiltIn().set_test_message(self.test_message) # Call Set Test Message internally
As the purpose of the library is to set test messages the library scope should be TEST CASE. This means that a new library object will be created before every test case, effectively resetting any messages set by previous tests.
Here is the whole code of the library (TestMessageLibrary.py):
from robot.libraries.BuiltIn import BuiltIn
class TestMessageLibrary(object):
ROBOT_LIBRARY_SCOPE = 'TEST CASE' # define library scope
ROBOT_LISTENER_API_VERSION = 2 # select listener API
ROBOT_LIBRARY_VERSION = 0.1
def __init__(self):
self.ROBOT_LIBRARY_LISTENER = self # tell the framework that it will be a listener library
self.test_message = '' # internal variable to build the final test message
def _log_message(self, message):
if message['level'] == 'FAIL':
self.test_message = f"{self.test_message}\n{message['message']}" # concatenate failure message
def add_test_message(self, message):
self.test_message = f"{self.test_message}\n{message}" # concatenate normal test message
def set_final_test_message(self):
"""
Call this keyword at the end of the test case teardown.
This keyword can only be used in a test teardown.
"""
BuiltIn()._get_test_in_teardown('Set Final Test Message') # Check if we are in the test teardown, fail if not.
BuiltIn().set_test_message(self.test_message)
globals()[__name__] = TestMessageLibrary
This is an example suite with the library:
*** Settings ***
Library TestMessageLibrary
*** Test Cases ***
Test
[template] Template
1
3
2
5
6
4
6
[teardown] Set Final Test Message
Other Test
Add Test Message This should not conflict
[teardown] Set Final Test Message
*** Keywords ***
Template
[arguments] ${number}
No Operation
Run Keyword If ${number} == 2 Fail fail message ${number}
Run Keyword If ${number} == 4 Fail fail message ${number}
Add Test Message My test message ${number}
Example run called with robot --pythonpath ./ SO.robot. As the library is in the same directory as the suite file --pythonpath ./ was need to be able to import the library.
Report file:

Robot Framework: why does Log ignore my argument?

When I run the code below I get an error message
Keyword 'BuiltIn.Log' expected 1 to 5 arguments, got 0.
for the second log to console (within the if-clause). Why? Why doesn't it "see" the variable I try to send as an argument?
Googling doesn't return anything useful. I have tried several combinations of spaces and apostrophes but nothing has worked.
Function key above F12
[Arguments] ${fkey}
${ValidFKeys}= Create List F13 F14 F15 F16 F17
log to console ${fkey}
Run Keyword If $fkey in $ValidFKeys run keywords
... log to console ${fkey}
Check the Run Keywords documentation:
By default all arguments are expected to be keywords to be executed.
What happened is Run Keywords treated Log To Console as the first keyword to be ran, then the value of ${fkey} as the second - it did not pass it as argument to the log. To overcome this, add an "AND" - so now it knows ${fkey} is an argument; if yo udon't have any other keyword to be ran, either drop Run Keywords, or use No Operation:
Run Keyword If $fkey in $ValidFKeys run keywords
... log to console ${fkey} AND No Operation

How to use run a keyword if testcasename is equal to abc in robotframework

I know how can we use run keyword if specific condition is met but i want to run a keyword if testcasename matches.
run keyword if testcase=abc.robot
does anyone know how can we achieve that.
Robot framework provides several automatic variables -- variables that are set automatically by the framework. One such variable is ${TEST_NAME}.
In the following example, only the log statement in the second test will run:
*** Test Cases ***
Example 1
run keyword if "${TEST_NAME}" == "Example 2"
... log this is example 2?
Example 2
run keyword if '${TEST_NAME}' == "Example 2"
... log this is example 2!
Run Keyword If '${TEST_NAME}'=='<your_test_name>' <Keyword> <args>

Run a test case Multiple times and display the pass and fail count under test statistics

How to run a particular test case multiple times and display the pass and fail count under Test Statistics?
Below is the current code I have to run a test case multiple times. (The test case is implemented in a keyword and called)
*** Test Cases ***
Testcase
repeat keyword 5 Run Keyword And Continue On Failure Execute
*** Keywords ***
Execute
log Hello world!
The code is run from cmd using "pybot testcase.robot"
This code runs the test multiple times but I'm not getting the final pass/fail count in the logs.
I need to manually count the pass and fail test case repetitions.
So what modifications should I do to get the data automatically and should be seen in Test Statistics of the log also.
Instead of using "Repeat Keyword", use For loop.
Use "Run Keyword And Return Status" instead of "Run Keyword And Continue On Failure ".
*** Test Cases ***
Test Me
${fail}= Set Variable 0
:FOR ${index} IN RANGE 5
\ ${passed}= Run Keyword and Return Status Execute
\ Continue For Loop If ${passed}
\ ${fail}= ${fail} + 1
${success}= Set Variable 5 - ${fail}
Log Many Success: ${success}
Log Many fail: ${fail}

Resources