If I have a list of strings ['PASS', 'FAIL', 'PASS'], how can I return
multiple PASS or FAIL status, depending on the string? Right now I have something like:
test01
:FOR ${test} IN #{tests}
\ Log to Console ${test}
\ Should Match ${test} PASS
The robot framework will return:
test01
PASS
PASS
FAIL
test01 | FAIL |
'FAIL' does not match 'PASS'
Essentially I want one test to dynamically generate the TEST_STATUS for an arbitrary length list, and the results to look something like:
test01
PASS | PASS |
PASS | PASS |
FAIL
test01 | FAIL |
'FAIL' does not match 'PASS'
You have to create separate test cases, since a test case has exactly one status, PASS or FAIL.
However, there are ways to ensure that all values in the list are handled. The easiest, I think, is using a test case template, like this
Test Case
[Template] Should Be Equal
: FOR ${status} IN #{VALUES}
\ ${status} PASS
With template, all the steps are run in continue on failure mode, which means that a failure does not prevent the loop from finishing. Instead, they failure(s) are collected and used to create a final status.
Related
I want to use Robot Framework to write and execute Test Cases in Gherkin format.
What I want is when I execute a Test Case, output in the console besides the name
of the Scenario, each step (When, Then...) and log as well if the step passes or not.
You could achieve such functionality with a listener that uses the listener interface of the framework.
The end_keyword listener method will be invoked during execution when a keyword is finished. It will get the keyword name and its attributes as a parameter, so you can log both the name and the status.
You have to filter it so only keywords starting with Given, When, Then will be logged on the console.
Example:
ROBOT_LISTENER_API_VERSION = 2
def start_test(name, attributes):
# Add an extra new line at the beginning of each test case to have everything aligned.
print(f'\n')
def end_keyword(name, attributes):
if name.startswith('Given') or name.startswith('When') or name.startswith('Then'):
print(f'{name} | {attributes["status"]} |')
Console output for the behavior-driven development example of the user guide.
robot --pythonpath . --listener listener.py test.robot
==============================================================================
Test
==============================================================================
Add two numbers
Given I have Calculator open | PASS |
.When I add 2 and 40 | PASS |
.Then result should be 42 | PASS |
Add two numbers | PASS |
------------------------------------------------------------------------------
Add negative numbers
Given I have Calculator open | PASS |
.When I add 1 and -2 | PASS |
.Then result should be -1 | PASS |
Add negative numbers | PASS |
------------------------------------------------------------------------------
Test | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
==============================================================================
This is my code:
:FOR ${a} IN RANGE 2 ${Row_Count}
\ Run Keyword If '${temp}'== 'True' Click Link xpath=//table[#id='listAllSTR']/tbody/tr[${a}]/td[2]/a and
\ ... Screen validation for Answered ${STR_detail} and
\ ... ELSE Continue For Loop
\ Run Keyword If ${a}>${Row_Count} Exit For Loop**
When the if condition passes (i.e. if '${temp}'== 'True'), I need to click a link, but I'm getting an error saying
Keyword 'Selenium2Library.Click Link' expected 1 argument, got 5.
I don't know what to do.
Can anyone help me out?
About the Issue.
You are executing multiple keywords in your if statement so, it is taking other keywords as arguments to first one.
Solution
You can create a custom keyword and add other keywords to it. Use this custom keyword in your if statement. see below example.
*** Keywords ***
Custom Keyword From If
[Documentation] Keywords documentation.
keyword1
keyword2
*** Test Cases ***
Test Custom Keyword
Run Keyword If '${a}'=='True' Custom Keyword From If
NOTE:
For executing multiple keywords robot has the keyword "run keywords" see the documentation link
in robot framework ... are used to continue the code on next line as part of previous line
in the example you trying after click link keyword you add ... which causing this error remove those and your code will start running.
click link keyword accepts only one parameter as locator in your case it considers following to lines as parameter
:FOR ${a} IN RANGE 2 ${Row_Count}
\ Run Keyword If '${temp}'== 'True' Click Link
xpath=//table[#id='listAllSTR']/tbody/tr[${a}]/td[2]/a
\ Screen validation for Answered ${STR_detail}
\ ELSE Continue For Loop
\ Run Keyword If ${a}>${Row_Count} Exit For Loop
edit
new syntax of for loop
FOR ${a} IN RANGE 2 ${Row_Count}
Run Keyword If '${temp}'== 'True' Click Link
xpath=//table[#id='listAllSTR']/tbody/tr[${a}]/td[2]/a
Screen validation for Answered ${STR_detail}
ELSE Continue For Loop
Run Keyword If ${a}>${Row_Count} Exit For Loop
END
I would like to look for a particular message in a constantly updating file. I used Wait Until Keyword Succeeds with my own keyword to search the file and it works fine.
*** Test Cases ***
${lineCount} MyKeywordToGetLineCountToStartSearch ${filename}
Wait Until Keyword Succeeds 10s 2s KeywordToLookForTheMessage ${filename} ${linecount} ${message}
*** Keywords ***
KeywordToLookForTheMessage
[Arguments] ${filename} ${linecount} ${message}
Run tail -n +${linecount} ${filename} > ${locationdir}/${newfile}
${filecontent} Get File ${locationdir}/${newfile}
#{lines} Split To Lines ${filecontent}
${result_list} Create List
: FOR ${line} IN #{lines}
\ ${state} ${msg} Run Keyword And Ignore Error Should Contain ${line} ${message}
\ Run Keyword If '${state}' == 'PASS' Append To List ${result_list} ${line}
Should not be empty ${result_list}
Now what I'm missing is ,
With each iteration I need the line count to be updated so that I don't look through the same lines again .
While doing that, I would also want to retain the original line count value for further in the testcase.
How can I do that ?
This kind of complex logic should be implemented in test library using Python, not trying to use lower level keywords provided by existing libraries.
I have text file which has list of lists like below.
**sample.txt Text file content **:
[["Sanjay", "Bangalore", "100"], ["Akshay", "Pune", "101"], ["Pranay", "Delhi", "102"]]
Requirement:
I have to iterate over each list in he above list and assign each item in list to variable.
Test Case
${FILECONTENT}= Get File sample.txt
Log to console ${FILECONTENT}
: FOR ${ELEMENT} IN ${FILECONTENT}
\ ${NAME}= ${ELEMENT}[0]
\ ${CITY}= ${ELEMENT}[1]
\ ${ID}= ${ELEMENT}[2]
\ Log to console ${ELEMENT}
Log to console For loop is over
I am not able to loop over content as its not treating content as list of lists.
Can any one help how to achieve this.
The example code you provided has a few issues. First, and foremost is that you need to convert the string to a list-in-list construction. Then you need to correctly iterate over it and lastly assign variables in the right way.
As there isn't a native keyword to allow for instant string to list-in-list conversion I created a custom keyword library for it and stored it as List.py in the same folder as your robot script:
import ast
class List(object):
ROBOT_LIBRARY_VERSION = 1.0
def __init__(self):
pass
def ConvertToListFromString(self, ListString):
x = ast.literal_eval(ListString)
return x
This library can then be utilized to create the functionality in robot:
*** Settings ***
Library OperatingSystem
Library List
*** Test Cases ***
Sample
${FILECONTENT}= Get File sample.txt
#{list} Convert To List From String ${FILECONTENT}
Log to Console ${EMPTY}
: FOR ${ELEMENT} IN #{list}
\ ${NAME} Set Variable ${ELEMENT[0]}
\ ${CITY} Set Variable ${ELEMENT[1]}
\ ${ID} Set Variable ${ELEMENT[2]}
\
\ Log to console Name=${NAME}, City=${CITY}, Id=${ID}
This then results into:
Command: C:\Python27\python.exe -m robot.run -P C:\Eclipse\Workspace\ExternalList
-s ExternalList.ExternalList C:\Eclipse\Workspace\ExternalList
Suite Executor: Robot Framework 3.0 (Python 2.7.9 on win32)
==============================================================================
ExternalList
==============================================================================
ExternalList.ExternalList
==============================================================================
Sample
Name=Sanjay, City=Bangalore, Id=100
Name=Akshay, City=Pune, Id=101
Name=Pranay, City=Delhi, Id=102
| PASS |
------------------------------------------------------------------------------
ExternalList.ExternalList | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
ExternalList | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output: C:\Eclipse\Workspace\ExternalList\output.xml
Log: C:\Eclipse\Workspace\ExternalList\log.html
Report: C:\Eclipse\Workspace\ExternalList\report.html
It should be noted that reading files an converting them to code poses some security risks that need to be mitigated. The above code is therefore not Production ready.
If the data is valid JSON, you can convert the data to JSON and then iterate over the values very easily:
${FILECONTENT}= Get File sample.txt
${JSON}= evaluate json.loads($FILECONTENT) json
:FOR ${ELEMENT} IN #{JSON}
\ ${NAME} Set Variable ${ELEMENT[0]}
\ ${CITY} Set Variable ${ELEMENT[1]}
\ ${ID} Set Variable ${ELEMENT[2]}
\ Log to console element: ${ELEMENT}
Note: the other statements in your FOR loop are incorrect. To set new variables you must call the Set Variable keyword. That is why I changed them in the example code.
I would like to repeat the similar commands with replacing few variables in Robot framework. Could please suggest me how to do it?
Here is the sample code:
variable1 = ['abc']
varaible2 = ['123','456']
| | Run Keyword And Continue On Failure | testing | ${variable1} | ${variable2} | ${GetVal} | ${Check} |
variable3 = ['xyz']
varaible2 = ['678','789']
| | Run Keyword And Continue On Failure | testing | ${variable3} | ${variable4} | ${GetVal} | ${Check} |
Yes Robot framework supports for loops here is the example
:FOR ${animal} IN cat dog
\ Log ${animal}
\ Log 2nd keyword
Log Outside loop
For More Examples Please go through this link
http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#for-loops
Robot framework provides a "for" loop with the special keyword :FOR (see For Loops in the user guide)
| | :FOR | ${v2} | IN | #{variable2}
| | | Run keyword and continue on failure
| | | ... | testing | ${variable1} | ${v2} | ${GetVal} | ${Check}
Notice that the body of the loop has an extra level of indentation.
If you want to do nested loops you'll need to create a separate keyword for the nested loop. It very quickly becomes easier to write a single python keyword that does all of the looping and logic, as robot really isn't designed to be a general purpose programming language.
here is an example which loops for a given number
: FOR ${INDEX} IN RANGE 200
\ Log To Console ${INDEX}
The other answers are very good at explaining how to write a simple FOR loop in Robot Framework, so this is added clarity for your information.
First of all, the code to do as you're asking is as follows, assuming the various unknown variables are already defined elsewhere:
*** Test Cases ***
Do Your Test
:FOR ${INDEX} IN RANGE ${INCLUSIVE_STARTING_INDEX1} ${EXCLUSIVE_ENDING_INDEX1}
\ Run Keyword and Continue On Failure testing ${variable1} ${variable2} ${GetVal} ${Check}
:FOR ${INDEX} IN RANGE ${INCLUSIVE_STARTING_INDEX2} ${EXCLUSIVE_ENDING_INDEX2}
\ Run Keyword and Continue On Failure testing ${variable3} ${variable4} ${GetVal} ${Check}
Second, I need to clarify that FOR Loops in Robot Framework are NOT Keywords. They're distinctively separate entities at the most basic level in the language. I learned this by spending hours delving into the code, trying to figure out how it might be possible to code a nestable For loop. To save you the effort of trying, it isn't without coding your own customized keyword in Python.
Also, I should specify that I'm taking the liberty of assuming that you made a few typos in your question, and that your personalized keyword "testing" that you wrote somewhere else accepts a list object as its second input variable. If that is incorrect, let me know and I'll give you a more accurate answer.
If you want only one loop you can use
:FOR ${iTemp} IN #{listOfStudents}
\ Log ${iTemp}
\ Log GO_ON.
but you can't make loop inside loop
for that you should use keyword for that like below
First Loop
:FOR ${i} IN #{listOfStudents}
\ Log ${i}
\ Log OutSide Loop
Outside Loop
:FOR ${j} IN #{ListOfSubject}
\ Log ${j}
\ Log new Kewords.
Thats the way you can use loops in Robot Framework
Thasnks
For loop syntax was enhanced in Robot Framework 3.1. New syntax is as follows:
*** Test Cases ***
Example
FOR ${animal} IN cat dog
Log ${animal}
Log 2nd keyword
END
Log Outside loop
Second Example
FOR ${var} IN one two ${3} four ${five}
... kuusi 7 eight nine ${last}
Log ${var}
END