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.
Related
I use SSHLibrary to connect to the computer to run test cases. As follows:
*** Test Cases ***
Check CPU Temperature
Check that the CPU temperature is less than ? °C ${CPU tem}
Check CPU Usage
Check if any application is using CPU more than ? percent ${CPU usage percent}
Check TCP transmission
Check TCP transmission > ? MBytes ${tcp transmission}
*** Keywords ***
Open Connection & Login
Open Connection ${HOST}
Login ${ACCOUNT} ${PASSWORD}
#(The following is omitted)
I would like to ask how can I do if I want to use the same Test cases to test the second computer?
Well, that depends how much you want to change the structure of your current file/tests. Since you have single variables ${HOST}, ${ACCOUNT}, and ${PASSWORD} and it doesn't seem from your question that you iterate over some data structure where you store different login information for several different hosts, then the more straightforward way of running this is just to run several commands:
$ robot --variable HOST:host1 --variable ACCOUNT:a --variable PASSWORD:secret * && robot --variable HOST:host2 --variable ACCOUNT:a --variable PASSWORD *
EDIT: As I have been correctly reminded in the comments, executing the second command from the previous example will overwrite the outputs created by the first command, so a better way to go about it (to preserve logs from both executions) is something like this:
$ robot --timestampoutput --output host1 --log host1 --report host1 --variable HOST:host1 --variable ACCOUNT:a --variable PASSWORD:secret * && robot --timestampoutput --output host2 --log host2 --report host2 --variable HOST:host2 --variable ACCOUNT:a --variable PASSWORD:secret *
That will create separate outputs for each command in the following format: host{n}-{date}-{time}.
Since this is already a long command, it's better to use argument file that contains all these command-line options, you can later reference just this file from the command like: $ robot --argumentfile <path_to_argument_file>. More on that here.
This approach requires no change in your test/keyword files, but it doesn't scale very well if you have a lot of machines to run these tests on.
I'd most likely go for the following approach:
create a resource file with login information to all the machines I want to run these tests. If could be something like this:
Resources/machines.py
MACHINES = [
{
"host": "host1",
"account" "a",
"password": "secret"
},
{
"host": "host2",
"account" "b",
"password": "secret"
}
]
I'd iterate over this test data in each test case, calling the keywords with these values, something like:
*** Test Cases ***
Check Temperature
FOR ${machine} IN #{MACHINES}
# you would need to assing values from the dict into ${host}, ${account},
# and ${pwd} here, you want to check Collections library for this
Check CPU Temperature ${host} ${account} ${pwd}
END
Then you would be able to issue just one command with no need to specify any variables on the command line. It scales better if you have a lot of test data.
Another way of doing this would be a data driven approach:
*** Test Cases ***
Check Temperature
[Template] Check CPU Temperature
host1 a secret
host2 a secret
host3 a secret
and similarly for other test cases. You'd also need to change your keywords such as Check CPU Temperature so they accept parameters for a host, account, and login.
This approach is perhaps a little bit straighforward than the previous one, but you keep test data hard-coded in your test (.robot) files, which I personally don't like.
*** 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 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.
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.