Skip to content

Commit 2a3607f

Browse files
samyarpotlapallismlindauer
authored andcommitted
Pushing with all successful test cases
1 parent ae41977 commit 2a3607f

File tree

3 files changed

+115
-92
lines changed

3 files changed

+115
-92
lines changed

src/sasctl/_services/score_execution.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,44 +62,46 @@ def create_score_execution(
6262
if score_definition.status_code >= 400:
6363
raise HTTPError(score_definition.json())
6464
score_exec_name = score_definition.get("name")
65-
model_uri = score_definition.get("objectDescriptor", ["uri"])
66-
model_name = score_definition.get("objectDescriptor", ["name"])
67-
model_input_library = score_definition.get("inputData", ["libraryName"])
68-
model_table_name = score_definition.get("inputData", ["tableName"])
65+
model_uri = score_definition.get("objectDescriptor", "uri")
66+
model_name = score_definition.get("objectDescriptor", "name")
67+
model_input_library = score_definition.get("inputData", "libraryName")
68+
model_table_name = score_definition.get("inputData", "tableName")
6969

7070
# Defining a default output table name if none is provided
7171
if not output_table_name:
7272
output_table_name = f"{model_name}_{score_definition_id}"
7373

7474
# Getting all score executions that are using the inputted score_definition_id
75-
76-
score_execution = cls.list_executions(filter=f"eq(scoreDefinitionId, '{score_definition_id}')")
75+
76+
score_execution = cls.list_executions(
77+
filter=f"eq(scoreDefinitionId, '{score_definition_id}')"
78+
)
7779
if score_execution.status_code >= 400:
7880
raise HTTPError(
79-
f"Something went wrong in the LIST_EXECUTIONS statement. See error: {score_execution.json()}"
81+
f"Something went wrong in the LIST_EXECUTIONS statement. See error: {score_execution.json()}"
8082
)
81-
83+
8284
# Checking the count of the execution list to see if there are any score executions for this score_definition_id already running
8385
execution_count = score_execution.get("count") # Exception catch location
8486
if execution_count == 1:
85-
execution_id = score_execution.get("items", [0], ["id"])
87+
execution_id = score_execution.get("items", 0, "id")
8688
deleted_execution = cls.delete_execution(execution_id)
8789
if deleted_execution.status_code >= 400:
8890
raise HTTPError(
89-
f"Something went wrong in the DELETE statement. See error: {deleted_execution.json()}"
90-
)
91+
f"Something went wrong in the DELETE statement. See error: {deleted_execution.json()}"
92+
)
9193

9294
headers_score_exec = {"Content-Type": "application/json"}
9395

9496
create_score_exec = {
95-
"name": score_exec_name,
97+
"name": f"{score_exec_name}",
9698
"description": description,
9799
"hints": {
98-
"objectURI": model_uri,
99-
"inputTableName": model_table_name,
100-
"inputLibraryName": model_input_library,
100+
"objectURI": f"{model_uri}",
101+
"inputTableName": f"{model_table_name}",
102+
"inputLibraryName": f"{model_input_library}",
101103
},
102-
"scoreDefinitionId": score_definition_id,
104+
"scoreDefinitionId": f"{score_definition_id}",
103105
"outputTable": {
104106
"tableName": output_table_name,
105107
"libraryName": output_library_name,

tests/unit/test_score_definitions.py

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import random
1111
import tempfile
1212
import unittest
13+
import copy
1314
from pathlib import Path
1415
from unittest import mock
1516

@@ -31,44 +32,25 @@ def test_create_score_definition():
3132
- Invalid model id
3233
- Valid table name without input mapping
3334
- Invalid table name with invalid file
34-
- Invalid table name with valid file and without input mapping
35+
- Invalid table name with valid file
36+
- Invalid table name without table file argument
3537
3638
"""
39+
# Mocking a session to allow the post call to go through
3740
with mock.patch("sasctl.core.Session._get_authorization_token"):
3841
current_session("example.com", "username", "password")
39-
40-
TARGET = {
41-
"name": MODEL_NAME,
42-
"projectId": PROJECT_ID,
43-
"modeler": USER,
44-
"description": "model description",
45-
"function": "Classification",
46-
"algorithm": "Dummy Algorithm",
47-
"tool": "pytest",
48-
"champion": True,
49-
"role": "champion",
50-
"immutable": True,
51-
"retrainable": True,
52-
"scoreCodeType": None,
53-
"targetVariable": None,
54-
"trainTable": None,
55-
"classificationEventProbabilityVariableName": None,
56-
"classificationTargetEventValue": None,
57-
"location": None,
58-
"properties": [
59-
{"name": "custom1", "value": 123, "type": "numeric"},
60-
{"name": "custom2", "value": "somevalue", "type": "string"},
61-
# {'name': 'customDate', 'value': 1672462800000, 'type': 'date'},
62-
{"name": "customDateTime", "value": 1672481272000, "type": "dateTime"},
63-
],
64-
"inputVariables": [],
65-
"outputVariables": [],
66-
"version": 2,
67-
}
6842

69-
# Passed params should be set correctly
70-
target = copy.deepcopy(TARGET)
43+
# TARGET = {
44+
# "mappings": [
45+
# {"mappingValue": "first", "mappingType": "datasource", "variableName": "first"},
46+
# {"mappingValue": "second", "mappingType": "datasource", "variableName": "second"},
47+
# {"mappingValue": "third", "mappingType": "datasource", "variableName": "third"}
48+
# ]
49+
# }
7150

51+
# target = copy.deepcopy(TARGET)
52+
53+
# Mocking the REST API calls and functions
7254
with mock.patch(
7355
"sasctl._services.model_repository.ModelRepository.get_model"
7456
) as get_model:
@@ -81,6 +63,7 @@ def test_create_score_definition():
8163
with mock.patch(
8264
"sasctl._services.score_definitions.ScoreDefinitions.post"
8365
) as post:
66+
# Invalid model id test case
8467
get_model.return_value.status_code = 404
8568
with pytest.raises(HTTPError):
8669
sd.create_score_definition(
@@ -89,6 +72,7 @@ def test_create_score_definition():
8972
table_name="test_table",
9073
)
9174

75+
# Valid model id but invalid table name with no table_file argument test case
9276
get_model.return_value.status_code = 200
9377
get_model.return_value.json.return_value = {
9478
"id": "12345",
@@ -103,6 +87,8 @@ def test_create_score_definition():
10387
model_id="12345",
10488
table_name="test_table",
10589
)
90+
91+
# Invalid table name with a table_file argument that doesn't work test case
10692
get_table.return_value.status_code = 404
10793
upload_file.return_value = None
10894
get_table.return_value.status_code = 404
@@ -114,6 +100,7 @@ def test_create_score_definition():
114100
table_file="test_path",
115101
)
116102

103+
# Valid table_file argument that successfully creates a table test case
117104
get_table.return_value.status_code = 404
118105
upload_file.return_value = RestObj
119106
get_table.return_value.status_code = 200
@@ -128,6 +115,7 @@ def test_create_score_definition():
128115
)
129116
assert response
130117

118+
# Valid table_name argument test case
131119
get_table.return_value.status_code = 200
132120
get_table.return_value.json.return_value = {
133121
"tableName": "test_table"
@@ -140,6 +128,7 @@ def test_create_score_definition():
140128
)
141129
assert response
142130

131+
# Checking response with inputVariables in model elements
143132
get_model.return_value.status_code = 200
144133
get_model.return_value.json.return_value = {
145134
"id": "12345",
@@ -163,3 +152,7 @@ def test_create_score_definition():
163152
)
164153
assert response
165154
assert post.call_count == 3
155+
156+
# data = post.call_args
157+
# json_data = json.loads(data.kwargs["data"])
158+
# assert target["mappings"] == json_data["mappings"]

tests/unit/test_score_execution.py

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import random
1111
import tempfile
1212
import unittest
13+
import copy
1314
from pathlib import Path
1415
from unittest import mock
1516
from unittest.mock import MagicMock
@@ -26,21 +27,40 @@
2627
from sasctl._services.score_execution import ScoreExecution as se
2728

2829

30+
# Creating a CustomMock for list_executions to avoid a TypeError when comparing status code from mock with >= 400 in score_execution
31+
class CustomMock:
32+
def __init__(self, status_code, json_info):
33+
self.status_code = status_code
34+
self.json_info = json_info
35+
36+
def get(self, key1, key2=None, key3=None):
37+
if key2 is None and key3 is None:
38+
return self.json_info[key1]
39+
else:
40+
return self.json_info[key1][key2][key3]
41+
42+
2943
def test_create_score_execution():
3044
"""
3145
Test Cases:
32-
- Valid score definition id?
33-
-yes
34-
-no
35-
- Valid execution id?
36-
37-
-Valid count key? -> treated like input mapping -> no because i think it's required
38-
- output table -> treat like input mapping but within the create_score_execution step (do I for library and server in score definition thought? but I think you need a target step here too)
46+
- Valid score definition id and invalid list_executions argument
47+
- Invalid score definition id
48+
- Valid list_executions argument with execution already running but invalid delete_execution argument
49+
- Valid list_executions argument with execution already running but valid delete_execution argument
50+
- Valid list_executions argument without execution already running
51+
- With output table specified within create_score_execution arguments
3952
4053
"""
54+
55+
# Mocking a session to allow the post call to go through
4156
with mock.patch("sasctl.core.Session._get_authorization_token"):
42-
current_session("example.com", "username", "password")
57+
current_session("example.com", "username", "password")
58+
# Mocking what a successful score execution post would be if the user specified an output table
59+
TARGET = {"outputTable": {"tableName": "example_table"}}
60+
# Creating a target to compare post call responses to
61+
target = copy.deepcopy(TARGET)
4362

63+
# Mocking the REST API calls and functions
4464
with mock.patch(
4565
"sasctl._services.score_definitions.ScoreDefinitions.get_definition"
4666
) as get_definition:
@@ -51,64 +71,72 @@ def test_create_score_execution():
5171
"sasctl._services.score_execution.ScoreExecution.delete_execution"
5272
) as delete_execution:
5373
with mock.patch(
54-
"sasctl._services.score_execution.ScoreExecution.post"
74+
"sasctl._services.score_execution.ScoreExecution.post"
5575
) as post:
76+
# Invalid score definition id test case
5677
get_definition.return_value.status_code = 404
5778
with pytest.raises(HTTPError):
58-
se.create_score_execution(
59-
score_definition_id="12345"
60-
)
79+
se.create_score_execution(score_definition_id="12345")
80+
81+
# Valid score definition id and invalid list_executions argument test case
6182
get_definition.return_value.status_code = 200
6283
get_definition.return_value.json.return_value = {
6384
"inputData": {
6485
"libraryName": "cas-shared-default",
65-
"tableName": ""
86+
"tableName": "test_table",
6687
},
6788
"name": "score_def_name",
6889
"objectDescriptor": {
6990
"name": "test_model",
7091
"type": "sas.publish.example",
71-
"uri": "/modelPublish/models/example"
72-
}
92+
"uri": "/modelPublish/models/example",
93+
},
7394
}
74-
list_executions.return_value.status_code = 400 #test case worked with .return_value.status_code but caused an HTTP error that said error with list_Executions
95+
list_executions.return_value.status_code = 404
7596
with pytest.raises(HTTPError):
76-
se.create_score_execution(
77-
score_definition_id="12345"
78-
)
97+
se.create_score_execution(score_definition_id="12345")
7998

80-
list_executions.status_code = 200 #why does this not have a return value and how is this related to different score_Defintion instantiation in score_execution
81-
list_executions.return_value.json.return_value = {"count": 1}
99+
# Valid list_executions argument with execution already running but invalid delete_execution argument test case
100+
list_mock_execution = CustomMock(
101+
status_code=200,
102+
json_info={"count": 1, "items": [{"id": "1234"}]},
103+
)
104+
list_executions.return_value = list_mock_execution
82105
delete_execution.return_value.status_code = 404
83106
with pytest.raises(HTTPError):
84-
se.create_score_execution(
85-
score_definition_id="12345"
86-
)
87-
#Test cases that don't work or I haven't tested
88-
delete_execution.return_value.status_code = 200
89-
response = se.create_score_execution(
90-
score_definition_id="3456"
107+
se.create_score_execution(score_definition_id="12345")
108+
109+
# Valid list_executions argument with execution already running but valid delete_execution argument test case
110+
list_executions.return_value = list_mock_execution
111+
delete_execution.return_value.status_code = 200
112+
response = se.create_score_execution(score_definition_id="3456")
113+
assert response
114+
115+
# Valid list_executions argument without execution already running test case
116+
list_mock_execution_diff_count = CustomMock(
117+
status_code=200,
118+
json_info={"count": 0, "items": [{"id": "1234"}]},
91119
)
120+
list_executions.return_value = list_mock_execution_diff_count
121+
response = se.create_score_execution(score_definition_id="12345")
92122
assert response
93123

94-
list_executions.status_code = 200 #shouldn't this work with 200 response and not give me a type rror >= since it's not running 400 statement
95-
96-
list_executions.return_value.json.return_value = {"count": 0}
124+
# Checking whether the output table name remained the default empty string or the default changed as writted in score_execution
125+
data = post.call_args
126+
json_data = json.loads(data.kwargs["data"])
127+
assert json_data["outputTable"]["tableName"] != ""
128+
129+
# With output table specified within create_score_execution arguments test case
97130
response = se.create_score_execution(
98-
score_definition_id="12345"
131+
score_definition_id="12345", output_table_name="example_table"
99132
)
100133
assert response
134+
assert post.call_count == 3
101135

102-
list_executions.status_code = 200
103-
list_executions.return_value.json.return_value = {"count": 0}
104-
response = se.create_score_execution(
105-
score_definition_id="12345",
106-
output_table_name = "test_output_table"
136+
# Checking whether specified output table name or the default output table name is in the response
137+
data = post.call_args
138+
json_data = json.loads(data.kwargs["data"])
139+
assert (
140+
target["outputTable"]["tableName"]
141+
== json_data["outputTable"]["tableName"]
107142
)
108-
assert response #target needed here to test with and without specified output_table_name
109-
110-
111-
#pytest.skip()
112-
# raise HTTP error?
113-
#notes -> how to test count because it should only delete if count == 1 so how do I test that if/else
114-
#notes -> output table case, again TARGET?

0 commit comments

Comments
 (0)