I have to convert following robot framework keyword in to python code. Can you please help me out.
Robot framework sample keyword:
*variables*
${locator} xpath=(//div[#it="testID"])[2]
*keyword*
sample keyword ${count} Get Element Count ${locator}
In python file. I used the following command
from robot.libraries.BuiltIn import BuiltIn
def _helper keyword(locator):
count=BuiltIn.run_keyword(get_element_count,locator)
When I executed it, I received the following error message: NameError: name 'get_element_count' is not defined.
First, no need the xpath= in your xpath, simply use:
*variables*
${locator} | (//div[#it="testID"])[2]
Secondly, get_element_count is a keyword come from SeleniumLibrary, not Builtin. Therefore, you need to import SeleniumLibrary to call it:
def get_element_count(locator):
context = BuiltIn().get_library_instance('SeleniumLibrary')
return context.get_element_count(locator)
The method get_element_count is actually from the SeleniumLibrary; for its call to fail like this, it probably means you don't have it imported in the context you're running your function (e.g. the suite this function is called doesn't have Library SeleniumLibrary in it, or in any of the resources it imports).
Once you resolve that, there's a slightly better way to call its methods - instead of going through run_keyword, you can use get_library_instance() and directly call its keywords:
se_lib = BuiltIn().get_library_instance('SeleniumLibrary')
cnt = se_lib.get_element_count(locator)
For this to work though, the library obviously needs to be imported - to have an instance to get.
P.S. Don't use "count" for a variable name - it's a python's builtin function you've just overridden - hidden bugs downstream ;)
Related
I start with the assumption that I have already looked at many other posts related to the "builtin_function_or_method" error, but I have not found a solution to my problem. I really hope that someone has a moment to read because I write this post out of exhaustion.
To summarize: the following piece of code invokes the "get_valid_locations_" function
valid_locations = eval.get_valid_locations_(board)
The method I call is a function of the Evaluate class that I have previously imported in this way (I attach both how I imported the file and how I instantiated the object)
from Utilities import evaluate
eval = evaluate.Evaluate()
While the function is as follows
def get_valid_locations_(self, board):
valid_locations = []
for col in range(NUMS_COL):
if eval.is_valid_location(board, col):
valid_locations.append(col)
return valid_locations
I cannot understand what generates the error. It seems to me that the assignment and the way in which I import the class is correct, also because in the Evaluate class there are other functions that do not generate errors. So the problem I think is restricted to either the function or how it is invoked. Unless the Python compiler sees the method. I also tried to add the _ to the end of the function name but nothing.
I hope someone can help me or have some advice on how to better structure the files for projects. Thanks a lot in advance and have a nice day.
In this line that's failing:
valid_locations = eval.get_valid_locations_(board)
It sees eval as the standard Python builtin function eval. Wherever you defined it like this:
eval = evaluate.Evaluate()
The first line is not seeing that definition.
First of all, choose a different name that isn't a Python builtin to reduce confusion.
Then make sure that your use of the object eval has the correct value. If you defined it globally in a module, then from some_module import eval. Or you could pass it as an argument to a function where eval.get_valid_locations_(board) is called.
Your definition of get_valid_locations_ has a similar problem where it calls eval.is_valid_location(board, col). If get_valid_locations_ and is_valid_location are both methods of the class Evaluate, then you should call self.is_valid_location instead. Not all instances of Evaluate should necessarily be called eval, nor should they have to be defined in the same file as the class.
you created an eval object, and then trying to call get_valid_locations_ function on it.
valid_locations = eval.get_valid_locations_(board)
this is what generates the error. eval object has no get_valid_locations_ function.
I am using Robot Framework and Appium to automate an Android native app. We have moved to espresso driver for running these tests and the elements need to be identified using the view-tag locator. However, Appium Robot library does not have support for this locator strategy.
I have written the custom keyword below
from robot.libraries.BuiltIn import BuiltIn
from robot.api.deco import keyword
#keyword(name='Find by ViewTag')
def by_viewtag(tagname):
"""Provides support to find elements using view tag for Espresso driver on Android"""
appiumlib = BuiltIn().get_library_instance('AppiumLibrary')
driver = appiumlib._current_application()
el = driver.find_element_by_android_viewtag(tagname)
print(el)
return el
and I am using it in my page file to find the object like this:
*** Settings ***
Library ../../../../Resources/Utils/find_elements_utils.py
Library BuiltIn
Library AppiumLibrary
Resource ../../../../Resources/Utils/helpers.robot
*** Variables ***
${loginBtn} = id=btn_sign_in
${signUpEmail}= Call Method Find by ViewTag
However, running this throws the following error
Element locator 'Call Method Find by ViewTag' did not match any elements after 20 seconds
Robot framework thinks I am passing an element locator when I am trying to call a keyword to find the locator. Can someone please help me with this? Is there any additional function I need to write to make this happen?
Please help!
The *** Variables *** table can only define static strings, it can't call other keywords. You are defining ${signUpEmail} as the literal string "Call Method Find by ViewTag" (minus the quotes). Anywhere you use it, that full string will be what is passed to a keyword.
If you want to call your Find by ViewTag keyword, you don't need to use Call Method. It's a normal keyword so you can call it in a normal way. For example:
${result}= Find By ViewTag a_view_tag
I solved this problem by extending the Appium library to support the view-tag strategy.
Along with the function I also needed to update the strategies object in the constructor of Appium Library.
def __init__(self):
"""Initialize extended locators."""
ElementFinder.__init__(self)
strategies = {
'viewtag': self._by_viewtag,
}
self._strategies.update(strategies)
I'm trying to figure out the arguments of a method retrieved from a module.
I found an inspect module with a handy function, getargspec.
It works for a function that I define, but won't work for functions from an imported module.
import math, inspect
def foobar(a,b=11): pass
inspect.getargspec(foobar) # this works
inspect.getargspec(math.sin) # this doesn't
I'll get an error like this:
File "C:\...\Python 2.5\Lib\inspect.py", line 743, in getargspec
raise TypeError('arg is not a Python function')
TypeError: arg is not a Python function
Is inspect.getargspec designed only for local functions or am I doing something wrong?
It is impossible to get this kind of information for a function that is implemented in C instead of Python.
The reason for this is that there is no way to find out what arguments the method accepts except by parsing the (free-form) docstring since arguments are passed in a (somewhat) getarg-like way - i.e. it's impossible to find out what arguments it accepts without actually executing the function.
You can get the doc string for such functions/methods which nearly always contains the same type of information as getargspec. (I.e. param names, no. of params, optional ones, default values).
In your example
import math
math.sin.__doc__
Gives
"sin(x)
Return the sine of x (measured in radians)"
Unfortunately there are several different standards in operation. See What is the standard Python docstring format?
You could detect which of the standards is in use, and then grab the info that way. From the above link it looks like pyment could be helpful in doing just that.
I want to create a python library with a 0 argument function that my custom Robot Framework keywords can call. It needs to know the absolute path of the file where the keyword is defined, and the name of the keyword. I know how to do something similar with test cases using the robot.libraries.BuiltIn library and the ${SUITE_SOURCE} and ${TEST NAME} variables, but I can't find anything similar for custom keywords. I don't care how complicated the answer is, maybe I have to dig into the guts of Robot Framework's internal classes and access that data somehow. Is there any way to do this?
Thanks to janne I was able to find the solution.
from robot.running.context import EXECUTION_CONTEXTS
def resource_locator():
name = EXECUTION_CONTEXTS.current.keywords[-1].name
libname = EXECUTION_CONTEXTS.current.get_handler(name).libname
resources = EXECUTION_CONTEXTS.current.namespace._kw_store.resources
path = ""
for key in resources._keys:
if resources[key].name == libname:
path = key
break
return {'name': name, 'path': path}
EXECUTION_CONTEXTS.current.keywords is the stack of keywords called, with the earliest first and the most recent last, so EXECUTION_CONTEXTS.current.keywords[-1] gets the last keyword, which is the keyword that called this function.
EXECUTION_CONTEXTS.current.get_handler(name).libname gets the name of the library in which the keyword name is defined. In the case of user defined keywords, it is the filename (not the full path) minus the extension.
EXECUTION_CONTEXTS.current.namespace._kw_store.resources is a dictionary of all included resources, where the key is the absolute path. Because the file path is the key, I have to search for the key such that the value's name is the name of the resource in which the keyword is defined (libname)
I took a relatively quick look through the sources, and it seems that the execution context does have any reference to currently executing keyword. So, the only way I can think of resolving this is:
Your library needs also to be a listener, since listeners get events when a keyword is started
You need to go through robot.libraries.BuiltIn.EXECUTION_CONTEXT._kw_store.resources to find out which resource file contains the keyword currently executing.
I did not do a POC, so I am not sure whether this actually doable, bu that's the solution that comes to my mind currently.
I'm writing an interpreter for an old in-game scripting language, and so need to compile dictionary that has the name of the command from the language matched up against the symbol for that function.
Now, I've already figured out here: How to call a function based on list entry?
...That you can call functions this way, and I know that you can use dir to get a list of strings of all functions in a module. I've been able to get this list, and using a regex, removed the built-in commands and anything else I don't actually want the script to be able to call. The goal is to sandbox here. :)
Now that I have the list of items that are defined in the module, I need to get the symbol for each definition.
For a more visual representation, this is the test module I want to get the symbol for:
def notify(stack,mufenv):
print stack[-1]
It's pulled in via an init script, and I am able to get the notify function's name in a list using:
import mufprims
import re
moddefs=dir(mufprims)
primsfilter=re.compile('__.+__')
primslist=[ 'mufprims.' + x for x in dir(mufprims) if not primsfilter.match(x) ]
print primslist
This returns:
['mufprims.notify']
...which is the exact name of the function I wish to find the symbol for.
I read over http://docs.python.org/library/symtable.html here, but I'm not sure I understand it. I think this is the key to what I want, but I didn't see an example that I could understand. Any ideas how I would get the symbol for the functions I've pulled from the list?
You want to get the function from the mufprims module by using getattr and the function name. Like so:
primslist=[getattr(mufprims, x) for x in dir(mufprims) if not primsfilter.match(x) ]
I thought I might add another possible suggestion for retrieving the functions of an object:
import inspect
# example using os.path
import os.path
results = inspect.getmembers(os.path, inspect.isroutine)
print results
# truncated result
[...,
('splitdrive', <function splitdrive at 0x1002bcb18>),
('splitext', <function splitext at 0x1002bcb90>),
('walk', <function walk at 0x1002bda28>)]
Using dir on the object would essentially give you every member of that object, including non-callable attributes, etc. You could use the inspect module to get a more controlled return type.