I'm new to robot framework, I have a python script that I want to run in robot framework but it's not running properly, it fails and the output is empty of the script(the error: '' does not contain 'hello')
the robot framework file:
*** Settings ***
Library OperatingSystem
Library Process
*** Test Cases ***
Simple pyhton example
${result} = Run Process python3 hello.py -c arg1 -b arg2
Log ${result.stdout}
Should Contain ${result.stdout} hello
the py file:
import sys
print("This is the name of the script:", sys.argv[0])
print("Number of arguments:", len(sys.argv))
print("The arguments are:", str(sys.argv))
print("hello world")
First of all your hello.py file needs to contain a function (or a class with methods). Not sure what you want to do with the specific arguments, but the content could look like this:
def hello_world(name, friend):
return "hello " + name + " and " + friend
Now you may import it as a library into your robot file and call the function:
*** Settings ***
Library hello.py
*** Test Cases ***
Simple Pyhton Example
${result} Hello World bitrex superman
Log ${result}
Should Contain ${result} hello
More information: https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#creating-test-libraries
The requirement is to run a Robot keyword which has named arg as dictionary, from PYTHON
But when we call like below, what i expect is a dictionary for arg1 and a string 'hello' in arg2, when calling "Test KW", but i get is, whole dictionary in arg1, and arg2 as empty
Need your help. Below is the minimal working code
cat testcase.robot
*** Settings ***
Library /homes/user/importresource.py
*** Test Cases ***
TC
custom keyword
cat test.robot
*** Keywords ***
Test KW
[Arguments] ${arg1}= ${arg2}=
${newvr}= set variable ${arg1}
${type value}= Evaluate type($arg1)
Log To Console ${type value}
Log to console ${arg2}
:FOR ${key} IN #{arg1.keys()}
\ Set To Dictionary ${args}
... ${key}=${arg1["${key}"]}
cat importresource.py
from robot.libraries.BuiltIn import BuiltIn
class importresource(object):
ROBOT_LISTENER_API_VERSION = 3
ROBOT_LIBRARY_SCOPE = 'TEST SUITE'
def __init__(self):
pass
def custom_keyword(self):
BuiltIn().import_resource('/homes/user/test.robot')
args = {'arg1':{'key':'value'},'arg2':'hello'}
BuiltIn().run_keyword('Test KW',args)
I am trying to implement hostname like module and my target machine in an amazon-ec2. But When I am running the script its giving me below error:
[ansible-user#ansible-master ~]$ ansible node1 -m edit_hostname.py -a node2
ERROR! this task 'edit_hostname.py' has extra params, which is only allowed in the following modules: meta, group_by, add_host, include_tasks, import_role, raw, set_fact, command, win_shell, import_tasks, script, shell, include_vars, include_role, include, win_command
My module is like this:
#!/usr/bin/python
from ansible.module_utils.basic import *
try:
import json
except ImportError:
import simplejson as json
def write_to_file(module, hostname, hostname_file):
try:
with open(hostname_file, 'w+') as f:
try:
f.write("%s\n" %hostname)
finally:
f.close()
except Exception:
err = get_exception()
module.fail_json(msg="failed to write to the /etc/hostname file")
def main():
hostname_file = '/etc/hostname'
module = AnsibleModule(argument_spec=dict(name=dict(required=True, type=str)))
name = module.params['name']
write_to _file(module, name, hostname_file)
module.exit_json(changed=True, meta=name)
if __name__ == "__main__":
main()
I don't know where I am making the mistake. Any help will be greatly appreciated. Thank you.
When developing a new module, I would recommend to use the boilerplate described in the documentation. This also shows that you'll need to use AnsibleModule to define your arguments.
In your main, you should add something like the following:
def main():
# define available arguments/parameters a user can pass to the module
module_args = dict(
name=dict(type='str', required=True)
)
# seed the result dict in the object
# we primarily care about changed and state
# change is if this module effectively modified the target
# state will include any data that you want your module to pass back
# for consumption, for example, in a subsequent task
result = dict(
changed=False,
original_hostname='',
hostname=''
)
module = AnsibleModule(
argument_spec=module_args
supports_check_mode=False
)
# manipulate or modify the state as needed (this is going to be the
# part where your module will do what it needs to do)
result['original_hostname'] = module.params['name']
result['hostname'] = 'goodbye'
# use whatever logic you need to determine whether or not this module
# made any modifications to your target
result['changed'] = True
# in the event of a successful module execution, you will want to
# simple AnsibleModule.exit_json(), passing the key/value results
module.exit_json(**result)
Then, you can call the module like so:
ansible node1 -m mymodule.py -a "name=myname"
ERROR! this task 'edit_hostname.py' has extra params, which is only allowed in the following modules: meta, group_by, add_host, include_tasks, import_role, raw, set_fact, command, win_shell, import_tasks, script, shell, include_vars, include_role, include, win_command
As explained by your error message, an anonymous default parameter is only supported by a limited number of modules. In your custom module, the paramter you created is called name. Moreover, you should not include the .py extension in the module name. You have to call your module like so as an ad-hoc command:
$ ansible node1 -m edit_hostname -a name=node2
I did not test your module code so you may have further errors to fix.
Meanwhile, I still strongly suggest you use the default boilerplate from the ansible documentation as proposed in #Simon's answer.
I need to call a python method from robot framework.
def getRandomEmails():
a = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(16))
email = a + '#' + 'gmail.com'
return email
This function is written in EnvVar.py file
How can I use the returned value from this method in Robot Framework. I have tried almost many ways, but nothing works.
please help.
Using Evaluate
Exactly how to do it on your system depends on how your files are organized and how you've configured robot, but in short, Evaluate from the BuiltIn library is the keyword that lets you run arbitrary methods from importable modules.
Example:
For this example I've created a file named EnvVar.py in the current working directory. It has the following contents:
import random, string
def getRandomEmails():
a = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(16))
email = a + '#' + 'gmail.com'
return email
I then created a file named "example.robot" that looks like this:
*** Test cases ***
Example
${result}= evaluate EnvVar.getRandomEmails() modules=EnvVar
log result: ${result}
Since the current working directory isn't by default on my PYTHONPATH (your setup may be different), I have to tell robot to include the current directory on PYTHONPATH. I can do that with the --pythonpath option.
$ robot --pythonpath . example.robot
Creating a keyword library
Another solution is to create your own keyword library that exposes this function as a keyword.
For example, assuming you can import EnvVar, you could write a library named "Util" (Util.py) that creates a keyword that calls this function:
# Util.py
import EnvVar
def get_random_emails():
return EnvVar.getRandomEmails()
You would then use this in a test like any other keyword library:
*** Settings ***
Library Util.py
*** Test Cases ***
Example
${result}= Get Random Emails
log result: ${result}
If it's the only method you want to add than you could add keyword decorator i.e:
from robot.api.deco import keyword
#keyword
def getRandomEmails():
a = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(16))
email = a + '#' + 'gmail.com'
return email
And obviously you should import in settings as library
In robot framework how do you to create object of class and call the methods in corresponding class? This is the code snippet.
*** Settings ***
Documentation A resource file with reusable keywords and variables.
... Use keywords in this file in testcases directory.
Library /home/kirti/src/Helper/utilities.py
Library /home/kirti/src/Helper/config_parser.py
#Library /home/kirti/qa/src/executor/cleanup.CleanUp
Library /home/kirti/qa/src/executor/cleanup.py
*** Variables ***
${RESULT} 0
*** Keywords ***
Read Json Config Values
Log To Console "Setting up the config values globally"
config_parser.Json Config Parser
Import Variables /home/kirti/src/Helper/variables.py
Log Variables INFO
Check Machines Reachability
utilities.Check All Machines Status
Check SNMP Counter
utilities.Get Snmp 192.178.1.2 PPSessionCount
Call Clean Up
#${cleanupobj}= cleanup.create cleanup
#${name}= ${cleanupobj.cc()}
Import Library /home/kirti/src/executor/cleanup.py
${cmp}= Get library instance CleanUp
Log To Console ${cmp}.__class__.__name__
#${name}= Call method ${cmp} Create cleanup
${name}= Call method ${cmp} cc
#${name}= Call method ${cleanupobj} env cleanup
#Log To Console "${name}"
#Log Variables INFO
utilities.Check All Machines Status
Here is a way you can achieve the desired result.
Lets take example of demo.py which have class Sample
Sample class has init ,getting_path() as methods
class Sample(object):
def __init__(self,path,device):
self.device=device
self.path = path
def getting_path(self):
return self.path
Lets use these methods in Robotfile
*** Settings ***
#in the Library section you reference python class in below format
# (file.class_name) so file is demo.py and class is Sample
Library demo.Sample ${path} ${device} WITH NAME obj
#path and device are two arguments required by __init__,'obj' will be used to
#access the methods in python class
Library Collections
*** Variables ***
${path} c:
${device} samsung
*** Test Cases ***
Test
Test_python_class
*** Keywords ***
Test_python_class
#with obj you now call the method of python file
${result} = obj.getting_path
#if method need any argument , this can be passed like
#${result} = obj.getting_path ${arg1} ${arg2}
log to console ${result}
If you want to use a specific instance of a class you can use
${instance} = obj arg1
log to console ${instance.function(args)}