V3 Listener Errors - takes 2 positional arguments but 3 were given
I have noticed that V3 listeners generate a lot of errors for methods that aren't even in the listener file, the errors all have this message:
[ ERROR ] Calling method '
' of listener ' ' failed: TypeError: SuiteVisitor. () takes 2 positional arguments but 3 were given
This Issue applies to Robot Framework 7.0 and 7.0.1, and also earlier versions (don't remember which ones)
I have created an example to you can reproduce this issue (feel free to use it as a test case):
mylistener.py:
from robot.api import SuiteVisitor
from robot.libraries.BuiltIn import BuiltIn
class mylistener(SuiteVisitor):
ROBOT_LISTENER_API_VERSION = 3
def end_test(self, test, result):
print(test.name)
print(test.parent.metadata)
myrobot.robot:
*** Test Cases ***
Demo Test Case
Demo Keyword
Demo If
Demo For Loop
Demo While Loop
*** Keywords ***
Demo Keyword
No Operation
Demo If
VAR ${a} aaa
IF '${a}' == 'aaa'
Log ${a}
END
Demo For Loop
FOR ${i} IN RANGE 3
Log ${i}
END
Demo While Loop
VAR ${i} 0
WHILE ${i} < 3
${i}= Evaluate ${i} + 1
END
Command to reproduce:
robot --listener mylistener.py myrobot.robot
Errors this produces in the log.html file (and on the console):
20240625 13:26:25.200 ERROR Calling method 'start_suite' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_suite() takes 2 positional arguments but 3 were given 20240625 13:26:25.201 ERROR Calling method 'start_test' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_test() takes 2 positional arguments but 3 were given 20240625 13:26:25.201 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.202 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.202 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.203 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.203 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.203 ERROR Calling method 'start_var' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_var() takes 2 positional arguments but 3 were given 20240625 13:26:25.203 ERROR Calling method 'end_var' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_var() takes 2 positional arguments but 3 were given 20240625 13:26:25.204 ERROR Calling method 'start_if' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_if() takes 2 positional arguments but 3 were given 20240625 13:26:25.204 ERROR Calling method 'start_if_branch' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_if_branch() takes 2 positional arguments but 3 were given 20240625 13:26:25.204 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.204 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.205 ERROR Calling method 'end_if_branch' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_if_branch() takes 2 positional arguments but 3 were given 20240625 13:26:25.205 ERROR Calling method 'end_if' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_if() takes 2 positional arguments but 3 were given 20240625 13:26:25.205 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.205 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.206 ERROR Calling method 'start_for' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_for() takes 2 positional arguments but 3 were given 20240625 13:26:25.206 ERROR Calling method 'start_for_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_for_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.206 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.207 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.207 ERROR Calling method 'end_for_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_for_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.207 ERROR Calling method 'start_for_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_for_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.207 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.208 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.208 ERROR Calling method 'end_for_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_for_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.208 ERROR Calling method 'start_for_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_for_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.208 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.209 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.209 ERROR Calling method 'end_for_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_for_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.209 ERROR Calling method 'end_for' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_for() takes 2 positional arguments but 3 were given 20240625 13:26:25.209 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.210 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.210 ERROR Calling method 'start_var' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_var() takes 2 positional arguments but 3 were given 20240625 13:26:25.210 ERROR Calling method 'end_var' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_var() takes 2 positional arguments but 3 were given 20240625 13:26:25.210 ERROR Calling method 'start_while' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_while() takes 2 positional arguments but 3 were given 20240625 13:26:25.211 ERROR Calling method 'start_while_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_while_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.211 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.211 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.211 ERROR Calling method 'end_while_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_while_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.212 ERROR Calling method 'start_while_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_while_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.212 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.212 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.212 ERROR Calling method 'end_while_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_while_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.213 ERROR Calling method 'start_while_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_while_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.213 ERROR Calling method 'start_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.start_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.213 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.214 ERROR Calling method 'end_while_iteration' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_while_iteration() takes 2 positional arguments but 3 were given 20240625 13:26:25.214 ERROR Calling method 'end_while' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_while() takes 2 positional arguments but 3 were given 20240625 13:26:25.214 ERROR Calling method 'end_keyword' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_keyword() takes 2 positional arguments but 3 were given 20240625 13:26:25.215 ERROR Calling method 'end_suite' of listener '/home/dave/Documents/tmp/listener_errors/mylistener.py' failed: TypeError: SuiteVisitor.end_suite() takes 2 positional arguments but 3 were given
Expected result: This should no produce any errors
Additional info for assessing severity:
- test cases are not impacted (only the ugly errors in the log)
- listener functions defined in the listener file work as expected
Workaround: for each affected function create a function in the listener file like the ones below:
def end_suite(self, suite, result):
pass
def start_suite(self, suite, result):
pass
def start_test(self, test, result):
pass
def start_keyword(self, data, result):
pass
def end_keyword(self, data, result):
pass
Alternate Workaround:
Change mylistener.py to:
from robot.libraries.BuiltIn import BuiltIn
class mylistener:
ROBOT_LISTENER_API_VERSION = 3
def end_test(self, test, result):
print(test.name)
print(test.parent.metadata)
The problem is that your original listener implements the SuiteVisitor interface but the listener interface isn't compatible with it. The former is meant for working either with data or result suites while the latter gets both and thus their start_xxx and end_xxx method signatures are different. The latter interface also has some additional methods that the former doesn't.
There being many similar interfaces can certainly be confusing. If you have ideas how to enhance the documentation, let us know. We could also consider publishing an adapter that allows using an existing visitor as a listener. We already use one non-generic adapter internally.
Ah I see where I went wrong now, I followed this example in the documentation: https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#example-select-every-xth-test
I didn't realize the difference between prerunmodifier and listeners. My eventual fix was to remove the SuiteVisitor as I didn't need it.
Thanks @pekkaklarck for you explanation, maybe there could be a mention in the tip section that while prerunmodifier and listeners look similar they are different, maybe even have a section somewhere explaining the differences, but I don't see this as urgent, not sure how many people will trip on this.