Skip to content

Commit 85a676d

Browse files
SSSantosh18Priyadarshini PiramanayagamSuganth SadaiyappanSSadaiyappan-NI
authored
feat: Add steps APIs to the testmonitor client (#96)
Signed-off-by: Santosh Srinivasulu <santosh.srinivasulu@emerson.com> Co-authored-by: Priyadarshini Piramanayagam <priydarshini.piramanayagam@emerson.com> Co-authored-by: Suganth Sadaiyappan <suganth.sadaiyappan@emerson.com> Co-authored-by: Suganth Sadaiyappan <135005314+SSadaiyappan-NI@users.noreply.github.com>
1 parent 62b1205 commit 85a676d

16 files changed

+1302
-9
lines changed

docs/api_reference/testmonitor.rst

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ nisystemlink.clients.testmonitor
1414
.. automethod:: update_results
1515
.. automethod:: delete_result
1616
.. automethod:: delete_results
17+
.. automethod:: create_steps
18+
.. automethod:: query_steps
19+
.. automethod:: query_step_values
20+
.. automethod:: delete_steps
21+
.. automethod:: delete_step
22+
.. automethod:: update_steps
23+
.. automethod:: get_steps
24+
.. automethod:: get_step
1725

1826
.. automodule:: nisystemlink.clients.testmonitor.models
1927
:members:

docs/getting_started.rst

+9-2
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ Overview
261261
~~~~~~~~
262262

263263
The :class:`.TestMonitorClient` class is the primary entry point of the Test Monitor API
264-
used to interact with test results (Results).
264+
used to interact with test results (Results) and test steps (Steps).
265265

266266
When constructing a :class:`.TestMonitorClient`, you can pass an
267267
:class:`.HttpConfiguration` (like one retrieved from the
@@ -271,12 +271,19 @@ default connection. The default connection depends on your environment.
271271
With a :class:`.TestMonitorClient` object, you can:
272272

273273
* Create, update, query, and delete results
274+
* Create, update, query, and delete steps
274275

275276
Examples
276277
~~~~~~~~
277278

278279
Create, query, update, and delete some results
279280

280-
.. literalinclude:: ../examples/result/results.py
281+
.. literalinclude:: ../examples/testmonitor/results.py
282+
:language: python
283+
:linenos:
284+
285+
Create, update, query, and delete steps
286+
287+
.. literalinclude:: ../examples/testmonitor/steps.py
281288
:language: python
282289
:linenos:

examples/testmonitor/steps.py

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
from nisystemlink.clients.testmonitor import TestMonitorClient
2+
from nisystemlink.clients.testmonitor.models import (
3+
CreateResultRequest,
4+
CreateStepRequest,
5+
NamedValue,
6+
QueryStepsRequest,
7+
QueryStepValuesRequest,
8+
StepField,
9+
StepIdResultIdPair,
10+
UpdateStepRequest,
11+
)
12+
from nisystemlink.clients.testmonitor.models._status import Status
13+
from nisystemlink.clients.testmonitor.models._step_data import Measurement, StepData
14+
15+
16+
def create_test_result():
17+
"""Create example result on your server."""
18+
new_results = [
19+
CreateResultRequest(
20+
part_number="Example 123 AA",
21+
program_name="Example Name",
22+
host_name="Example Host",
23+
status=Status.PASSED(),
24+
keywords=["original keyword"],
25+
properties={"original property key": "yes"},
26+
)
27+
]
28+
create_response = client.create_results(new_results)
29+
return create_response
30+
31+
32+
# Server configuration is not required when used with Systemlink Client or run throught Jupyter on SLE
33+
server_configuration = None
34+
35+
# # Example of setting up the server configuration to point to your instance of SystemLink Enterprise
36+
# server_configuration = HttpConfiguration(
37+
# server_uri="https://yourserver.yourcompany.com",
38+
# api_key="YourAPIKeyGeneratedFromSystemLink",
39+
# )
40+
41+
client = TestMonitorClient(configuration=server_configuration)
42+
43+
# create a result to attach the steps to
44+
create_response = create_test_result()
45+
46+
# Create the step requests
47+
result_id = create_response.results[0].result_id
48+
step_requests = [
49+
CreateStepRequest(
50+
step_id="step1",
51+
name="step1",
52+
result_id=result_id,
53+
inputs=[
54+
NamedValue(name="Temperature", value="35"),
55+
NamedValue(name="Voltage", value="5"),
56+
],
57+
),
58+
CreateStepRequest(
59+
step_id="step2",
60+
name="step2",
61+
result_id=result_id,
62+
),
63+
]
64+
65+
# Create the steps
66+
create_response = client.create_steps(steps=step_requests)
67+
created_steps = create_response.steps
68+
print(create_response)
69+
70+
# You can query steps based on any field using DynamicLinq syntax.
71+
# These are just some representative examples.
72+
# Query based on result id
73+
query_response = client.query_steps(
74+
QueryStepsRequest(filter=f'resultId == "{result_id}"')
75+
)
76+
queried_steps = query_response.steps
77+
78+
# query step name using query step values
79+
query_values_response = client.query_step_values(
80+
QueryStepValuesRequest(
81+
filter=f'resultId == "{result_id}"',
82+
field=StepField.NAME,
83+
)
84+
)
85+
86+
# update the data of the step
87+
# extra properties of the measurements will be converted to string if not already a string
88+
update_response = client.update_steps(
89+
steps=[
90+
UpdateStepRequest(
91+
step_id=step.step_id,
92+
result_id=step.result_id,
93+
data=StepData(
94+
text="My output string",
95+
parameters=[
96+
Measurement(
97+
name="Temperature",
98+
status="Passed",
99+
measurement="35",
100+
lowLimit="30",
101+
highLimit="40",
102+
units="C",
103+
comparisonType="Numeric",
104+
spec_id="spec1",
105+
spec_info={
106+
"specKey": 10
107+
}, # will be converted to string as '{"specKey": 10}'
108+
)
109+
],
110+
),
111+
)
112+
for step in created_steps
113+
]
114+
)
115+
116+
# delete all steps at once
117+
delete_response = client.delete_steps(
118+
steps=[
119+
StepIdResultIdPair(step_id=step.step_id, result_id=step.result_id)
120+
for step in queried_steps
121+
]
122+
)
123+
124+
create_response = client.create_steps(steps=step_requests)
125+
created_steps = create_response.steps
126+
127+
# delete steps one by one
128+
for step in created_steps:
129+
if step.step_id and step.result_id:
130+
client.delete_step(result_id=step.result_id, step_id=step.step_id)

nisystemlink/clients/testmonitor/_test_monitor_client.py

+189-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
CreateResultRequest,
1010
UpdateResultRequest,
1111
)
12-
from uplink import Field, Query, retry, returns
12+
from uplink import Field, Path, Query, retry, returns
1313

1414
from . import models
1515

@@ -31,7 +31,7 @@ def __init__(self, configuration: Optional[core.HttpConfiguration] = None):
3131
is used to obtain the configuration.
3232
3333
Raises:
34-
ApiException: if unable to communicate with the Spec Service.
34+
ApiException: if unable to communicate with the TestMonitor Service.
3535
"""
3636
if configuration is None:
3737
configuration = core.HttpConfigurationManager.get_configuration()
@@ -197,3 +197,190 @@ def delete_results(
197197
or provided an invalid argument.
198198
"""
199199
...
200+
201+
@post(
202+
"steps",
203+
args=[Field("steps"), Field("updateResultTotalTime")],
204+
)
205+
def create_steps(
206+
self,
207+
steps: List[models.CreateStepRequest],
208+
update_result_total_time: bool = False,
209+
) -> models.CreateStepsPartialSuccess:
210+
"""Creates one or more steps.
211+
212+
Args:
213+
steps: A list of steps to create.
214+
update_result_total_time: Determine test result total time from the step total times.
215+
Defaults to False.
216+
217+
Returns:
218+
A list of steps that were successfully created and ones that failed to be created.
219+
220+
Raises:
221+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
222+
invalid arguments.
223+
"""
224+
...
225+
226+
@post("delete-steps", args=[Field("steps")])
227+
def delete_steps(
228+
self, steps: List[models.StepIdResultIdPair]
229+
) -> Optional[models.DeleteStepsPartialSuccess]:
230+
"""Deletes one or more steps by global ID.
231+
232+
Args:
233+
steps: A list of step IDs and result IDs. Note that these are the global IDs and not the
234+
`step_id` that is local to a product and workspace.
235+
236+
Returns:
237+
None if all deletes succeed otherwise a list of which IDs failed and which succeeded.
238+
239+
Raises:
240+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there
241+
invalid arguments.
242+
"""
243+
...
244+
245+
@delete(
246+
"results/{resultId}/steps/{stepId}",
247+
args=[Path("resultId"), Path("stepId"), Query("updateResultTotalTime")],
248+
)
249+
def delete_step(
250+
self,
251+
result_id: str,
252+
step_id: str,
253+
update_result_total_time: Optional[bool] = False,
254+
) -> None:
255+
"""Deletes a single step.
256+
257+
Args:
258+
result_id: The resultId of the step to delete.
259+
step_id: The stepId of the step to delete.
260+
update_result_total_time: Determine test result total time from the step total times.
261+
Defaults to False.
262+
263+
Returns:
264+
None
265+
266+
Raises:
267+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
268+
invalid arguments.
269+
"""
270+
...
271+
272+
@post("query-steps")
273+
def query_steps(self, query: models.QueryStepsRequest) -> models.PagedSteps:
274+
"""Queries for steps that match the filters.
275+
276+
Args:
277+
query: The query contains a product ID as well as a filter for steps under that product.
278+
279+
Returns:
280+
A list of steps that match the filter.
281+
282+
Raises:
283+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
284+
invalid arguments.
285+
"""
286+
...
287+
288+
@post(
289+
"update-steps",
290+
args=[
291+
Field("steps"),
292+
Field("updateResultTotalTime"),
293+
Field("replaceKeywords"),
294+
Field("replaceProperties"),
295+
],
296+
)
297+
def update_steps(
298+
self,
299+
steps: List[models.UpdateStepRequest],
300+
update_result_total_time: bool = False,
301+
replace_keywords: bool = False,
302+
replace_properties: bool = False,
303+
) -> models.UpdateStepsPartialSuccess:
304+
"""Updates one or more steps.
305+
306+
Update requires that the version field matches the version being updated from.
307+
308+
Args:
309+
steps: a list of steps that are to be updated. Must include the global ID and
310+
each step being updated must match the version currently on the server.
311+
update_result_total_time: Determine test result total time from the step total times.
312+
Defaults to False.
313+
replace_keywords: Replace with existing keywords instead of merging them.
314+
Defaults to False.
315+
replace_properties: Replace with existing properties instead of merging them.
316+
Defaults to False.
317+
318+
Returns
319+
A list of steps that were successfully updated and a list of ones that were not along
320+
with error messages for updates that failed.
321+
322+
Raises:
323+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
324+
invalid arguments.
325+
"""
326+
...
327+
328+
@get(
329+
"steps",
330+
args=[Query("continuationToken"), Query("take"), Query("returnCount")],
331+
)
332+
def get_steps(
333+
self,
334+
continuation_token: Optional[str] = None,
335+
take: Optional[int] = None,
336+
return_count: Optional[bool] = None,
337+
) -> models.PagedSteps:
338+
"""Reads a list of steps.
339+
340+
Args:
341+
continuation_token: The token used to paginate steps.
342+
take: The number of steps to get in this request.
343+
return_count: Whether or not to return the total number of steps available.
344+
345+
Returns:
346+
A list of steps.
347+
348+
Raises:
349+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
350+
invalid arguments..
351+
"""
352+
...
353+
354+
@get("results/{resultId}/steps/{stepId}", args=[Path("resultId"), Path("stepId")])
355+
def get_step(self, result_id: str, step_id: str) -> models.Step:
356+
"""Gets a single step.
357+
358+
Args:
359+
result_id: The resultId of the step to get.
360+
step_id: The stepId of the step to get.
361+
362+
Returns:
363+
The step.
364+
365+
Raises:
366+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
367+
invalid arguments.
368+
"""
369+
...
370+
371+
@returns.json # type: ignore
372+
@post("query-step-values")
373+
def query_step_values(self, query: models.QueryStepValuesRequest) -> List[str]:
374+
"""Queries values for a step field.
375+
376+
Args:
377+
query: The query parameters.
378+
379+
Returns:
380+
A list of values for the specified step field.
381+
382+
Raises:
383+
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
384+
invalid arguments.
385+
"""
386+
...

0 commit comments

Comments
 (0)