From 2a2d19f4ae08c19e3cca937b5e9bc786591a973b Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Wed, 1 Nov 2023 23:02:46 +0100 Subject: [PATCH 01/12] basic multiprocessing --- RobotFrameworkService/routers/robotframework.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index 08bac1b..b93f84b 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -9,11 +9,20 @@ import robot +import multiprocessing as mp + router = APIRouter( prefix="/robotframework", responses={404: {"description": "Not found: Webservice is either busy or requested endpoint is not supported."}}, ) +@router.get('/run/async/all', tags=["execution"]) +async def run_async(request: Request): + id = request.headers["request-id"] + p = mp.Process(target=_start_all_robot_tasks, args=[id]) + p.start() + return id + @router.get('/run/all', tags=["execution"]) async def run(request: Request): From 955aa94d7d479ecd08aa5fa567a8aadc1eacaf08 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Wed, 1 Nov 2023 23:49:42 +0100 Subject: [PATCH 02/12] generic run-robot funcs --- .../routers/robotframework.py | 62 ++++++++----------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index b93f84b..661420f 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -16,21 +16,12 @@ responses={404: {"description": "Not found: Webservice is either busy or requested endpoint is not supported."}}, ) -@router.get('/run/async/all', tags=["execution"]) -async def run_async(request: Request): - id = request.headers["request-id"] - p = mp.Process(target=_start_all_robot_tasks, args=[id]) +async def run_robot_in_brackground(func, args=[], kwargs={}): + p = mp.Process(target=func, args=args, kwargs=kwargs) p.start() - return id - -@router.get('/run/all', tags=["execution"]) -async def run(request: Request): - """ - Run all task available. - """ - id = request.headers["request-id"] - result: int = _start_all_robot_tasks(id) +async def run_robot(func, args=[], kwargs={}): + result: int = func(*args, **kwargs) if result == 0: result_page = 'PASS' result_page += f'

Go to log

' @@ -45,6 +36,23 @@ async def run(request: Request): return Response(content=result_page, media_type="text/html", status_code=status_code) +@router.get('/run/async/all', tags=["execution"]) +async def run_async(request: Request): + id = request.headers["request-id"] + await run_robot_in_brackground(func=_start_all_robot_tasks, args=[id]) + return id + + +@router.get('/run/all', tags=["execution"]) +async def run(request: Request): + """ + Run all task available. + """ + id = request.headers["request-id"] + response = await run_robot(func=_start_all_robot_tasks, args=[id]) + + return response + @router.get('/run/{task}', tags=["execution"]) async def run_task(task, request: Request): @@ -52,20 +60,9 @@ async def run_task(task, request: Request): Run a given task. """ id = request.headers["request-id"] - variables = RequestHelper.parse_variables_from_query(request) - result: int = _start_specific_robot_task(id, task, variables=variables) - if result == 0: - result_page = 'PASS' - result_page += f'

Go to log

' - - elif 250 >= result >= 1: - result_page = f'FAIL: {result} tasks failed' - result_page += f'

Go to log

' - - else: - result_page = f'FAIL: Errorcode {result}' - - return Response(content=result_page, media_type="text/html") + variables = RequestHelper.parse_variables_from_query(request) + response = await run_robot(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) + return response @router.get('/run/suite/{suite}', tags=["execution"]) async def run_suite(suite, request: Request): @@ -74,15 +71,8 @@ async def run_suite(suite, request: Request): """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) - result: int = _start_specific_robot_suite(id, suite, variables=variables) - if result == 0: - result_page = 'PASS' - elif 250 >= result >= 1: - result_page = f'FAIL: {result} tasks for suite {suite} failed' - else: - result_page = f'FAIL: Errorcode {result}' - result_page += f'

Go to log

' - return Response(content=result_page, media_type="text/html") + response = await run_robot(func=_start_specific_robot_suite, kwargs={'suite':suite, 'variables':variables}) + return response @router.get('/run_and_show/{task}', tags=["execution"], response_class=HTMLResponse) From 944281ef98ac873fbfd9e2bbd3c73f02633a6ab5 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:08:22 +0100 Subject: [PATCH 03/12] async robot calls --- .../routers/robotframework.py | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index 661420f..0c2ebf2 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -19,8 +19,9 @@ async def run_robot_in_brackground(func, args=[], kwargs={}): p = mp.Process(target=func, args=args, kwargs=kwargs) p.start() + return p -async def run_robot(func, args=[], kwargs={}): +async def run_robot_and_wait(func, args=[], kwargs={}): result: int = func(*args, **kwargs) if result == 0: result_page = 'PASS' @@ -36,24 +37,25 @@ async def run_robot(func, args=[], kwargs={}): return Response(content=result_page, media_type="text/html", status_code=status_code) -@router.get('/run/async/all', tags=["execution"]) -async def run_async(request: Request): - id = request.headers["request-id"] - await run_robot_in_brackground(func=_start_all_robot_tasks, args=[id]) - return id - @router.get('/run/all', tags=["execution"]) -async def run(request: Request): +async def run_all(request: Request): """ Run all task available. """ id = request.headers["request-id"] - response = await run_robot(func=_start_all_robot_tasks, args=[id]) + response = await run_robot_and_wait(func=_start_all_robot_tasks, args=[id]) return response +@router.get('/run/all/async', tags=["execution"]) +async def run_all_async(request: Request): + id = request.headers["request-id"] + await run_robot_in_brackground(func=_start_all_robot_tasks, args=[id]) + return id + + @router.get('/run/{task}', tags=["execution"]) async def run_task(task, request: Request): """ @@ -61,9 +63,20 @@ async def run_task(task, request: Request): """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) - response = await run_robot(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) + response = await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) return response + +@router.get('/run/{task}/async', tags=["execution"]) +async def run_task_async(task, request: Request): + """ + Run a given task. + """ + id = request.headers["request-id"] + variables = RequestHelper.parse_variables_from_query(request) + await run_robot_in_brackground(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) + return id + @router.get('/run/suite/{suite}', tags=["execution"]) async def run_suite(suite, request: Request): """ @@ -71,9 +84,19 @@ async def run_suite(suite, request: Request): """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) - response = await run_robot(func=_start_specific_robot_suite, kwargs={'suite':suite, 'variables':variables}) + response = await run_robot_and_wait(func=_start_specific_robot_suite, kwargs={'suite':suite, 'variables':variables}) return response +@router.get('/run/suite/{suite}/async', tags=["execution"]) +async def run_suite_async(suite, request: Request): + """ + Run a given suite. + """ + id = request.headers["request-id"] + variables = RequestHelper.parse_variables_from_query(request) + await run_robot_in_brackground(func=_start_specific_robot_suite, kwargs={'suite':suite, 'variables':variables}) + return id + @router.get('/run_and_show/{task}', tags=["execution"], response_class=HTMLResponse) async def start_robot_task_and_show_log(task: str, arguments: Request): From f254e86d5f62bf66ac8efdd8528f1fb31d6bb4e2 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:11:54 +0100 Subject: [PATCH 04/12] add documentation --- RobotFrameworkService/routers/robotframework.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index 0c2ebf2..b04e8e0 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -51,6 +51,9 @@ async def run_all(request: Request): @router.get('/run/all/async', tags=["execution"]) async def run_all_async(request: Request): + """ + Starts all Robot tasks. Returns execution id and continures to run Robot tasks in background. + """ id = request.headers["request-id"] await run_robot_in_brackground(func=_start_all_robot_tasks, args=[id]) return id @@ -70,7 +73,7 @@ async def run_task(task, request: Request): @router.get('/run/{task}/async', tags=["execution"]) async def run_task_async(task, request: Request): """ - Run a given task. + Start a given task. Returns execution id and continues to run Robot task in background. """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) @@ -90,7 +93,7 @@ async def run_suite(suite, request: Request): @router.get('/run/suite/{suite}/async', tags=["execution"]) async def run_suite_async(suite, request: Request): """ - Run a given suite. + Start a given suite. Returns execution id and continues to run Robot suite in background. """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) From bf1a379f277c5a8ee71bab529aac018389afacf6 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:22:21 +0100 Subject: [PATCH 05/12] more generic --- RobotFrameworkService/routers/robotframework.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index b04e8e0..e61ca32 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -22,6 +22,7 @@ async def run_robot_in_brackground(func, args=[], kwargs={}): return p async def run_robot_and_wait(func, args=[], kwargs={}): + # this is still blocking result: int = func(*args, **kwargs) if result == 0: result_page = 'PASS' @@ -107,7 +108,7 @@ async def start_robot_task_and_show_log(task: str, arguments: Request): Run a given task with variables and return log.html """ variables = RequestHelper.parse_variables_from_query(arguments) - _start_specific_robot_task(task, variables) + await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) return RedirectResponse(f"/logs/{task}/log.html") @@ -117,7 +118,7 @@ async def start_robot_task_and_show_report(task: str, arguments: Request): Run a given task with variables and return report.html """ variables = RequestHelper.parse_variables_from_query(arguments) - _start_specific_robot_task(task, variables) + await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) return RedirectResponse(f"/logs/{task}/report.html") From 44ceaf52727a470f9af11de6dd943fcc60561ebd Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:32:06 +0100 Subject: [PATCH 06/12] fix missing attribute --- RobotFrameworkService/routers/robotframework.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index e61ca32..5887ffe 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -103,12 +103,13 @@ async def run_suite_async(suite, request: Request): @router.get('/run_and_show/{task}', tags=["execution"], response_class=HTMLResponse) -async def start_robot_task_and_show_log(task: str, arguments: Request): +async def start_robot_task_and_show_log(task: str, request: Request): """ Run a given task with variables and return log.html """ - variables = RequestHelper.parse_variables_from_query(arguments) - await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) + id = request.headers["request-id"] + variables = RequestHelper.parse_variables_from_query(request) + await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'id':id, 'task':task, 'variables':variables}) return RedirectResponse(f"/logs/{task}/log.html") @@ -117,8 +118,9 @@ async def start_robot_task_and_show_report(task: str, arguments: Request): """ Run a given task with variables and return report.html """ + id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(arguments) - await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) + await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'id':id, 'task':task, 'variables':variables}) return RedirectResponse(f"/logs/{task}/report.html") From 93d5ceac13a0f9e6fd05e9beedac8f8808ac8364 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:34:27 +0100 Subject: [PATCH 07/12] fix --- RobotFrameworkService/routers/robotframework.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index 5887ffe..4a7b2e9 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -114,12 +114,12 @@ async def start_robot_task_and_show_log(task: str, request: Request): @router.get('/run_and_show_report/{task}', tags=["execution"], response_class=HTMLResponse) -async def start_robot_task_and_show_report(task: str, arguments: Request): +async def start_robot_task_and_show_report(task: str, request: Request): """ Run a given task with variables and return report.html """ id = request.headers["request-id"] - variables = RequestHelper.parse_variables_from_query(arguments) + variables = RequestHelper.parse_variables_from_query(request) await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'id':id, 'task':task, 'variables':variables}) return RedirectResponse(f"/logs/{task}/report.html") From 765bf6073bb0dd4eea55dd280005c851fef733ea Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:42:32 +0100 Subject: [PATCH 08/12] fix unittests --- RobotFrameworkService/routers/robotframework.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index 4a7b2e9..ee63ba0 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -67,7 +67,7 @@ async def run_task(task, request: Request): """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) - response = await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'task':task, 'variables':variables}) + response = await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'id': id, 'task':task, 'variables':variables}) return response @@ -88,7 +88,7 @@ async def run_suite(suite, request: Request): """ id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) - response = await run_robot_and_wait(func=_start_specific_robot_suite, kwargs={'suite':suite, 'variables':variables}) + response = await run_robot_and_wait(func=_start_specific_robot_suite, kwargs={'id': id, 'suite':suite, 'variables':variables}) return response @router.get('/run/suite/{suite}/async', tags=["execution"]) From 2095a94e884f0ad5d80ab75e86917567c368db67 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:43:18 +0100 Subject: [PATCH 09/12] scoped requirements --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements-dev.txt diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..7a074a5 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1 @@ +robotframework-tidy \ No newline at end of file From 1bcffbc85cf22667e33e0d22f48640d81d30de06 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:43:25 +0100 Subject: [PATCH 10/12] ammend --- requirements-test.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements-test.txt diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..7922838 --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1 @@ +httpx \ No newline at end of file From d953cc45ddfec283d55fd084061bd828d1171cd3 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:50:18 +0100 Subject: [PATCH 11/12] unittest: print error message --- tests/test_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_app.py b/tests/test_app.py index 616a462..f3e638c 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -49,7 +49,7 @@ def test_is_robotreport_available(self): def __get_robot_webservice(self,endpoint, expected_response_code=200): with TestClient(app) as client: response = client.get(endpoint) - self.assertEqual(expected_response_code, response.status_code) + self.assertEqual(expected_response_code, response.status_code, response.text) return response def __is_robot_passed(self, response, msg=None): From d7fc52dbf0c65a56976bb22878db20f457caecf0 Mon Sep 17 00:00:00 2001 From: Markus Stahl Date: Thu, 2 Nov 2023 00:54:24 +0100 Subject: [PATCH 12/12] fix report location --- RobotFrameworkService/routers/robotframework.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RobotFrameworkService/routers/robotframework.py b/RobotFrameworkService/routers/robotframework.py index ee63ba0..d1e78a1 100644 --- a/RobotFrameworkService/routers/robotframework.py +++ b/RobotFrameworkService/routers/robotframework.py @@ -110,7 +110,7 @@ async def start_robot_task_and_show_log(task: str, request: Request): id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'id':id, 'task':task, 'variables':variables}) - return RedirectResponse(f"/logs/{task}/log.html") + return RedirectResponse(f"/logs/{id}/log.html") @router.get('/run_and_show_report/{task}', tags=["execution"], response_class=HTMLResponse) @@ -121,7 +121,7 @@ async def start_robot_task_and_show_report(task: str, request: Request): id = request.headers["request-id"] variables = RequestHelper.parse_variables_from_query(request) await run_robot_and_wait(func=_start_specific_robot_task, kwargs={'id':id, 'task':task, 'variables':variables}) - return RedirectResponse(f"/logs/{task}/report.html") + return RedirectResponse(f"/logs/{id}/report.html") @router.get('/show_log/{executionid}', tags=["reporting"], response_class=HTMLResponse)