Skip to content

Commit c66edf8

Browse files
author
Yi-Ting Lee
committed
change: add queryLineageResult visualizer load test & integ test
1 parent 24f8925 commit c66edf8

File tree

2 files changed

+197
-31
lines changed

2 files changed

+197
-31
lines changed

tests/integ/sagemaker/lineage/helpers.py

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,10 @@
1212
# language governing permissions and limitations under the License.
1313
"""This module contains helper methods for tests of SageMaker Lineage"""
1414
from __future__ import absolute_import
15-
from urllib import response
1615

1716
import uuid
1817
from datetime import datetime
1918
import time
20-
import boto3
21-
from botocore.config import Config
22-
from sagemaker.lineage import association
23-
from sagemaker.lineage.artifact import Artifact
24-
from sagemaker.lineage.association import Association
2519

2620

2721
def name():
@@ -92,7 +86,6 @@ def __init__(self, sagemaker_session):
9286
self.artifacts = []
9387
self.actions = []
9488
self.contexts = []
95-
self.trialComponents = []
9689
self.associations = []
9790

9891
def create_artifact(self, artifact_name, artifact_type="Dataset"):
@@ -115,11 +108,10 @@ def create_action(self, action_name, action_type="ModelDeployment"):
115108
ActionName=action_name,
116109
Source={
117110
"SourceUri": "Test-action-" + action_name,
118-
"SourceTypes": [
119-
{"SourceIdType": "S3ETag", "Value": "Test-action-sourceId-value"},
120-
],
111+
"SourceType": "S3ETag",
112+
"SourceId": "Test-action-sourceId-value",
121113
},
122-
ActionType=action_type
114+
ActionType=action_type,
123115
)
124116
self.actions.append(response["ActionArn"])
125117

@@ -130,22 +122,15 @@ def create_context(self, context_name, context_type="Endpoint"):
130122
ContextName=context_name,
131123
Source={
132124
"SourceUri": "Test-context-" + context_name,
133-
"SourceTypes": [
134-
{"SourceIdType": "S3ETag", "Value": "Test-context-sourceId-value"},
135-
],
125+
"SourceType": "S3ETag",
126+
"SourceId": "Test-context-sourceId-value",
136127
},
137-
ContextType=context_type
128+
ContextType=context_type,
138129
)
139130
self.contexts.append(response["ContextArn"])
140131

141132
return response["ContextArn"]
142133

143-
def create_trialComponent(self, trialComponent_name, trialComponent_type="TrainingJob"):
144-
response = self.client.create_trial_component(
145-
TrialComponentName=trialComponent_name,
146-
147-
)
148-
149134
def create_association(self, source_arn, dest_arn, association_type="AssociatedWith"):
150135
response = self.client.add_association(
151136
SourceArn=source_arn, DestinationArn=dest_arn, AssociationType=association_type
@@ -177,3 +162,10 @@ def clean_all(self):
177162
time.sleep(0.5)
178163
except Exception as e:
179164
print("skipped " + str(e))
165+
166+
for context_arn in self.contexts:
167+
try:
168+
self.client.delete_context(ContextArn=context_arn)
169+
time.sleep(0.5)
170+
except Exception as e:
171+
print("skipped " + str(e))

tests/integ/sagemaker/lineage/test_lineage_visualize.py

Lines changed: 184 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,15 @@
1111
# ANY KIND, either express or implied. See the License for the specific
1212
# language governing permissions and limitations under the License.
1313
"""This module contains code to test SageMaker ``LineageQueryResult.visualize()``"""
14-
15-
import datetime
16-
import logging
14+
from __future__ import absolute_import
1715
import time
16+
import json
1817

1918
import pytest
2019

2120
import sagemaker.lineage.query
2221
from sagemaker.lineage.query import LineageQueryDirectionEnum
23-
from tests.integ.sagemaker.lineage.helpers import name, names, retry, LineageResourceHelper
22+
from tests.integ.sagemaker.lineage.helpers import name, LineageResourceHelper
2423

2524

2625
def test_LineageResourceHelper(sagemaker_session):
@@ -35,6 +34,7 @@ def test_LineageResourceHelper(sagemaker_session):
3534
print(e)
3635
assert False
3736

37+
3838
@pytest.mark.skip("visualizer load test")
3939
def test_wide_graph_visualize(sagemaker_session):
4040
lineage_resource_helper = LineageResourceHelper(sagemaker_session=sagemaker_session)
@@ -46,9 +46,11 @@ def test_wide_graph_visualize(sagemaker_session):
4646
# \ \--> Artifact
4747
# \---> ...
4848
try:
49-
for i in range(500):
49+
for i in range(10):
5050
artifact_arn = lineage_resource_helper.create_artifact(artifact_name=name())
51-
lineage_resource_helper.create_association(source_arn=wide_graph_root_arn, dest_arn=artifact_arn)
51+
lineage_resource_helper.create_association(
52+
source_arn=wide_graph_root_arn, dest_arn=artifact_arn
53+
)
5254
except Exception as e:
5355
print(e)
5456
lineage_resource_helper.clean_all()
@@ -65,6 +67,7 @@ def test_wide_graph_visualize(sagemaker_session):
6567

6668
lineage_resource_helper.clean_all()
6769

70+
6871
@pytest.mark.skip("visualizer load test")
6972
def test_long_graph_visualize(sagemaker_session):
7073
lineage_resource_helper = LineageResourceHelper(sagemaker_session=sagemaker_session)
@@ -74,9 +77,11 @@ def test_long_graph_visualize(sagemaker_session):
7477
# create long graph
7578
# Artifact -> Artifact -> ... -> Artifact
7679
try:
77-
for i in range(20):
80+
for i in range(10):
7881
new_artifact_arn = lineage_resource_helper.create_artifact(artifact_name=name())
79-
lineage_resource_helper.create_association(source_arn=last_arn, dest_arn=new_artifact_arn)
82+
lineage_resource_helper.create_association(
83+
source_arn=last_arn, dest_arn=new_artifact_arn
84+
)
8085
last_arn = new_artifact_arn
8186
except Exception as e:
8287
print(e)
@@ -85,12 +90,181 @@ def test_long_graph_visualize(sagemaker_session):
8590

8691
try:
8792
lq = sagemaker.lineage.query.LineageQuery(sagemaker_session)
88-
lq_result = lq.query(start_arns=[long_graph_root_arn], direction=LineageQueryDirectionEnum.DESCENDANTS)
93+
lq_result = lq.query(
94+
start_arns=[long_graph_root_arn], direction=LineageQueryDirectionEnum.DESCENDANTS
95+
)
8996
# max depth = 10 -> graph rendered only has length of ten (in DESCENDANTS direction)
9097
lq_result.visualize(path="longGraph.html")
9198
except Exception as e:
9299
print(e)
93100
lineage_resource_helper.clean_all()
94101
assert False
95102

96-
lineage_resource_helper.clean_all()
103+
lineage_resource_helper.clean_all()
104+
105+
106+
def test_graph_visualize(sagemaker_session):
107+
lineage_resource_helper = LineageResourceHelper(sagemaker_session=sagemaker_session)
108+
109+
# create lineage data
110+
# image artifact ------> model artifact(startarn) -> model deploy action -> endpoint context
111+
# /->
112+
# dataset artifact -/
113+
try:
114+
graph_startarn = lineage_resource_helper.create_artifact(
115+
artifact_name=name(), artifact_type="Model"
116+
)
117+
image_artifact = lineage_resource_helper.create_artifact(
118+
artifact_name=name(), artifact_type="Image"
119+
)
120+
lineage_resource_helper.create_association(
121+
source_arn=image_artifact, dest_arn=graph_startarn, association_type="ContributedTo"
122+
)
123+
dataset_artifact = lineage_resource_helper.create_artifact(
124+
artifact_name=name(), artifact_type="DataSet"
125+
)
126+
lineage_resource_helper.create_association(
127+
source_arn=dataset_artifact, dest_arn=graph_startarn, association_type="AssociatedWith"
128+
)
129+
modeldeploy_action = lineage_resource_helper.create_action(
130+
action_name=name(), action_type="ModelDeploy"
131+
)
132+
lineage_resource_helper.create_association(
133+
source_arn=graph_startarn, dest_arn=modeldeploy_action, association_type="ContributedTo"
134+
)
135+
endpoint_context = lineage_resource_helper.create_context(
136+
context_name=name(), context_type="Endpoint"
137+
)
138+
lineage_resource_helper.create_association(
139+
source_arn=modeldeploy_action,
140+
dest_arn=endpoint_context,
141+
association_type="AssociatedWith",
142+
)
143+
time.sleep(1)
144+
except Exception as e:
145+
print(e)
146+
lineage_resource_helper.clean_all()
147+
assert False
148+
149+
# visualize
150+
try:
151+
lq = sagemaker.lineage.query.LineageQuery(sagemaker_session)
152+
lq_result = lq.query(start_arns=[graph_startarn])
153+
lq_result.visualize(path="testGraph.html")
154+
except Exception as e:
155+
print(e)
156+
lineage_resource_helper.clean_all()
157+
assert False
158+
159+
# check generated graph info
160+
try:
161+
fo = open("testGraph.html", "r")
162+
lines = fo.readlines()
163+
for line in lines:
164+
if "nodes = " in line:
165+
node = line
166+
if "edges = " in line:
167+
edge = line
168+
169+
# extract node data
170+
start = node.find("[")
171+
end = node.find("]")
172+
res = node[start + 1 : end].split("}, ")
173+
res = [i + "}" for i in res]
174+
res[-1] = res[-1][:-1]
175+
node_dict = [json.loads(i) for i in res]
176+
177+
# extract edge data
178+
start = edge.find("[")
179+
end = edge.find("]")
180+
res = edge[start + 1 : end].split("}, ")
181+
res = [i + "}" for i in res]
182+
res[-1] = res[-1][:-1]
183+
edge_dict = [json.loads(i) for i in res]
184+
185+
# check node number
186+
assert len(node_dict) == 5
187+
188+
# check startarn
189+
found_value = next(
190+
dictionary for dictionary in node_dict if dictionary["id"] == graph_startarn
191+
)
192+
assert found_value["color"] == "#146eb4"
193+
assert found_value["label"] == "Model"
194+
assert found_value["shape"] == "star"
195+
assert found_value["title"] == "Artifact"
196+
197+
# check image artifact
198+
found_value = next(
199+
dictionary for dictionary in node_dict if dictionary["id"] == image_artifact
200+
)
201+
assert found_value["color"] == "#146eb4"
202+
assert found_value["label"] == "Image"
203+
assert found_value["shape"] == "dot"
204+
assert found_value["title"] == "Artifact"
205+
206+
# check dataset artifact
207+
found_value = next(
208+
dictionary for dictionary in node_dict if dictionary["id"] == dataset_artifact
209+
)
210+
assert found_value["color"] == "#146eb4"
211+
assert found_value["label"] == "DataSet"
212+
assert found_value["shape"] == "dot"
213+
assert found_value["title"] == "Artifact"
214+
215+
# check modeldeploy action
216+
found_value = next(
217+
dictionary for dictionary in node_dict if dictionary["id"] == modeldeploy_action
218+
)
219+
assert found_value["color"] == "#88c396"
220+
assert found_value["label"] == "ModelDeploy"
221+
assert found_value["shape"] == "dot"
222+
assert found_value["title"] == "Action"
223+
224+
# check endpoint context
225+
found_value = next(
226+
dictionary for dictionary in node_dict if dictionary["id"] == endpoint_context
227+
)
228+
assert found_value["color"] == "#ff9900"
229+
assert found_value["label"] == "Endpoint"
230+
assert found_value["shape"] == "dot"
231+
assert found_value["title"] == "Context"
232+
233+
# check edge number
234+
assert len(edge_dict) == 4
235+
236+
# check image_artifact -> model_artifact(startarn) edge
237+
found_value = next(
238+
dictionary for dictionary in edge_dict if dictionary["from"] == image_artifact
239+
)
240+
assert found_value["to"] == graph_startarn
241+
assert found_value["title"] == "ContributedTo"
242+
243+
# check dataset_artifact -> model_artifact(startarn) edge
244+
found_value = next(
245+
dictionary for dictionary in edge_dict if dictionary["from"] == dataset_artifact
246+
)
247+
assert found_value["to"] == graph_startarn
248+
assert found_value["title"] == "AssociatedWith"
249+
250+
# check model_artifact(startarn) -> modeldeploy_action edge
251+
found_value = next(
252+
dictionary for dictionary in edge_dict if dictionary["from"] == graph_startarn
253+
)
254+
assert found_value["to"] == modeldeploy_action
255+
assert found_value["title"] == "ContributedTo"
256+
257+
# check modeldeploy_action -> endpoint_context edge
258+
found_value = next(
259+
dictionary for dictionary in edge_dict if dictionary["from"] == modeldeploy_action
260+
)
261+
assert found_value["to"] == endpoint_context
262+
assert found_value["title"] == "AssociatedWith"
263+
264+
except Exception as e:
265+
print(e)
266+
lineage_resource_helper.clean_all()
267+
assert False
268+
269+
# clean lineage data
270+
lineage_resource_helper.clean_all()

0 commit comments

Comments
 (0)