robotframework icon indicating copy to clipboard operation
robotframework copied to clipboard

V3 Listener Errors - takes 2 positional arguments but 3 were given

Open damies13 opened this issue 1 year ago • 2 comments

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

damies13 avatar Jun 25 '24 03:06 damies13

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

damies13 avatar Jun 25 '24 03:06 damies13

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)

damies13 avatar Jun 25 '24 04:06 damies13

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.

pekkaklarck avatar Jul 01 '24 10:07 pekkaklarck

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.

damies13 avatar Jul 04 '24 00:07 damies13