Within robot framework, I can use a for loop in each test case to Start an SSH connection to each host within a list, and then run commands on that host.
But it seems that the ssh setup happens in every test case which takes a considerable amount of time.
Is there some way in which I can make the connection persistent for every test case in a test suite?
Example Code:
*** Settings ***
Variables sys_variables.py
Resource ${RESOURCES}/common.robot
*** Test Cases ***
Ping :FOR ${HOST} IN #{REACHABLE}
\ SSH to ${HOST} ${USER} ${PASS}
\ ${result} = Run and Log ${PING_GOOGLE_DNS}
\ Should Be Equal As Integers ${result} 0
\ log ${result}
This works, but I'd like to not have to run it in every testcase.
Just put the tests in a single suite and make the connections in the suite setup. The suite setup is executed one time, before the actual test executions.
Consider the following example code:
*** Settings ***
Suite Setup SuiteSetup
*** Test Cases ***
Test1
Log This is the test 1
Test2
Log This is the Test 2
*** Keywords ***
SuiteSetup
Log This is the single setup
Put your connection cycle inside the SuiteSetup keyword and you're done.
Related
I have a simple test, using the SSHLibrary which I'd like to start and run in parallel on multiple hosts. Now I have statically set 'host1'. How would I run this on host1, host2 and host3 at the same time?
*** Settings ***
Documentation Demo
Library SSHLibrary
Suite Setup Open Connection And Log In
Suite Teardown Close All Connections
*** Variables ***
${HOST} host1
${USERNAME} user
*** Test Cases ***
Evaluate command status
[Documentation] Demo
${output} Execute Command net show version
Should Be True $output
*** Keywords ***
Open Connection And Log In
Open Connection ${HOST}
Login With Public Key ${USERNAME} /home/user/.ssh/id_rsa
You can set the variable on the command line with the --variable or -V option:
robot --variable host:host1
robot --variable host:host2
For more information see Setting variables in command line in the robot framework user guide.
Robot iteself doesn't provide any features to run tests in parallel. To run them in parallel you could write a script that runs robot in the background for each host, and then combine the reports from each run into a single unified report.
*** Settings ***
Documentation Transfer a file from OCU to PC
Library SSHLibrary
Suite Setup Open Connection and Login With Public Key
Suite Teardown Close All Connections
*** Variables ***
${REMOTE HOST} 192.168.x.xxx
${USER} xxx
*** Keywords ***
Open Connection and Login With Public Key
Open Connection ${REMOTE HOST}
Login With Public Key ${USER} /home/bhushan/.ssh/id_rsa
*** Test Cases ***
Run the given command on the console
${pwd}= Execute Command pwd
Should Be Equal ${pwd} /home/root
${output}= Execute Command ls
${output}= Execute Command scp /home/root/myfile.txt bhushan#192.168.x.xxx:/home/bhushan/vdr-reports/
Log ${output}
I have Dropbear of the latest version installed on my target. I am trying to run the above SSH Library Robot framework keyword based test case which defines to transfer a file from remote to the local host. The execute command keyword works in the beginning i.e. ${output}= Execute Command ls, but i am getting an error while using the same keyword in copying the files, i.e i can't see anything happening on the console. It is hanging and i waited for long time to see the output but haven't seen anything. But this works when i copy the files to my local machine manually. Can anyone here try to help me in fixing this error.
KEYWORD ${output} = SSHLibrary . Execute Command scp
/home/root/myfile.txt bhushan#192.168.x.xxx:/home/bhushan/vdr-reports/
Documentation: Executes command on the remote machine and returns
its outputs. Start / End / Elapsed: 20170829 10:26:23.897 / 20170829
10:26:50.148 / 00:00:26.251 10:26:23.898 INFO Executing command 'scp
/home/root/myfile.txt
bhushan#192.168.x.xxx:/home/bhushan/vdr-reports/'...................>
This is what i see in the log
I am trying to check if the process is actively running from the unix system.It can be one process or multiple process .Following is the example that i am trying. Can someone guide me how this can be achieved ?
*** Settings ***
Library Process
Library OperatingSystem
*** Test cases ***
Example
${output} = Run process /etc/init.d/bluetooth
${op}= Is Process Running ${output}
Should be equal ${op} True
[root#test ssh-scripts]# pybot test-process.robot
==============================================================================
Test-Process
==============================================================================
Example | FAIL |
Non-existing index or alias '<result object with rc 3>'.
------------------------------------------------------------------------------
Test-Process | FAIL |
1 critical test, 0 passed, 1 failed
1 test total, 0 passed, 1 failed
==============================================================================
/etc/init.d/bluetooth is startup script, you won't to check the startup script but rather the process(es) started by it
Keyword Run Process waits till the process terminates. You probably won't wait for termination, you rather want to run the process on background.
This works as expected for me:
Test Processes
${handle} Start Process echo foo stdout=/tmp/bar
${output} Is Process Running handle=${handle}
Should Not Be True ${output}
${handle} Start Process yes stdout=/dev/null
${output} Is Process Running handle=${handle}
Should Be True ${output}
[Teardown] Terminate All Processes
I.e. echo terminates earlier than the first Is Process Running check is performed. But yes is started and keeps running in the moment of second Is Process Running.
Following script worked for me . I have placed a regex pattern to match the string after command is executed. This can achieved in alternate way but this served my purpose.
*** Settings ***
Library Process
Library SSHLibrary
Suite Setup Open Connection And Log In
Suite Teardown Close All Connections
Library OperatingSystem
*** Variables ***
${HOST} 16.10.90.24
${USERNAME} root
${PASSWORD} admin123
${postgres_cmd} /etc/init.d/DB_Platform_TaskManager status
${PATTERN} (?m).*is\ running
*** Test Cases ***
Check whether postgres is running
Open Connection And Log In
Start Command ${postgres_cmd}
${rc}= Read Command Output return_stdout=True return_rc=False
Log ${rc}
Should Match Regexp ${rc} ${PATTERN}
*** Keywords ***
Open Connection And Log In
Open Connection ${HOST}
Login ${USERNAME} ${PASSWORD}
I have following codes, some of them work but...(These sections are in 1 file and consecutive, split for clarification)
*** Settings ***
Documentation documentation for this test suite
... requires command line variables: IP
resource resource/applicationcontrol.robot
resource resource/clientmgr.robot
Suite Setup applicationcontrol.Open connections
Suite Teardown Close connections
Test Setup Exit Current Running Apps
*** Variables ***
#{apps} 1stapp 2ndapp 3rdapp 4thapp
=====================================================
*** Keywords ***
App For Port [Arguments] ${app}
:for ${port_num} IN 1 2
\ applicationcontrol.Launch application ${app} ${port_num}
\ ${status} Run Keyword And Return Status Check launching status ${app} ${port_num}
\ Continue For Loop If '${status}'=='False'
\ Run Keyword If '${status}'=='True' Add Success
\ Exit For Loop <--Line in question
Q: Exit For Loop exits the most enclosing For loop or all nesting For Loops?
======================================================
Add Success
${success_num} Evaluate ${success_num} + 1
Ratio Statistics
${fail_num} Evaluate ${total_num} - ${success_num}
Log Total: ${total_num}, Failed: <p style="color:red">${fail_num}</p> HTML
Exit Current Running Apps
:for ${port_num} IN 1 2
\ Exit application ${port_num}
\ Check exit status ${port_num} <--Line in question
Q: Check exit status ${port_num} gets executed only for 1st loop...don't understand why
======================================================
*** Test Cases ***
Launch and exit multiple apps [Arguments] #{apps}
${temp} Get Length ${apps}
Set Test Variable ${total_num} ${temp}
Set Test Variable ${success_num} 0
:for ${app} IN #{apps} <--Line in question
\ App For Port ${app}
\ Exit Current Running Apps
Ratio Statistics <--Line in question
Q: :for ${app} IN #{apps} This For Loop should have executed 4 times, but only executed for 1 time.
Q: Ratio Statistics never gets executed. How can I get it executed?
I cannot find answers on internet or User's Guide. Thanks in advance.
Additional:
resource/applicationcontrol.robot:
Exit application [Arguments] ${PORT}
${RUNNING_RESPONSE} send cmd appsvc get_apps
${RUNNING_APPS} response parameter ${RUNNING_RESPONSE}
Pass Execution If '${RUNNING_APPS}' == '${None}' No app running on ${PORT}
${TARGET_APP} get target application ${RUNNING_APPS} ${PORT}
send cmd appsvc exit_app ${TARGET_APP}
Exit For Loop exits the most enclosing For loop or all nesting For Loops?
Real nested for loops don't exist in Robot.
You can just have a loop that calls a keyword that has a loop.
Anyway, "Exit For Loop" exist the current loop (most enclosing if you want)
Check exit status ${port_num} gets executed only for 1st
for ${app} IN #{apps} This For Loop should have executed 4 times
Ratio Statistics never gets executed. How can I get it executed?We don't have enough information to help you on those questions. Yes, it should work the way you describe... See Brian's comment.
Thanks everyone, I found the answer.
In resource/applicationcontrol.robot:
Exit application [Arguments] ${PORT}
${RUNNING_RESPONSE} send cmd appsvc get_apps
${RUNNING_APPS} response parameter ${RUNNING_RESPONSE}
Pass Execution If '${RUNNING_APPS}' == '${None}' No app running on ${PORT}
${TARGET_APP} get target application ${RUNNING_APPS} ${PORT}
send cmd appsvc exit_app ${TARGET_APP}
The Pass Execution If statement exits current test case in question instead of the rest of that keyword, which is what I want it to be.
So my solution is putting the rest of this keyword into a new 'helper' keyword and using Run Keyword Unless instead to invoke the new keyword.
I am using Robot Framework SSH Library for my automation.
I need to establish SSH Tunnel to a remote machine using Robot Framework and then execute set of tests on the remote machine.
Looks like RF SSH Library do not have support for this.
Can someone point me to any other options available?
Thank you!
You could use Robot Framework to open SSH connection, copy test files, run them and copy results back.
You will need two files, first one is ssh.txt
*** Settings ***
Library SSHLibrary
Suite Setup Open Connection And Log In
Suite Teardown Copy And Delete Files And Close Connections
*** Variables ***
${HOST} your.server.here
${USERNAME} username
${PASSWORD} password
*** Testcases ***
Run Tests on remote server
Put File real-test.txt
Run Test In Server real-test.txt
Sleep 1s
*** Keywords ***
Open Connection And Log In
Open Connection ${HOST}
Login ${USERNAME} ${PASSWORD}
Copy And Delete Files And Close Connections
Copy Results From Server
Clean Up Server real-text.txt
Close All Connections
Run Test In Server
[Arguments] ${filename}
${rc}= Execute Command pybot ${filename} return_stdout=False return_rc=True
Should Be Equal As Numbers ${rc} 0
Copy Results From Server
GetFile log.html
GetFile output.xml
GetFile report.html
Clean Up Server
[Arguments] ${filename}
Write rm log.html
Write rm output.xml
Write rm report.html
Write rm ${filename}
the 2nd file is where real tests are, real-test.txt:
*** Settings ***
Library OperatingSystem
*** Testcases ***
Test 1
FileShouldExist real-test.txt
run this by specifying output files to avoid filename collisions when log files are copied back from server:
pybot -o conn.xml -r conn.html -l connlog.html ssh.txt
I recently did something like this but created the functionality in Python which I then imported to Robot as a keyword.
The jist of it was:
in SSHTunnel.py:
from sshtunnel import SSHTunnelForwarder
(other imports)
class SSHTunnel:
def create_ssh_tunnel(self):
ssh_server = SSHTunnelForwarder(
(host, int(port)),
ssh_username=username,
ssh_password=pass,
remote_bind_address=(remote_bind_host, int(remote_bind_port))
)
ssh_server.start()
def stop_ssh_tunnel(self):
ssh_server.stop()
Now you add the SSHTunnel.py file to the Robot Library and call the keyword Create SSH Tunnel in the beginning of the testcase (can also be in Test Setup or Suite Setup) and Stop SSH Tunnel at the end.
Hope that helps.
Library SSHLibrary
Open Connection host_server
Login With Public Key test /test.pem test12345
Create Local SSH Tunnel 9191 remote_host remote_port bind_address=127.0.0.1
#Once the connection is made you can directly access the resources in remote_host, for eg : i am trying to connect mysql db in remote host
Connect To Database Using Custom Params pymysql database='testDb', user='testuser', password='test123', host='127.0.0.1', port=9191
You can achieve this with the help of 'local port forwarding' feature.
Ref: https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding.
Use this command on the test server(where the robot is running) in an instance:
ssh -4 -L <listening_port/forwarding_port>:<destination_ip>:destination_port> username#jump_box.com
eg)
ssh -4 -L 50025:10.122.56.45:23 anishg#jumpbox.teski.com
Use the following command in another instance to work in the destination server:
telnet localhost <listening port>
eg)
telnet localhost 50025
Here you can execute the commands as like you are working on the destination server, as the session is opened.
In Robot, this can be achieved by this way also:
The Step (1) - Port forwarding is done in a shell script and this shell script is called in your robot framework.
Do Telnet/other in localhost with port specified
sample.sh:
ssh -4 -L 50025:10.122.56.45:23 anishg#jumpbox.teski.com
Robot Code:
*** Test Cases ***
Port Forwarding
Start Process ./sample.sh shell=True #Port is opened
Log To Console SHELL IS Executing
Telnet.Open Connection localhost port=50025 #Normal op as in destn server
Note: I used jump_box as I dont have access to destination server from my test instance.