Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add steps APIs to the testmonitor client #96

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6b57da8
add models needed for steps client
SSSantosh18 Feb 25, 2025
6718b60
add first version of client
SSSantosh18 Feb 25, 2025
68957e2
simplify delete api client request body
SSSantosh18 Feb 25, 2025
669cf74
correct the children attribute
SSSantosh18 Feb 25, 2025
703f35a
correct attribute names to snake case
SSSantosh18 Feb 25, 2025
a3f3924
make step id and result id required in request object base
SSSantosh18 Feb 26, 2025
a66f2b6
fix circular dependency
SSSantosh18 Feb 27, 2025
c42a4ff
fix url parameters error
SSSantosh18 Feb 27, 2025
1cd2fe5
move to testmonitor client
SSSantosh18 Feb 27, 2025
e1a53d8
update method name
SSSantosh18 Feb 27, 2025
5767928
update enum fields
SSSantosh18 Feb 27, 2025
da7c36d
fix lint and format
SSSantosh18 Feb 27, 2025
ab10b8f
add retry mechanism and exception docs
SSSantosh18 Feb 27, 2025
9593d4c
update model name
SSSantosh18 Mar 4, 2025
ffb6db9
update model name and type for consistency
SSSantosh18 Mar 4, 2025
00c96e0
fix query step values response
SSSantosh18 Mar 4, 2025
de82ea4
add integration tests hardcoded result
SSSantosh18 Mar 4, 2025
db80834
update model name
SSSantosh18 Mar 4, 2025
5793863
add example
SSSantosh18 Mar 4, 2025
d105f2c
fix lint issues
SSSantosh18 Mar 4, 2025
624392c
update models
SSSantosh18 Mar 4, 2025
1181821
fix mypy types error
SSSantosh18 Mar 4, 2025
18b4996
Merge branch 'master' of https://github.com/ni/nisystemlink-clients-p…
SSSantosh18 Mar 5, 2025
2a58408
minor doc update
SSSantosh18 Mar 5, 2025
1a336e9
docs update
Mar 5, 2025
5b3648c
fix: add result creation to test cases
Mar 5, 2025
3f89c51
status common
Mar 5, 2025
f06eed4
add optional for delete-steps return
Mar 5, 2025
4cd7d58
fix: lint
Mar 5, 2025
7a3aea5
fix: resolve comments
Mar 5, 2025
79e7013
rename word
Mar 5, 2025
4da33ad
fix: resolve comments
Mar 5, 2025
7842189
remove object sufix from class name
Mar 5, 2025
857f823
rename request models
Mar 5, 2025
bf437e6
Fix PR comments
Mar 6, 2025
8f19b55
fix pipeline failures and handle measurement data extra fields
Mar 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/api_reference/testmonitor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ nisystemlink.clients.testmonitor
.. automethod:: update_results
.. automethod:: delete_result
.. automethod:: delete_results
.. automethod:: create_steps
.. automethod:: query_steps
.. automethod:: query_step_values
.. automethod:: delete_steps
.. automethod:: delete_step
.. automethod:: update_steps
.. automethod:: get_steps
.. automethod:: get_step

.. automodule:: nisystemlink.clients.testmonitor.models
:members:
Expand Down
3 changes: 2 additions & 1 deletion docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ Overview
~~~~~~~~

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

When constructing a :class:`.TestMonitorClient`, you can pass an
:class:`.HttpConfiguration` (like one retrieved from the
Expand All @@ -271,6 +271,7 @@ default connection. The default connection depends on your environment.
With a :class:`.TestMonitorClient` object, you can:

* Create, update, query, and delete results
* Create, update, query, and delete steps

Examples
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to actually add your example reference down here

~~~~~~~~
Expand Down
115 changes: 115 additions & 0 deletions examples/testmonitor/steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from nisystemlink.clients.testmonitor import TestMonitorClient
from nisystemlink.clients.testmonitor.models import (
CreateMultipleStepsRequest,
CreateResultRequest,
CreateStepRequest,
NamedValue,
QueryStepsRequest,
QueryStepValuesRequest,
Status,
StepField,
StepIdResultIdPair,
UpdateMultipleStepsRequest,
UpdateStepRequest,
)


def create_test_result():
"""Create example result on your server."""
new_results = [
CreateResultRequest(
part_number="Example 123 AA",
program_name="Example Name",
host_name="Example Host",
status=Status.PASSED(),
keywords=["original keyword"],
properties={"original property key": "yes"},
)
]
create_response = client.create_results(new_results)
return create_response


# Server configuration is not required when used with Systemlink Client or run throught Jupyter on SLE
server_configuration = None

# # Example of setting up the server configuration to point to your instance of SystemLink Enterprise
# server_configuration = HttpConfiguration(
# server_uri="https://yourserver.yourcompany.com",
# api_key="YourAPIKeyGeneratedFromSystemLink",
# )

client = TestMonitorClient(configuration=server_configuration)

# create a result to attach the steps to
create_response = create_test_result()

# Create the step requests
result_id = create_response.results[0].result_id
step_requests = [
CreateStepRequest(
step_id="step1",
name="step1",
result_id=result_id,
inputs=[
NamedValue(name="Temperature", value="35"),
NamedValue(name="Voltage", value="5"),
],
),
CreateStepRequest(
step_id="step2",
name="step2",
result_id=result_id,
),
]

# Create the steps
create_response = client.create_steps(CreateMultipleStepsRequest(steps=step_requests))
created_steps = create_response.steps
print(create_response)

# You can query steps based on any field using DynamicLinq syntax.
# These are just some representative examples.
# Query based on result id
query_response = client.query_steps(
QueryStepsRequest(filter=f'resultId == "{result_id}"')
)
queried_steps = query_response.steps

# query step name using query step values
query_values_response = client.query_step_values(
QueryStepValuesRequest(
filter=f'resultId == "{result_id}"',
field=StepField.NAME,
)
)

# update the name of a step
update_response = client.update_steps(
UpdateMultipleStepsRequest(
steps=[
UpdateStepRequest(
step_id=step.step_id,
result_id=step.result_id,
name="updated name",
)
for step in created_steps
]
)
)

# delete all steps at once
delete_response = client.delete_steps(
steps=[
StepIdResultIdPair(step_id=step.step_id, result_id=step.result_id)
for step in queried_steps
]
)

create_response = client.create_steps(CreateMultipleStepsRequest(steps=step_requests))
created_steps = create_response.steps

# delete steps one by one
for step in created_steps:
if step.step_id and step.result_id:
client.delete_step(result_id=step.result_id, step_id=step.step_id)
166 changes: 164 additions & 2 deletions nisystemlink/clients/testmonitor/_test_monitor_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
CreateResultRequest,
UpdateResultRequest,
)
from uplink import Field, Query, retry, returns
from uplink import Field, Path, Query, retry, returns

from . import models

Expand All @@ -31,7 +31,7 @@ def __init__(self, configuration: Optional[core.HttpConfiguration] = None):
is used to obtain the configuration.

Raises:
ApiException: if unable to communicate with the Spec Service.
ApiException: if unable to communicate with the TestMonitor Service.
"""
if configuration is None:
configuration = core.HttpConfigurationManager.get_configuration()
Expand Down Expand Up @@ -197,3 +197,165 @@ def delete_results(
or provided an invalid argument.
"""
...

@post("steps")
def create_steps(
self, steps: models.CreateMultipleStepsRequest
) -> models.CreateStepsPartialSuccess:
"""Creates one or more steps.

Args:
steps: A list of steps to create.

Returns:
A list of steps that were successfully created and ones that failed to be created.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments.
"""
...

@post("delete-steps", args=[Field("steps")])
def delete_steps(
self, steps: List[models.StepIdResultIdPair]
) -> Optional[models.DeleteStepsPartialSuccess]:
"""Deletes one or more steps by global ID.

Args:
steps: A list of step IDs and result IDs. Note that these are the global IDs and not the
`step_id` that is local to a product and workspace.

Returns:
None if all deletes succeed otherwise a list of which IDs failed and which succeeded.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there
invalid arguments.
"""
...

@post("query-steps")
def query_steps(self, query: models.QueryStepsRequest) -> models.PagedSteps:
"""Queries for steps that match the filters.

Args:
query: The query contains a product ID as well as a filter for steps under that product.

Returns:
A list of steps that match the filter.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments.
"""
...

@post("update-steps")
def update_steps(
self, steps: models.UpdateMultipleStepsRequest
) -> models.UpdateStepsPartialSuccess:
"""Updates one or more steps.

Update requires that the version field matches the version being updated from.

Args:
steps: a list of steps that are to be updated. Must include the global ID and
each step being updated must match the version currently on the server.

Returns
A list of steps that were successfully updated and a list of ones that were not along
with error messages for updates that failed.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments.
"""
...

@get(
"steps",
args=[Query("continuationToken"), Query("take"), Query("returnCount")],
)
def get_steps(
self,
continuation_token: Optional[str] = None,
take: Optional[int] = None,
return_count: Optional[bool] = None,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we check if python bool works with c# type, when we pass it as query param @SSSantosh18 ?

) -> models.PagedSteps:
"""Reads a list of steps.

Args:
continuation_token: The token used to paginate steps.
take: The number of steps to get in this request.
return_count: Whether or not to return the total number of steps available.

Returns:
A list of steps.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments..
"""
...

@get("results/{resultId}/steps/{stepId}", args=[Path("resultId"), Path("stepId")])
def get_step(self, result_id: str, step_id: str) -> models.Step:
"""Gets a single step.

Args:
result_id: The resultId of the step to get.
step_id: The stepId of the step to get.

Returns:
The step.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments.
"""
...

@delete(
"results/{resultId}/steps/{stepId}",
args=[Path("resultId"), Path("stepId"), Query("updateResultTotalTime")],
)
def delete_step(
self,
result_id: str,
step_id: str,
update_result_total_time: Optional[bool] = False,
) -> None:
"""Deletes a single step.

Args:
result_id: The resultId of the step to delete.
step_id: The stepId of the step to delete.
update_result_total_time: Determine test result total time from the step total times.
Defaults to False.

Returns:
None

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments.
"""
...

@returns.json # type: ignore
@post("query-step-values")
def query_step_values(self, query: models.QueryStepValuesRequest) -> List[str]:
"""Queries values for a step field.

Args:
query: The query parameters.

Returns:
A list of values for the specified step field.

Raises:
ApiException: if unable to communicate with the `/nitestmonitor` service or if there are
invalid arguments.
"""
...
19 changes: 17 additions & 2 deletions nisystemlink/clients/testmonitor/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
from ._api_info import Operation, V2Operations, ApiInfo
from ._result import Result
from ._status import StatusType, Status
from ._step import Step, NamedValue, StepData
from ._paged_results import PagedResults
from ._paged_steps import PagedSteps
from ._delete_results_partial_success import DeleteResultsPartialSuccess
from ._delete_steps_partial_success import DeleteStepsPartialSuccess, StepIdResultIdPair
from ._create_results_partial_success import CreateResultsPartialSuccess
from ._create_steps_partial_success import CreateStepsPartialSuccess
from ._update_results_partial_success import UpdateResultsPartialSuccess
from ._delete_results_partial_success import DeleteResultsPartialSuccess
from ._paged_results import PagedResults
from ._update_steps_partial_success import UpdateStepsPartialSuccess
from ._create_result_request import CreateResultRequest
from ._create_steps_request import CreateMultipleStepsRequest, CreateStepRequest
from ._update_result_request import UpdateResultRequest
from ._update_steps_request import UpdateMultipleStepsRequest, UpdateStepRequest
from ._query_results_request import (
QueryResultsRequest,
QueryResultValuesRequest,
ResultField,
ResultProjection,
)
from ._query_steps_request import (
QueryStepsRequest,
QueryStepValuesRequest,
StepOrderBy,
StepField,
StepProjection,
StepResponseFormat,
)

# flake8: noqa
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from typing import List, Optional

from nisystemlink.clients.core import ApiError
from nisystemlink.clients.core._uplink._json_model import JsonModel
from nisystemlink.clients.testmonitor.models._create_steps_request import (
CreateStepRequest,
)
from nisystemlink.clients.testmonitor.models._step import Step


class CreateStepsPartialSuccess(JsonModel):
steps: List[Step]
"""The list of steps that were successfully created."""

failed: Optional[List[CreateStepRequest]] = None
"""The list of step requests that failed.

If this is `None`, then all steps were successfully created.
"""

error: Optional[ApiError] = None
"""Error messages for steps that were not created.

If this is `None`, then all steps were successfully created.
"""
Loading