2

I am learning the dynamic library implementation in robot framework using python. In this process, I have created a new keyword using the dynamic library as explained in this link.

The source code is given below

import logging


class libdynamicsampl1:
    def get_keyword_names(self):
        return ["methOne", "methTwo"]

    def methOne(self):
        logging.info("called the methone")

    def methTwo(self, name):
        logging.info("called the methtwo with the arg as" + name)

    def run_keyword(self, name, args):
        print "Running keyword '%s' with arguments %s." % (name, args)
        methArgs = (self,) + (args)
        return getattr(self, name, methArgs)()

When i run this keyword from the robot file, like the code given below,

*** Test Cases ***
Log Dynamic Test Library
    Invoke dyn tests no arg
    Invoke dyn tests with arg

*** Keywords ***
Invoke dyn tests no arg
    meth one

Invoke dyn tests with arg
    meth two    "welcome to awesome robot framework"

There is an error like the below, the inference is that the methTwo takes "self" and "name", but using getattr(...) passes only the name I guess.

TypeError: methTwo() takes exactly 2 arguments (1 given)

Kindly help in fixing this issue or suggest the best practice / implementation on how to invoke the methods based on the input arguments. There is no sample from the robot framework site, hence any fix will be very helpful.

The below implementation in the run_keyword method works fine, but i feel that its not the best practice to implement in a production ready code base.

def run_keyword(self, name, args):
    print "Running keyword '%s' with arguments %s." % (name, args)
    if name == "methOne":
        return self.methOne()
    if name == "methTwo":
        return self.methTwo(args[0])
8
  • What are you trying to accomplish? Are you wanting "meth one" (with a single space) to call the methOne method? The code you posted doesn't give the error you say it does. It will give the error No keyword with name 'meth one' found.. Commented Mar 19, 2019 at 14:10
  • In your link you refer to the documentation of Robot Framework 2.8.7. Is this deliberate, or by accident? In the current version of Robot Framework the documenation on Dynamic Library is more extensive with examples. Commented Mar 19, 2019 at 15:07
  • @BryanOakley, I have the libdynamicsampl1.py invoked and tested in the robot file mentioned above. I am not sure on how to use the run_keyword implementation. Though the documentation gives a sample that prints out the name of the methods that are being invoked, there is no mention on how to invoke the method in the real time, meaning, we should invoke the method as robot framework has no way to identify which method we are actually invoking. How should the implementation be so that the methods are invoked. The documentation lacks the robot file consumption and real-time examples Commented Mar 20, 2019 at 5:04
  • @A.Kootstra, the documentation is really good, but there are snippets of code which is of no real use when we can't put together and make a full sample. Had the documentation covered various topics from a single code base and finally make a full-blown functional flow or test that can be used as a reference, it will be very helpful. Commented Mar 20, 2019 at 5:09
  • 1
    yes, that's what the documentation claims that we can invoke methods by cased characters or by a "_", so i wanted to try those. Commented Mar 20, 2019 at 14:07

1 Answer 1

2

using getattr(...) passes only the name I guess.

That depends on how you define "only the name". getattr will return the function, it knows nothing about function arguments. However, the function it returns will be a method on the object, so you don't have to worry about passing the self parameter.

Consider this code:

return getattr(self, name, methArgs)()

It is the same as this code (assuming name is a valid method name)

func = getattr(self, name, methArgs)
func()

Assuming for the moment that getAttr returns self.methTwo, the above code is identical to this:

self.methTwo()

Notice that in the above, your code is not passing any arguments. When used in getattr, that variable doensn't represent arguments, it represents a default method name in case the one requested doesn't exist. In other words, when name is valid, getattr will simply ignore methArgs.

Since one of your methods expect an argument (name ), you will get an error that it didn't receive all of the arguments that it expected. That is exactly what happened, apparently.

There are other problems with your example, so I can't be sure of the exact solution. It's not clear if you expect meth one in the test to call methOne, or if meth one or methOne is a typo.

Assuming you use the correct name in both places, you can directly convert the name to the method with getattr, similar to how you are doing it now. The difference is simply that you need to pass the arguments to the function rather than to getattr.

For example, given this robot code snippet:

Invoke dyn tests with arg
    methTwo    "welcome to awesome robot framework"

Here is how you would implement run_keyword in order for that robot code to run:

def run_keyword(self, name, args):
    print "Running keyword '%s' with arguments %s." % (name, args)
    func = getattr(self, name)
    return func(*args)
Sign up to request clarification or add additional context in comments.

1 Comment

using the func(*args) worked fine in the above approach. Thanks a lot for the clarification.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.