codemie-test-harness 0.1.136__py3-none-any.whl → 0.1.137__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codemie-test-harness might be problematic. Click here for more details.

@@ -1,24 +1,41 @@
1
- """Integration tests for UserService."""
2
-
3
- from codemie_sdk import CodeMieClient
1
+ import os
4
2
  from codemie_sdk.models.user import User, UserData
3
+ from hamcrest import (
4
+ assert_that,
5
+ instance_of,
6
+ is_not,
7
+ all_of,
8
+ has_property,
9
+ )
10
+
11
+
12
+ def test_about_me(user_utils):
13
+ user = user_utils.get_about_me()
5
14
 
15
+ assert_that(
16
+ user,
17
+ all_of(
18
+ instance_of(User),
19
+ has_property("user_id", is_not(None)),
20
+ has_property("name", os.getenv("AUTH_USERNAME")),
21
+ has_property("username", os.getenv("AUTH_USERNAME")),
22
+ has_property("is_admin", is_not(None)),
23
+ has_property("applications", instance_of(list)),
24
+ has_property("applications_admin", instance_of(list)),
25
+ has_property("knowledge_bases", instance_of(list)),
26
+ ),
27
+ "User profile should have all required properties with correct types",
28
+ )
6
29
 
7
- def test_about_me(client: CodeMieClient):
8
- """Test successful retrieval of user profile."""
9
- user = client.users.about_me()
10
- assert isinstance(user, User)
11
- assert user.user_id is not None
12
- assert user.name is not None
13
- assert user.username is not None
14
- assert isinstance(user.is_admin, bool)
15
- assert isinstance(user.applications, list)
16
- assert isinstance(user.applications_admin, list)
17
- assert isinstance(user.knowledge_bases, list)
18
30
 
31
+ def test_get_user_data(user_utils):
32
+ user_data = user_utils.get_user_data()
19
33
 
20
- def test_get_data(client: CodeMieClient):
21
- """Test successful retrieval of user data."""
22
- user_data = client.users.get_data()
23
- assert isinstance(user_data, UserData)
24
- assert user_data.user_id is not None
34
+ assert_that(
35
+ user_data,
36
+ all_of(
37
+ instance_of(UserData),
38
+ has_property("user_id", is_not(None)),
39
+ ),
40
+ "User data should be valid UserData instance with user_id",
41
+ )
@@ -1,183 +1,156 @@
1
- """Integration tests for WorkflowExecutionService."""
2
-
3
1
  from time import sleep
4
2
 
5
3
  import pytest
6
- import requests
7
-
8
- from codemie_sdk import CodeMieClient
9
- from codemie_sdk.models.workflow import (
10
- WorkflowCreateRequest,
11
- WorkflowMode,
12
- ExecutionStatus,
4
+ from hamcrest import (
5
+ assert_that,
6
+ equal_to,
7
+ has_length,
8
+ contains_string,
9
+ all_of,
10
+ less_than_or_equal_to,
11
+ has_property,
12
+ is_not,
13
13
  )
14
+
15
+ from codemie_sdk.models.workflow import ExecutionStatus, WorkflowMode
14
16
  from codemie_test_harness.tests import PROJECT
15
17
  from codemie_test_harness.tests.utils.base_utils import get_random_name
16
18
 
19
+ from codemie_test_harness.tests.utils.yaml_utils import (
20
+ AssistantModel,
21
+ StateModel,
22
+ WorkflowYamlModel,
23
+ prepare_yaml_content,
24
+ )
17
25
 
18
- @pytest.fixture
19
- def valid_workflow_yaml(default_llm) -> str:
20
- """Return a valid workflow YAML configuration for testing."""
21
- return f"""
22
- assistants:
23
- - id: asst
24
- name: Simple assistant
25
- model: {default_llm.base_name}
26
- system_prompt: |
27
- You are simple chatbot.
28
- Generate a simple response.
29
-
30
- states:
31
- - id: simple
32
- assistant_id: asst
33
- task: |
34
- Say "Hello, World!"
35
- next:
36
- state_id: end
37
- """
38
-
39
-
40
- @pytest.fixture
41
- def test_workflow(client: CodeMieClient, valid_workflow_yaml: str):
42
- """Create a test workflow and clean it up after the test."""
43
- workflow_name = get_random_name()
44
- workflow_id = None
45
-
46
- try:
47
- # Create workflow
48
- create_request = WorkflowCreateRequest(
49
- name=workflow_name,
50
- description="Test workflow for executions",
51
- project=PROJECT,
52
- yaml_config=valid_workflow_yaml,
53
- mode=WorkflowMode.SEQUENTIAL,
54
- shared=False,
55
- )
56
26
 
57
- created = client.workflows.create_workflow(create_request)
58
- assert created is not None
59
-
60
- sleep(5) # Wait for workflow to be fully created
61
-
62
- workflows = client.workflows.list(projects=PROJECT, per_page=10)
63
- workflow = next((wf for wf in workflows if wf.name == workflow_name), None)
64
- assert workflow is not None
65
- workflow_id = workflow.id
66
-
67
- yield workflow_id
68
-
69
- finally:
70
- # Clean up
71
- if workflow_id:
72
- try:
73
- client.workflows.delete(workflow_id)
74
- except Exception as e:
75
- pytest.fail(f"Failed to clean up workflow: {str(e)}")
76
-
77
-
78
- def test_run_workflow(client: CodeMieClient, test_workflow: str):
79
- """Test workflow execution with state verification."""
80
-
81
- execution_id = None
82
- try:
83
- # Create a new execution
84
- execution = client.workflows.run(test_workflow, "Test")
85
- assert execution is not None
86
- sleep(5)
87
-
88
- # Test listing all executions
89
- executions = client.workflows.executions(test_workflow).list()
90
- assert executions is not None
91
- assert len(executions) == 1
92
- found_execution = executions[0]
93
- execution_id = executions[0].execution_id
94
- assert found_execution.workflow_id == test_workflow
95
- assert found_execution.status is not None
96
- assert found_execution.created_date is not None
97
- assert found_execution.created_by is not None
98
-
99
- # Test pagination
100
- paginated = client.workflows.executions(test_workflow).list(page=0, per_page=1)
101
- assert len(paginated) <= 1
102
-
103
- max_attempts = 30 # 30 * 2 seconds = 60 seconds total wait time
104
- attempts = 0
105
- while attempts < max_attempts:
106
- execution = client.workflows.executions(test_workflow).get(execution_id)
107
- if execution.status == ExecutionStatus.SUCCEEDED:
108
- # Only verify states and outputs on successful execution
109
- # Verify execution states
110
- states = (
111
- client.workflows.executions(test_workflow)
112
- .states(execution_id)
113
- .list()
114
- )
115
- assert states is not None
116
- assert len(states) == 2
117
-
118
- first_state = states[0]
119
- second_state = states[1]
120
- assert first_state.completed_at is not None
121
- assert second_state.completed_at is not None
122
- assert first_state.completed_at < second_state.completed_at
123
-
124
- # Verify the state outputs
125
- for state in states:
126
- state_output = (
127
- client.workflows.executions(test_workflow)
128
- .states(execution_id)
129
- .get_output(state.id)
130
- )
131
- assert state_output is not None
132
- assert state_output.output is not None
133
- # For our test workflow, the first state should contain "Hello, World!"
134
- if state.id == "simple":
135
- assert "Hello, World!" in state_output.output
136
- break
137
- elif execution.status == ExecutionStatus.FAILED:
138
- pytest.fail(f"Workflow execution failed: {execution.error_message}")
139
-
140
- sleep(2)
141
- attempts += 1
142
- else:
143
- raise TimeoutError(
144
- f"Workflow execution did not complete within {attempts * 2} seconds"
27
+ @pytest.fixture(scope="session")
28
+ def test_workflow(default_llm, search_utils, workflow_utils):
29
+ assistant_and_state_name = get_random_name()
30
+
31
+ assistant = AssistantModel(
32
+ id=assistant_and_state_name,
33
+ model=default_llm.base_name,
34
+ system_prompt="You are simple chatbot. Generate a simple response.",
35
+ )
36
+
37
+ state = StateModel(
38
+ id=assistant_and_state_name,
39
+ assistant_id=assistant_and_state_name,
40
+ task='Say "Hello, World!"',
41
+ )
42
+
43
+ workflow_yaml = WorkflowYamlModel(
44
+ enable_summarization_node=True,
45
+ assistants=[assistant],
46
+ states=[state],
47
+ )
48
+
49
+ yaml_content = prepare_yaml_content(workflow_yaml.model_dump(exclude_none=True))
50
+ created = workflow_utils.create_workflow(
51
+ workflow_yaml=yaml_content,
52
+ workflow_type=WorkflowMode.SEQUENTIAL,
53
+ project_name=PROJECT,
54
+ description="Test workflow for executions",
55
+ )
56
+ assert_that(created, is_not(None))
57
+
58
+ workflows = search_utils.list_workflows(projects=PROJECT, per_page=10)
59
+ workflow = next((wf for wf in workflows if wf.name == created.name), None)
60
+ assert_that(workflow, is_not(None))
61
+
62
+ return workflow.id
63
+
64
+
65
+ def test_run_workflow(workflow_utils, search_utils, test_workflow: str):
66
+ execution = workflow_utils.run_workflow(test_workflow, "Test")
67
+
68
+ assert_that(execution, is_not(None))
69
+
70
+ # Test listing all executions
71
+ executions = search_utils.list_workflow_executions(test_workflow_id=test_workflow)
72
+ assert_that(executions, has_length(equal_to(1)))
73
+ found_execution = executions[0]
74
+ execution_id = executions[0].execution_id
75
+ assert_that(
76
+ found_execution,
77
+ all_of(
78
+ has_property("workflow_id", equal_to(test_workflow)),
79
+ has_property("status", is_not(None)),
80
+ has_property("created_date", is_not(None)),
81
+ has_property("created_by", is_not(None)),
82
+ ),
83
+ )
84
+
85
+ # Test pagination
86
+ paginated = search_utils.list_workflow_executions(
87
+ test_workflow_id=test_workflow,
88
+ page=0,
89
+ per_page=1,
90
+ )
91
+ assert_that(paginated, has_length(less_than_or_equal_to(1)))
92
+
93
+ max_attempts = 30 # 30 * 2 seconds = 60 seconds total wait time
94
+ attempts = 0
95
+ while attempts < max_attempts:
96
+ execution = workflow_utils.get_workflow_execution(
97
+ test_workflow_id=test_workflow, execution_id=execution_id
98
+ )
99
+ if execution.status == ExecutionStatus.SUCCEEDED:
100
+ # Only verify states and outputs on successful execution
101
+ # Verify execution states
102
+ states = workflow_utils.get_workflow_executions_states(
103
+ test_workflow, execution_id
104
+ ).list()
105
+ assert_that(states, has_length(equal_to(2)))
106
+
107
+ first_state = states[0]
108
+ second_state = states[1]
109
+ assert_that(first_state.completed_at, is_not(None))
110
+ assert_that(second_state.completed_at, is_not(None))
111
+ assert_that(
112
+ first_state.completed_at,
113
+ less_than_or_equal_to(second_state.completed_at),
145
114
  )
146
115
 
147
- finally:
148
- if execution_id:
149
- try:
150
- client.workflows.executions(test_workflow).delete_all()
151
- sleep(5)
152
- try:
153
- client.workflows.executions(test_workflow).get(execution_id)
154
- pytest.fail(
155
- f"Workflow execution {execution_id} still exists after deletion"
156
- )
157
- except requests.exceptions.HTTPError as e:
158
- if e.response.status_code != 404:
159
- pytest.fail(
160
- f"Unexpected error during cleanup verification: {str(e)}"
161
- )
162
- except Exception as e:
163
- pytest.fail(f"Failed to clean up workflow execution: {str(e)}")
164
-
165
-
166
- def test_list_executions_nonexistent_workflow(client: CodeMieClient):
167
- """Test listing executions for non-existent workflow."""
168
- workflows = client.workflows.executions("non-existent-id").list()
169
- print(workflows)
170
- assert len(workflows) == 0
171
-
172
-
173
- def test_list_executions_invalid_parameters(client: CodeMieClient, test_workflow: str):
174
- """Test listing executions with invalid parameters."""
175
- # Test invalid page number
116
+ # Verify the state outputs
117
+ for state in states:
118
+ state_output = workflow_utils.get_workflow_executions_states(
119
+ test_workflow, execution_id
120
+ ).get_output(state.id)
121
+ # For our test workflow, the first state should contain "Hello, World!"
122
+ if state.id == "simple":
123
+ assert_that(state_output.output, contains_string("Hello, World!"))
124
+ break
125
+ elif execution.status == ExecutionStatus.FAILED:
126
+ pytest.fail(f"Workflow execution failed: {execution.error_message}")
127
+
128
+ sleep(2)
129
+ attempts += 1
130
+ else:
131
+ raise TimeoutError(
132
+ f"Workflow execution did not complete within {attempts * 2} seconds"
133
+ )
134
+
135
+
136
+ @pytest.mark.skip(reason="Bug: https://jiraeu.epam.com/browse/EPMCDME-7883")
137
+ def test_list_executions_nonexistent_workflow(search_utils):
176
138
  with pytest.raises(Exception) as exc_info:
177
- client.workflows.executions(test_workflow).list(page=-1)
178
- assert "page" in str(exc_info.value).lower()
139
+ search_utils.list_workflow_executions("non-existent-id")
140
+
141
+ assert_that(
142
+ str(exc_info.value).lower(),
143
+ contains_string("No workflows found with id non-existent-id"),
144
+ )
145
+
146
+
147
+ def test_list_executions_with_invalid_page_number(search_utils):
148
+ with pytest.raises(Exception) as exc_info:
149
+ search_utils.list_workflow_executions(test_workflow_id=None, page=-1)
150
+ assert_that(str(exc_info.value).lower(), contains_string("page"))
151
+
179
152
 
180
- # Test invalid per_page value
153
+ def test_list_executions_with_invalid_per_page_value(search_utils):
181
154
  with pytest.raises(Exception) as exc_info:
182
- client.workflows.executions(test_workflow).list(per_page=0)
183
- assert "per_page" in str(exc_info.value).lower()
155
+ search_utils.list_workflow_executions(test_workflow_id=None, per_page=0)
156
+ assert_that(str(exc_info.value).lower(), contains_string("per_page"))