From c59eb5b46c15ce955eedfca5fe284fb6baa22f05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de>
Date: Mon, 6 Nov 2023 10:22:52 +0100
Subject: [PATCH] Add executions status to developer statistics

#62
---
 app/api/endpoints/workflow.py             | 12 ++--
 app/crud/crud_workflow.py                 |  4 +-
 app/schemas/workflow_execution.py         |  5 ++
 app/tests/api/test_workflow.py            | 14 ++--
 app/tests/api/test_workflow_execution.py  | 53 ++++++++-------
 app/tests/conftest.py                     | 22 +++++-
 app/tests/crud/test_workflow.py           | 72 ++++++++++----------
 app/tests/crud/test_workflow_execution.py | 82 ++++++++++++-----------
 8 files changed, 149 insertions(+), 115 deletions(-)

diff --git a/app/api/endpoints/workflow.py b/app/api/endpoints/workflow.py
index dbbfac0..52c29e9 100644
--- a/app/api/endpoints/workflow.py
+++ b/app/api/endpoints/workflow.py
@@ -199,11 +199,15 @@ async def get_developer_workflow_statistics(
     response: Response,
     current_user: CurrentUser,
     developer_id: Optional[str] = Query(
-        None, description="", examples=["28c5353b8bb34984a8bd4169ba94c606"], min_length=3, max_length=64
+        None,
+        description="Filter by the developer of the workflows",
+        examples=["28c5353b8bb34984a8bd4169ba94c606"],
+        min_length=3,
+        max_length=64,
     ),
-    workflow_ids: Optional[List[UUID]] = Query(None, alias="workflow_id"),
-    start: Optional[date] = Query(None),
-    end: Optional[date] = Query(None),
+    workflow_ids: Optional[List[UUID]] = Query(None, description="Filter by workflow IDs", alias="workflow_id"),
+    start: Optional[date] = Query(None, description="Filter by workflow executions after this date"),
+    end: Optional[date] = Query(None, description="Filter by workflow executions before this date"),
 ) -> List[AnonymizedWorkflowExecution]:
     """
     Get the workflow executions with meta information and anonymized user IDs.\n
diff --git a/app/crud/crud_workflow.py b/app/crud/crud_workflow.py
index c09e1a8..9b7a9f9 100644
--- a/app/crud/crud_workflow.py
+++ b/app/crud/crud_workflow.py
@@ -144,11 +144,12 @@ class CRUDWorkflow:
                     WorkflowVersion.git_commit_hash,
                     Workflow._workflow_id,
                     Workflow.developer_id,
+                    WorkflowExecution.status,
                 )
                 .select_from(WorkflowExecution)
                 .join(WorkflowVersion)
                 .join(Workflow)
-                .order_by("started_at")
+                .where(WorkflowExecution.end_time != None)  # noqa:E711
             )
             if developer_id:
                 span.set_attribute("developer_id", developer_id)
@@ -185,6 +186,7 @@ class CRUDWorkflow:
                     workflow_id=row._workflow_id,
                     developer_id=row.developer_id,
                     git_commit_hash=row.git_commit_hash,
+                    status=row.status,
                 )
                 for row in rows
             ]
diff --git a/app/schemas/workflow_execution.py b/app/schemas/workflow_execution.py
index e0a7d54..6a0e158 100644
--- a/app/schemas/workflow_execution.py
+++ b/app/schemas/workflow_execution.py
@@ -134,3 +134,8 @@ class AnonymizedWorkflowExecution(BaseModel):
     developer_id: str = Field(
         ..., description="ID of developer of the workflow", examples=["28c5353b8bb34984a8bd4169ba94c606"]
     )
+    status: WorkflowExecution.WorkflowExecutionStatus = Field(
+        ...,
+        description="End status of the workflow execution",
+        examples=[WorkflowExecution.WorkflowExecutionStatus.SUCCESS],
+    )
diff --git a/app/tests/api/test_workflow.py b/app/tests/api/test_workflow.py
index a9a7847..9b11e26 100644
--- a/app/tests/api/test_workflow.py
+++ b/app/tests/api/test_workflow.py
@@ -513,7 +513,7 @@ class TestWorkflowRoutesList(_TestWorkflowRoutes):
         client: AsyncClient,
         random_user: UserWithAuthHeader,
         random_workflow: WorkflowOut,
-        random_workflow_execution: WorkflowExecution,
+        random_completed_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for getting all workflow executions as workflow statistics.
@@ -526,7 +526,7 @@ class TestWorkflowRoutesList(_TestWorkflowRoutes):
             Random user for testing.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random workflow for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing
         """
         response = await client.get(
@@ -538,8 +538,8 @@ class TestWorkflowRoutesList(_TestWorkflowRoutes):
         assert len(executions) == 1
         execution = executions[0]
         assert execution["workflow_id"] == str(random_workflow.workflow_id)
-        assert execution["workflow_execution_id"] == str(random_workflow_execution.execution_id)
-        assert execution["git_commit_hash"] == random_workflow_execution.workflow_version_id
+        assert execution["workflow_execution_id"] == str(random_completed_workflow_execution.execution_id)
+        assert execution["git_commit_hash"] == random_completed_workflow_execution.workflow_version_id
 
 
 class TestWorkflowRoutesGet(_TestWorkflowRoutes):
@@ -594,10 +594,10 @@ class TestWorkflowRoutesGet(_TestWorkflowRoutes):
         client: AsyncClient,
         random_user: UserWithAuthHeader,
         random_workflow: WorkflowOut,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
-        Test for getting a non-existing workflow.
+        Test for getting the aggregated workflow statistics.
 
         Parameters
         ----------
@@ -607,7 +607,7 @@ class TestWorkflowRoutesGet(_TestWorkflowRoutes):
             Random user for testing.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random workflow for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing
         """
         response = await client.get(
diff --git a/app/tests/api/test_workflow_execution.py b/app/tests/api/test_workflow_execution.py
index e33c0e9..5539139 100644
--- a/app/tests/api/test_workflow_execution.py
+++ b/app/tests/api/test_workflow_execution.py
@@ -1010,7 +1010,7 @@ class TestWorkflowExecutionRoutesGet(_TestWorkflowExecutionRoutes):
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for getting a workflow execution.
@@ -1021,23 +1021,24 @@ class TestWorkflowExecutionRoutesGet(_TestWorkflowExecutionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         response = await client.get(
-            "/".join([self.base_path, str(random_workflow_execution.execution_id)]), headers=random_user.auth_headers
+            "/".join([self.base_path, str(random_running_workflow_execution.execution_id)]),
+            headers=random_user.auth_headers,
         )
         assert response.status_code == status.HTTP_200_OK
 
         execution = response.json()
-        assert execution["execution_id"] == str(random_workflow_execution.execution_id)
+        assert execution["execution_id"] == str(random_running_workflow_execution.execution_id)
 
     @pytest.mark.asyncio
     async def test_get_workflow_execution_params(
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for getting the parameters of a workflow execution.
@@ -1048,11 +1049,11 @@ class TestWorkflowExecutionRoutesGet(_TestWorkflowExecutionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         response = await client.get(
-            "/".join([self.base_path, str(random_workflow_execution.execution_id), "params"]),
+            "/".join([self.base_path, str(random_running_workflow_execution.execution_id), "params"]),
             headers=random_user.auth_headers,
         )
         assert response.status_code == status.HTTP_200_OK
@@ -1086,7 +1087,7 @@ class TestWorkflowExecutionRoutesList(_TestWorkflowExecutionRoutes):
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for listing all workflow executions.
@@ -1097,7 +1098,7 @@ class TestWorkflowExecutionRoutesList(_TestWorkflowExecutionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         response = await client.get(self.base_path, headers=random_user.auth_headers)
@@ -1109,7 +1110,7 @@ class TestWorkflowExecutionRoutesList(_TestWorkflowExecutionRoutes):
             sum(
                 1
                 for execution in executions
-                if execution["execution_id"] == str(random_workflow_execution.execution_id)
+                if execution["execution_id"] == str(random_running_workflow_execution.execution_id)
             )
             == 1
         )
@@ -1121,7 +1122,7 @@ class TestWorkflowExecutionRoutesDelete(_TestWorkflowExecutionRoutes):
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for deleting an unfinished workflow execution.
@@ -1132,11 +1133,12 @@ class TestWorkflowExecutionRoutesDelete(_TestWorkflowExecutionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         response = await client.delete(
-            "/".join([self.base_path, str(random_workflow_execution.execution_id)]), headers=random_user.auth_headers
+            "/".join([self.base_path, str(random_running_workflow_execution.execution_id)]),
+            headers=random_user.auth_headers,
         )
         assert response.status_code == status.HTTP_400_BAD_REQUEST
 
@@ -1146,7 +1148,7 @@ class TestWorkflowExecutionRoutesDelete(_TestWorkflowExecutionRoutes):
         client: AsyncClient,
         db: AsyncSession,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for deleting a workflow execution.
@@ -1159,17 +1161,18 @@ class TestWorkflowExecutionRoutesDelete(_TestWorkflowExecutionRoutes):
             Async database session to perform query on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         await db.execute(
             update(WorkflowExecution)
-            .where(WorkflowExecution._execution_id == random_workflow_execution.execution_id.bytes)
+            .where(WorkflowExecution._execution_id == random_running_workflow_execution.execution_id.bytes)
             .values(status=WorkflowExecution.WorkflowExecutionStatus.SUCCESS.name)
         )
         await db.commit()
         response = await client.delete(
-            "/".join([self.base_path, str(random_workflow_execution.execution_id)]), headers=random_user.auth_headers
+            "/".join([self.base_path, str(random_running_workflow_execution.execution_id)]),
+            headers=random_user.auth_headers,
         )
         assert response.status_code == status.HTTP_204_NO_CONTENT
 
@@ -1180,7 +1183,7 @@ class TestWorkflowExecutionRoutesCancel(_TestWorkflowExecutionRoutes):
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
         mock_slurm_cluster: MockSlurmCluster,
     ) -> None:
         """
@@ -1192,17 +1195,17 @@ class TestWorkflowExecutionRoutesCancel(_TestWorkflowExecutionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         mock_slurm_cluster : app.tests.mocks.mock_slurm_cluster.MockSlurmCluster
             Mock Slurm cluster to inspect submitted jobs.
         """
         response = await client.post(
-            "/".join([self.base_path, str(random_workflow_execution.execution_id), "cancel"]),
+            "/".join([self.base_path, str(random_running_workflow_execution.execution_id), "cancel"]),
             headers=random_user.auth_headers,
         )
         assert response.status_code == status.HTTP_204_NO_CONTENT
-        job_active = mock_slurm_cluster.job_active(random_workflow_execution.slurm_job_id)
+        job_active = mock_slurm_cluster.job_active(random_running_workflow_execution.slurm_job_id)
         assert not job_active
 
     @pytest.mark.asyncio
@@ -1211,7 +1214,7 @@ class TestWorkflowExecutionRoutesCancel(_TestWorkflowExecutionRoutes):
         client: AsyncClient,
         db: AsyncSession,
         random_user: UserWithAuthHeader,
-        random_workflow_execution: WorkflowExecution,
+        random_running_workflow_execution: WorkflowExecution,
     ) -> None:
         """
         Test for canceling a finished workflow execution.
@@ -1224,17 +1227,17 @@ class TestWorkflowExecutionRoutesCancel(_TestWorkflowExecutionRoutes):
             Async database session to perform query on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         await db.execute(
             update(WorkflowExecution)
-            .where(WorkflowExecution._execution_id == random_workflow_execution.execution_id.bytes)
+            .where(WorkflowExecution._execution_id == random_running_workflow_execution.execution_id.bytes)
             .values(status=WorkflowExecution.WorkflowExecutionStatus.SUCCESS.name)
         )
         await db.commit()
         response = await client.post(
-            "/".join([self.base_path, str(random_workflow_execution.execution_id), "cancel"]),
+            "/".join([self.base_path, str(random_running_workflow_execution.execution_id), "cancel"]),
             headers=random_user.auth_headers,
         )
         assert response.status_code == status.HTTP_400_BAD_REQUEST
diff --git a/app/tests/conftest.py b/app/tests/conftest.py
index 7e7a221..0b00faa 100644
--- a/app/tests/conftest.py
+++ b/app/tests/conftest.py
@@ -1,4 +1,5 @@
 import asyncio
+import time
 from functools import partial
 from io import BytesIO
 from secrets import token_urlsafe
@@ -278,7 +279,7 @@ async def random_workflow_version(db: AsyncSession, random_workflow: WorkflowOut
 
 
 @pytest_asyncio.fixture(scope="function")
-async def random_workflow_execution(
+async def random_running_workflow_execution(
     db: AsyncSession,
     random_workflow_version: WorkflowVersion,
     random_user: UserWithAuthHeader,
@@ -286,7 +287,7 @@ async def random_workflow_execution(
     mock_slurm_cluster: MockSlurmCluster,
 ) -> AsyncIterator[WorkflowExecution]:
     """
-    Create a random workflow execution. Will be deleted, when the user is deleted.
+    Create a random running workflow execution. Will be deleted, when the user is deleted.
     """
     execution = WorkflowExecution(
         user_id=random_user.user.uid,
@@ -308,6 +309,23 @@ async def random_workflow_execution(
     mock_s3_service.Bucket(settings.PARAMS_BUCKET).Object(f"params-{execution.execution_id.hex}.json").delete()
 
 
+@pytest_asyncio.fixture(scope="function")
+async def random_completed_workflow_execution(
+    db: AsyncSession, random_running_workflow_execution: WorkflowExecution
+) -> WorkflowExecution:
+    """
+    Create a random workflow execution which is completed.
+    """
+
+    await db.execute(
+        update(WorkflowExecution)
+        .where(WorkflowExecution._execution_id == random_running_workflow_execution.execution_id.bytes)
+        .values(end_time=round(time.time()), status=WorkflowExecution.WorkflowExecutionStatus.SUCCESS)
+    )
+    await db.commit()
+    return random_running_workflow_execution
+
+
 @pytest_asyncio.fixture(scope="function")
 async def random_workflow_mode(
     db: AsyncSession,
diff --git a/app/tests/crud/test_workflow.py b/app/tests/crud/test_workflow.py
index 30cd17a..637c2d8 100644
--- a/app/tests/crud/test_workflow.py
+++ b/app/tests/crud/test_workflow.py
@@ -140,10 +140,10 @@ class TestWorkflowCRUDGet:
 
     @pytest.mark.asyncio
     async def test_get_workflow_statistics(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
-        Test for getting a workflow by its name from CRUD Repository.
+        Test for getting the aggregated workflow statistics.
 
         Parameters
         ----------
@@ -151,7 +151,7 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.statistics(db, random_workflow.workflow_id)
@@ -161,7 +161,7 @@ class TestWorkflowCRUDGet:
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer.
@@ -172,21 +172,21 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db)
         assert len(statistics) == 1
         assert statistics[0].started_at == date.today()
         assert statistics[0].workflow_id == random_workflow.workflow_id
-        assert statistics[0].workflow_execution_id == random_workflow_execution.execution_id
-        assert statistics[0].git_commit_hash == random_workflow_execution.workflow_version_id
-        assert statistics[0].pseudo_uid != random_workflow_execution.user_id
+        assert statistics[0].workflow_execution_id == random_completed_workflow_execution.execution_id
+        assert statistics[0].git_commit_hash == random_completed_workflow_execution.workflow_version_id
+        assert statistics[0].pseudo_uid != random_completed_workflow_execution.user_id
         assert statistics[0].developer_id == random_workflow.developer_id
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_developer_id(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a developer ID.
@@ -197,21 +197,21 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, developer_id=random_workflow.developer_id)
         assert len(statistics) == 1
         assert statistics[0].started_at == date.today()
         assert statistics[0].workflow_id == random_workflow.workflow_id
-        assert statistics[0].workflow_execution_id == random_workflow_execution.execution_id
-        assert statistics[0].git_commit_hash == random_workflow_execution.workflow_version_id
-        assert statistics[0].pseudo_uid != random_workflow_execution.user_id
+        assert statistics[0].workflow_execution_id == random_completed_workflow_execution.execution_id
+        assert statistics[0].git_commit_hash == random_completed_workflow_execution.workflow_version_id
+        assert statistics[0].pseudo_uid != random_completed_workflow_execution.user_id
         assert statistics[0].developer_id == random_workflow.developer_id
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_non_existent_developer_id(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a non-existing developer ID.
@@ -222,7 +222,7 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, developer_id=random_lower_string(40))
@@ -230,7 +230,7 @@ class TestWorkflowCRUDGet:
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_workflow_id(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a workflow ID.
@@ -241,21 +241,21 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, workflow_ids=[random_workflow.workflow_id])
         assert len(statistics) == 1
         assert statistics[0].started_at == date.today()
         assert statistics[0].workflow_id == random_workflow.workflow_id
-        assert statistics[0].workflow_execution_id == random_workflow_execution.execution_id
-        assert statistics[0].git_commit_hash == random_workflow_execution.workflow_version_id
-        assert statistics[0].pseudo_uid != random_workflow_execution.user_id
+        assert statistics[0].workflow_execution_id == random_completed_workflow_execution.execution_id
+        assert statistics[0].git_commit_hash == random_completed_workflow_execution.workflow_version_id
+        assert statistics[0].pseudo_uid != random_completed_workflow_execution.user_id
         assert statistics[0].developer_id == random_workflow.developer_id
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_non_existent_workflow_id(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a non-existing workflow ID.
@@ -266,7 +266,7 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, workflow_ids=[uuid4()])
@@ -274,7 +274,7 @@ class TestWorkflowCRUDGet:
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_start_date(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a start date in the past.
@@ -285,21 +285,21 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, start=date.today() - timedelta(days=7))
         assert len(statistics) == 1
         assert statistics[0].started_at == date.today()
         assert statistics[0].workflow_id == random_workflow.workflow_id
-        assert statistics[0].workflow_execution_id == random_workflow_execution.execution_id
-        assert statistics[0].git_commit_hash == random_workflow_execution.workflow_version_id
-        assert statistics[0].pseudo_uid != random_workflow_execution.user_id
+        assert statistics[0].workflow_execution_id == random_completed_workflow_execution.execution_id
+        assert statistics[0].git_commit_hash == random_completed_workflow_execution.workflow_version_id
+        assert statistics[0].pseudo_uid != random_completed_workflow_execution.user_id
         assert statistics[0].developer_id == random_workflow.developer_id
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_bad_start_day(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a start date in the future.
@@ -310,7 +310,7 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, start=date.today() + timedelta(days=7))
@@ -318,7 +318,7 @@ class TestWorkflowCRUDGet:
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_end_date(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a end date in the future.
@@ -329,21 +329,21 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, end=date.today() + timedelta(days=7))
         assert len(statistics) == 1
         assert statistics[0].started_at == date.today()
         assert statistics[0].workflow_id == random_workflow.workflow_id
-        assert statistics[0].workflow_execution_id == random_workflow_execution.execution_id
-        assert statistics[0].git_commit_hash == random_workflow_execution.workflow_version_id
-        assert statistics[0].pseudo_uid != random_workflow_execution.user_id
+        assert statistics[0].workflow_execution_id == random_completed_workflow_execution.execution_id
+        assert statistics[0].git_commit_hash == random_completed_workflow_execution.workflow_version_id
+        assert statistics[0].pseudo_uid != random_completed_workflow_execution.user_id
         assert statistics[0].developer_id == random_workflow.developer_id
 
     @pytest.mark.asyncio
     async def test_get_workflow_developer_statistics_with_bad_end_day(
-        self, db: AsyncSession, random_workflow: WorkflowOut, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_workflow: WorkflowOut, random_completed_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for getting workflow statistics for developer with a end date in the past.
@@ -354,7 +354,7 @@ class TestWorkflowCRUDGet:
             Async database session to perform query on.
         random_workflow : app.schemas.workflow.WorkflowOut
             Random bucket for testing.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_completed_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         statistics = await CRUDWorkflow.developer_statistics(db, end=date.today() - timedelta(days=7))
diff --git a/app/tests/crud/test_workflow_execution.py b/app/tests/crud/test_workflow_execution.py
index a0e5214..815eaf8 100644
--- a/app/tests/crud/test_workflow_execution.py
+++ b/app/tests/crud/test_workflow_execution.py
@@ -79,7 +79,9 @@ class TestWorkflowExecutionCRUDCreate:
 
 class TestWorkflowExecutionCRUDGet:
     @pytest.mark.asyncio
-    async def test_get_workflow_execution(self, db: AsyncSession, random_workflow_execution: WorkflowExecution) -> None:
+    async def test_get_workflow_execution(
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
+    ) -> None:
         """
         Test for getting a workflow execution by its execution id.
 
@@ -87,12 +89,12 @@ class TestWorkflowExecutionCRUDGet:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
-        execution = await CRUDWorkflowExecution.get(db, random_workflow_execution.execution_id)
+        execution = await CRUDWorkflowExecution.get(db, random_running_workflow_execution.execution_id)
         assert execution is not None
-        assert execution == random_workflow_execution
+        assert execution == random_running_workflow_execution
 
     @pytest.mark.asyncio
     async def test_get_non_existing_workflow_execution(self, db: AsyncSession) -> None:
@@ -111,7 +113,7 @@ class TestWorkflowExecutionCRUDGet:
 class TestWorkflowExecutionCRUDList:
     @pytest.mark.asyncio
     async def test_list_workflow_executions(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for listing all workflow executions.
@@ -120,16 +122,16 @@ class TestWorkflowExecutionCRUDList:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         executions = await CRUDWorkflowExecution.list(db)
         assert len(executions) > 0
-        assert sum(1 for execution in executions if execution == random_workflow_execution) == 1
+        assert sum(1 for execution in executions if execution == random_running_workflow_execution) == 1
 
     @pytest.mark.asyncio
     async def test_get_list_workflow_executions_of_user(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for listing all workflow executions and filter by user.
@@ -138,17 +140,17 @@ class TestWorkflowExecutionCRUDList:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
-        executions = await CRUDWorkflowExecution.list(db, uid=random_workflow_execution.user_id)
+        executions = await CRUDWorkflowExecution.list(db, uid=random_running_workflow_execution.user_id)
         assert len(executions) > 0
-        assert sum(1 for execution in executions if execution == random_workflow_execution) == 1
-        assert sum(1 for execution in executions if execution.user_id == random_workflow_execution.user_id) >= 1
+        assert sum(1 for execution in executions if execution == random_running_workflow_execution) == 1
+        assert sum(1 for execution in executions if execution.user_id == random_running_workflow_execution.user_id) >= 1
 
     @pytest.mark.asyncio
     async def test_get_list_workflow_executions_of_non_existing_user(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for listing all workflow executions and filter by non-existing user.
@@ -157,16 +159,16 @@ class TestWorkflowExecutionCRUDList:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         executions = await CRUDWorkflowExecution.list(db, uid=random_lower_string())
         assert len(executions) == 0
-        assert sum(1 for execution in executions if execution == random_workflow_execution) == 0
+        assert sum(1 for execution in executions if execution == random_running_workflow_execution) == 0
 
     @pytest.mark.asyncio
     async def test_get_list_workflow_executions_of_workflow_version(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for listing all workflow executions and filter by workflow version id.
@@ -175,26 +177,26 @@ class TestWorkflowExecutionCRUDList:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         executions = await CRUDWorkflowExecution.list(
-            db, workflow_version_id=random_workflow_execution.workflow_version_id
+            db, workflow_version_id=random_running_workflow_execution.workflow_version_id
         )
         assert len(executions) > 0
-        assert sum(1 for execution in executions if execution == random_workflow_execution) == 1
+        assert sum(1 for execution in executions if execution == random_running_workflow_execution) == 1
         assert (
             sum(
                 1
                 for execution in executions
-                if execution.workflow_version_id == random_workflow_execution.workflow_version_id
+                if execution.workflow_version_id == random_running_workflow_execution.workflow_version_id
             )
             >= 1
         )
 
     @pytest.mark.asyncio
     async def test_get_list_workflow_executions_of_non_existing_workflow_version(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for listing all workflow executions and filter by non-existing workflow version id.
@@ -203,16 +205,16 @@ class TestWorkflowExecutionCRUDList:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
         executions = await CRUDWorkflowExecution.list(db, workflow_version_id=random_hex_string())
         assert len(executions) == 0
-        assert sum(1 for execution in executions if execution == random_workflow_execution) == 0
+        assert sum(1 for execution in executions if execution == random_running_workflow_execution) == 0
 
     @pytest.mark.asyncio
     async def test_get_list_workflow_executions_with_given_status(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for listing all workflow executions and filter by status.
@@ -221,19 +223,19 @@ class TestWorkflowExecutionCRUDList:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
-        executions = await CRUDWorkflowExecution.list(db, status_list=[random_workflow_execution.status])
+        executions = await CRUDWorkflowExecution.list(db, status_list=[random_running_workflow_execution.status])
         assert len(executions) > 0
-        assert sum(1 for execution in executions if execution == random_workflow_execution) == 1
-        assert sum(1 for execution in executions if execution.status == random_workflow_execution.status) >= 1
+        assert sum(1 for execution in executions if execution == random_running_workflow_execution) == 1
+        assert sum(1 for execution in executions if execution.status == random_running_workflow_execution.status) >= 1
 
 
 class TestWorkflowExecutionCRUDLUpdate:
     @pytest.mark.asyncio
     async def test_cancel_workflow_execution(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for canceling a workflow execution.
@@ -242,13 +244,13 @@ class TestWorkflowExecutionCRUDLUpdate:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
-        await CRUDWorkflowExecution.cancel(db, random_workflow_execution.execution_id)
+        await CRUDWorkflowExecution.cancel(db, random_running_workflow_execution.execution_id)
 
         stmt = select(WorkflowExecution).where(
-            WorkflowExecution._execution_id == random_workflow_execution.execution_id.bytes
+            WorkflowExecution._execution_id == random_running_workflow_execution.execution_id.bytes
         )
         execution = await db.scalar(stmt)
         assert execution is not None
@@ -256,7 +258,7 @@ class TestWorkflowExecutionCRUDLUpdate:
 
     @pytest.mark.asyncio
     async def test_update_workflow_execution_slurm_job(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for updating the slurm job id of a workflow execution.
@@ -265,13 +267,13 @@ class TestWorkflowExecutionCRUDLUpdate:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
-        await CRUDWorkflowExecution.update_slurm_job_id(db, random_workflow_execution.execution_id, 250)
+        await CRUDWorkflowExecution.update_slurm_job_id(db, random_running_workflow_execution.execution_id, 250)
 
         stmt = select(WorkflowExecution).where(
-            WorkflowExecution._execution_id == random_workflow_execution.execution_id.bytes
+            WorkflowExecution._execution_id == random_running_workflow_execution.execution_id.bytes
         )
         execution = await db.scalar(stmt)
         assert execution is not None
@@ -281,7 +283,7 @@ class TestWorkflowExecutionCRUDLUpdate:
 class TestWorkflowExecutionCRUDDelete:
     @pytest.mark.asyncio
     async def test_delete_workflow_execution(
-        self, db: AsyncSession, random_workflow_execution: WorkflowExecution
+        self, db: AsyncSession, random_running_workflow_execution: WorkflowExecution
     ) -> None:
         """
         Test for deleting a workflow execution.
@@ -290,13 +292,13 @@ class TestWorkflowExecutionCRUDDelete:
         ----------
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
-        random_workflow_execution : clowmdb.models.WorkflowExecution
+        random_running_workflow_execution : clowmdb.models.WorkflowExecution
             Random workflow execution for testing.
         """
-        await CRUDWorkflowExecution.delete(db, random_workflow_execution.execution_id)
+        await CRUDWorkflowExecution.delete(db, random_running_workflow_execution.execution_id)
 
         stmt = select(WorkflowExecution).where(
-            WorkflowExecution._execution_id == random_workflow_execution.execution_id.bytes
+            WorkflowExecution._execution_id == random_running_workflow_execution.execution_id.bytes
         )
         execution = await db.scalar(stmt)
         assert execution is None
-- 
GitLab