lczub / TestLink-API-Python-client

A Python client to use the TestLink API
104 stars 63 forks source link

Hang on when run in pytest #157

Closed derentw closed 1 year ago

derentw commented 1 year ago

I use TestLink-API-Python-client to integrate pytest and TestLink, and my pytest run on docker. Sometime it hang on, I only can stop docker container to cancel my test. It look like hang on socket receive data.

I got some information from gdb.

gdb /usr/bin/python3 -p <pid>
....
(gdb) py-bt
Traceback (most recent call first):
  File "/usr/lib/python3.8/socket.py", line 669, in readinto
    return self._sock.recv_into(b)
  File "/usr/lib/python3.8/http/client.py", line 277, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/usr/lib/python3.8/http/client.py", line 316, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python3.8/http/client.py", line 1604, in getresponse
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1166, in single_request
    resp = http_conn.getresponse()
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1153, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 2218, in __request
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1109, in __call__
    return self.__send(self.__name, args)
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkapigeneric.py", line 2057, in _callServer
Python Exception <class 'UnicodeDecodeError'> 'ascii' codec can't decode byte 0xc2 in position 6878: ordinal not in range(128): 
Error occurred in Python: 'ascii' codec can't decode byte 0xc2 in position 6878: ordinal not in range(128)

(gdb) py-list
 664            self._checkReadable()
 665            if self._timeout_occurred:
 666                raise OSError("cannot read from timed out object")
 667            while True:
 668                try:
>669                    return self._sock.recv_into(b)
 670                except timeout:
 671                    self._timeout_occurred = True
 672                    raise
 673                except error as e:
 674                    if e.args[0] in _blocking_errnos:
lczub commented 1 year ago

Helle derentw,

Unclear what happens, maybe the data section, exchanged between testlink and client includes characters, which the text encoding could not handle.

How to check original exchange xml data describes, how you can extend for debugging the logging. Maybe this helps to understands, what kind of data are making the trouble.

This can produce hugh output, so maybe as first step you should try to identify the steps, which provokes this situations.

Hope this is a starting point to analyse this

Regards Luiko

Regards Luiko

derentw commented 1 year ago

Hi lczub,

Thanks your reply. On the same steps, it is not happened always. I already add verbose=True. If it happen again, I will provide the information.

derentw commented 1 year ago

Hi lczub,

When API success, I can saw the following message.

send: b'POST /lib/api/xmlrpc/v1/xmlrpc.php HTTP/1.1\r\nHost: <myhost>:8081\r\nAccept-Encoding: gzip\r\nContent-Type: text/xml\r\nUser-Agent: Python-xmlrpc/3.8\r\nContent-Length: 353\r\n\r\n'
send: b"<?xml version='1.0'?>\n<methodCall>\n<methodName>tl.getBuildsForTestPlan</methodName>\n<params>\n<param>\n<value><struct>\n<member>\n<name>testplanid</name>\n<value><string>39102</string></value>\n</member>\n<member>\n<name>devKey</name>\n<value><string>xxxxxxx</string></value>\n</member>\n</struct></value>\n</param>\n</params>\n</methodCall>\n"
...

But, when it hang on, there is no message output.... If you need more information, please tell me the steps. Is there any timeout we can set?

Currently, my work run solution is use multiprocessing to handle timeout and retry. I will let you know it is work or not.

lczub commented 1 year ago

Hello derentw, I tried, what happens when server is not reachable and verbose enabled. In this case, also no send information are logged, but resulting connection errors, what you do not get.

ConnectionRefusedError: [WinError 10061] Es konnte keine Verbindung hergestellt werden, da der Zielcomputer die Verbindung verweigerte

During handling of the above exception, another exception occurred:

testlink.testlinkerrors.TLConnectionError: problems connecting the TestLink Server http://localhost:8085/lib/api/xmlrpc/v1/xmlrpc.php
[WinError 10061] Es konnte keine Verbindung hergestellt werden, da der Zielcomputer die Verbindung verweigerte

I have no idea what happens, maybe another solution for debugging would be to disable error handling in TestlinkAPIGeneric._callServer()

Or to check if a different xmlrpc.client initialisation helps in TestlinkAPIGeneric._init()

        self.server = xmlrpc_client.ServerProxy(server_url, transport, encoding,
                                       verbose, allow_none, use_datetime, 
                                       context=context)

But I haven't found any timeout settings in related python doc module xmlrpc.client

Sorry Luiko

derentw commented 1 year ago

Hi lczub,

Currently, my work run solution is
use multiprocessing to handle timeout and retry.
I will let you know it is work or not.

In general case, it work well. But when test case execute long time, I got the following exception.

2023/02/05 18:00:39.924 [E]      my_testlink.py:398  Traceback (most recent call last):
  File "/home/tester/my_module/my_testlink.py", line 385, in _update_testcase_result
    ret = self.tlc.reportTCResult(testplanid=self.data['testplanid'],
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkdecorators.py", line 112, in wrapperAddDevKey
    return methodAPI(self, *argsPositional, **argsOptional)
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkdecorators.py", line 99, in wrapperWithArgs
    return self.callServerWithPosArgs(methodAPI.__name__,
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkapigeneric.py", line 1582, in callServerWithPosArgs
    response = self._callServer(methodNameAPI, argsOptional)
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkapigeneric.py", line 2057, in _callServer
    response = getattr(self.server.tl, methodNameAPI)(argsAPI)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1109, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1450, in __request
    response = self.__transport.request(
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1153, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1169, in single_request
    return self.parse_response(resp)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1335, in parse_response
    p.feed(data)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 438, in feed
    self._parser.Parse(data, 0)
xml.parsers.expat.ExpatError: junk after document element: line 1, column 91

I tried to add self.tlc = testlink.TestlinkAPIClient(self.testlink_url, self.testlink_access_key, verbose=True) before _update_testcase_result() and still got the same exception.

My test case run for 6.4 hours.

Do you have any idea on it?

lczub commented 1 year ago

Sorry derentw,

I have no glue, but maybe you should split your workflow between reading test cases, executing test cases and reporting test case results. It sounds, that you tries to open the hole time between reading and reporting the connection. Splitting thisinto separate actions / communications may help to prevent running into the timeouts.

Luiko

derentw commented 1 year ago

Hi lczub,

2023/02/05 18:00:39.924 [E]      my_testlink.py:398  Traceback (most recent call last):
  File "/home/tester/my_module/my_testlink.py", line 385, in _update_testcase_result
    ret = self.tlc.reportTCResult(testplanid=self.data['testplanid'],
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkdecorators.py", line 112, in wrapperAddDevKey
    return methodAPI(self, *argsPositional, **argsOptional)
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkdecorators.py", line 99, in wrapperWithArgs
    return self.callServerWithPosArgs(methodAPI.__name__,
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkapigeneric.py", line 1582, in callServerWithPosArgs
    response = self._callServer(methodNameAPI, argsOptional)
  File "/usr/local/lib/python3.8/dist-packages/testlink/testlinkapigeneric.py", line 2057, in _callServer
    response = getattr(self.server.tl, methodNameAPI)(argsAPI)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1109, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1450, in __request
    response = self.__transport.request(
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1153, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1169, in single_request
    return self.parse_response(resp)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 1335, in parse_response
    p.feed(data)
  File "/usr/lib/python3.8/xmlrpc/client.py", line 438, in feed
    self._parser.Parse(data, 0)
xml.parsers.expat.ExpatError: junk after document element: line 1, column 91

About this problem, I assign execution_duration=10062.733440229.

I got the error message from userlog0.log.

errormsg:Out of range value for column 'execution_duration' at row 1 

The root case is TestLink database table executions field execution_duration type is decimal(6,2) After doing this, the fail fixed.

ALTER TABLE executions MODIFY COLUMN execution_duration decimal(15,2) ;