Test managementΒΆ
To use a test management adapter, it must be installed in the directory for User Python libraries. The adapter can then be configured and used in ecu.test. Concrete steps for setup and configuration can be found here.
The specific description of the test management adapter interface is explained in the API documentation.
Info
When implementing your own GUI in ecu.test, you must always use the
ThreadDialog
to prevent the application from freezing.
Additional details are available in the TsShowDialogExample under
Utility Examples.
An example implementation for a test management adapter could look like this:
TmUserAdapterExample.py:
"""
This module contains an example of a user test management adapter. The source code of this
example can be found in the ecu.test installation directory under
``Templates/DefaultData/UserPyModules/TestManagement``.
A user test management adapter must be placed in the UserPyModules directory of the current
workspace. If the implementation of the active adapter is changed, it is necessary to reload the
UserPyModules via select *Extras -> Update user libraries* in ecu.test.
Hint: In case of failures prefer to raise errors instead of printing error messages.
Hint: When implementing your own GUI, you must always use the ThreadDialog to prevent the
application from freezing. An example implementation for using the ThreadDialog can be found in the
``Templates/DefaultData/Utilities/ExampleUtilities/ShowDialogExample`` subdirectory of the ecu.test
installation directory.
"""
from __future__ import annotations
from tts.core.api.internalApi.Api import Api
from tts.interface.testManagement import AbstractTmUserAdapter, TmObjectInfo
from .TmsRestClientExample import TmsRestClientExample
# Required so that ecu.test can discover this module and recognize it as a user test management
# adapter.
MODULE_TYPE = AbstractTmUserAdapter.MODULE_TYPE
class TmUserAdapterExample(AbstractTmUserAdapter):
__PROPERTY_AS_STR = 'Option 1'
__PROPERTY_AS_BOOL = 'Option 2'
__PROPERTY_AS_INT = 'Option 3'
__PROPERTY_AS_FLOAT = 'Option 4'
def __init__(self, properties: dict[str, int | str | float | bool | None]) -> None:
"""
This method is called on adapter creation. It can be used to start any external dependencies
needed by this adapter.
The properties contain the configured properties for the concrete adapter as a dictionary.
Key: The name of the property.
Value: The value for the property.
"""
self.__properties = properties
self.__objectApi = Api().ObjectApi
self.__tmsClient = TmsRestClientExample()
def __del__(self) -> None:
"""
This method is called when the instance is about to be destroyed. It can be used to dispose
external dependencies.
"""
if self.IsLoggedIn():
self.Logout()
@classmethod
def GetName(cls) -> str:
"""
The name of the user test management adapter.
This name is displayed in the test management configuration.
"""
return 'Test management user adapter example'
@classmethod
def GetAvailableProperties(cls) -> dict[str, dict]:
"""
Defines the properties available for the user test management adapter. These properties can
be configured in the test management configuration. The configured properties are passed to
the `__init__` method when this adapter is created.
Each property is identified by its name and described within its own dict containing
information on 'Description', 'Type' and 'Default'. Available types are:
'STRING', 'BOOL', 'INTEGER', 'FLOAT'.
"""
props: dict[str, dict] = {
TmUserAdapterExample.__PROPERTY_AS_STR: {
'Description': 'This is Option 1 with a string.',
'Type': 'STRING',
'Default': 'default value',
},
TmUserAdapterExample.__PROPERTY_AS_BOOL: {
'Description': 'This is Option 2 with a bool.',
'Type': 'BOOL',
'Default': False,
},
TmUserAdapterExample.__PROPERTY_AS_INT: {
'Description': 'This is Option 3 with a int.',
'Type': 'INTEGER',
'Default': 42,
},
TmUserAdapterExample.__PROPERTY_AS_FLOAT: {
'Description': 'This is Option 4 with a float.',
'Type': 'FLOAT',
'Default': 9.99999,
},
}
return props
def Login(self) -> bool:
"""
Log in to the test management system.
"""
self.__tmsClient.Login()
return True
def Logout(self) -> bool:
"""
Log out of the test management system.
"""
self.__tmsClient.Logout()
return True
def IsLoggedIn(self) -> bool:
"""
Returns if there is currently an active user logged in. Depending on that information,
actions will be activated in ecu.test.
"""
return self.__tmsClient.IsLoggedIn()
def ExportProject(self, filePaths: list[str]) -> None:
"""
Exports PRJ files to the test management system.
Convert here the ecu.test project to the specific tms object.
"""
for filePath in filePaths:
project = self.__objectApi.ProjectApi.OpenProject(filePath)
tmsObject = self.__ConvertToTmsObject(project)
newTmsId = self.__tmsClient.CreateItemAtTms(tmsObject)
project.SetTestSuiteId(newTmsId)
def ImportProject(self, targetDirectory: str, tmsIds: list[str]) -> None:
"""
Imports projects from test management system and saves it as PRJ files.
This method needs to contain:
- the selection of the project within the test management system
- the generation of the PRJ file using the ObjectApi.ProjectApi
The passed tms Ids are defined using the GUI in ecu.test. You can choose between a selection
and input mode. The selection mode uses FetchChildrenForProjectImport (if implemented) as
source.
"""
projectItemTypeId = 'TmsProjectId'
for tmsId in tmsIds:
tmsObject = self.__tmsClient.GetItemFromTms(tmsId)
# use the item type id of the tmsObject to decide if it is a project or not
if projectItemTypeId == tmsObject:
project = self.__objectApi.ProjectApi.CreateProject()
project.SetTestSuiteId(tmsId)
self.__ConvertToEcuTest(project, tmsObject)
project.Save(f'{targetDirectory}/myFancyProjectName_{tmsId}.prj')
else:
children = self.__tmsClient.GetChildrenForTmsId(tmsId)
# use the tms id's of the children
self.ImportProject(targetDirectory, children)
def ExportPackage(self, filePaths: list[str]) -> None:
"""
Exports PKG files to the test management system. Convert here the ecu.test packages to the
specific object.
"""
for filePath in filePaths:
package = self.__objectApi.PackageApi.OpenPackage(filePath)
tmsObject = self.__ConvertToTmsObject(package)
newTmsId = self.__tmsClient.CreateItemAtTms(tmsObject)
package.SetTestScriptId(newTmsId)
def ImportPackage(self, targetDirectory: str, tmsIds: list[str]) -> None:
"""
Imports packages from the test management system and saves it as PKG files.
This method needs to contain:
- the selection of the package within the test management system
- the generation of the PKG file using the ObjectApi.PackageApi.
The passed tms Ids are defined using the GUI in ecu.test. You can choose between a selection
and input mode. The selection mode uses FetchChildrenForPackageImport (if implemented) as
source.
"""
packageItemTypeId = 'TmsPackageId'
for tmsId in tmsIds:
tmsObject = self.__tmsClient.GetItemFromTms(tmsId)
# use the item type id of the tmsObject to decide if it is a package or not
if packageItemTypeId == tmsObject:
package = self.__objectApi.PackageApi.CreatePackage()
package.SetTestScriptId(tmsId)
self.__ConvertToEcuTest(package, tmsObject)
package.Save(f'{targetDirectory}/myFancyPackageName_{tmsId}.pkg')
else:
children = self.__tmsClient.GetChildrenForTmsId(tmsId)
# use the tms id's of the children
self.ImportPackage(targetDirectory, children)
def FetchChildrenForProjectImport(self, tmsId: str) -> list[TmObjectInfo]:
"""
Returns the direct children (only first level) for the test management object with the
specified tmsId. If the tmsId is empty the root objects are required. The result will be
displayed in the dialog to import projects. For the chosen projects ImportProject() will be
called.
"""
fetchedChildren = []
if tmsId:
children = self.__tmsClient.GetChildrenForTmsId(tmsId)
for child in children:
fetchedChildren.append(
TmObjectInfo(
'TestProjectChild',
f'TestProjectID_{child}',
{
'author': 'dummy guy',
'date': '30.02.2025',
'description': f'Child object {child} from tms that represents a project at ecu.test.',
},
),
)
else:
fetchedChildren.append(
TmObjectInfo(
'TestProject',
'TestProjectID_0',
{
'author': 'dummy guy',
'date': '30.02.2025',
'description': 'Object from tms that represents a project at ecu.test.',
},
),
)
return fetchedChildren
def FetchChildrenForPackageImport(self, tmsId: str) -> list[TmObjectInfo]:
"""
Returns the direct children (only first level) for the test management object with the
specified tmsId. If the tmsId is empty the root objects are required. The result will be
displayed in the dialog to import packages. For the chosen packages ImportPackage() will be
called.
"""
fetchedChildren = []
if tmsId:
children = self.__tmsClient.GetChildrenForTmsId(tmsId)
for child in children:
fetchedChildren.append(
TmObjectInfo(
'TestPackageChild',
f'TestPackageID_{child}',
{
'author': 'dummy guy',
'date': '30.02.2025',
'description': f'Child object {child} from tms that represents a package at ecu.test.',
},
)
)
else:
fetchedChildren.append(
TmObjectInfo(
'TestPackage',
'TestPackageID_0',
{
'author': 'dummy guy',
'date': '30.02.2025',
'description': 'Object from tms that represents a package at ecu.test.',
},
)
)
return fetchedChildren
def __ConvertToTmsObject(self, ecuTestObject: str) -> str:
print(f'Convert ecu.test object {ecuTestObject} to a tms object.')
return 'DummyTmsObject'
def __ConvertToEcuTest(self, targetEcuTestObject, tmsObject) -> None:
print(f'Convert tms object {tmsObject} to ecu.test object {targetEcuTestObject}')
TmsRestClientExample.py:
"""
This module contains an example of a user test management adapter. The source code of this
example can be found in the ecu.test installation directory under
``Templates/DefaultData/UserPyModules/TestManagement``.
A user test management adapter must be placed in the UserPyModules directory of the current
workspace. If the implementation of the active adapter is changed, it is necessary to reload the
UserPyModules via select *Extras -> Update user libraries* in ecu.test.
Hint: In case of failures prefer to raise errors instead of printing error messages.
"""
from __future__ import annotations
class TmsRestClientExample:
"""
Class that knows the concrete communication api (e.g. OpenAPI-client via Rest) to the test
management system.
"""
def __init__(self) -> None:
print('TMS: Setup concrete communication details to test management system.')
self.__isLoggedIn = False
def Login(self) -> None:
print('TMS: Process login.')
self.__isLoggedIn = True
def Logout(self) -> None:
print('TMS: Process logout.')
self.__isLoggedIn = False
def IsLoggedIn(self) -> bool:
return self.__isLoggedIn
def CreateItemAtTms(self, tmsObject: str) -> str:
print(f'TMS: Create new item at tms for {tmsObject}.')
return 'newTmsId'
def GetItemFromTms(self, tmsId: str) -> str:
print(f'TMS: Get item from tms for id {tmsId}.')
return 'DummyTmsItem'
def GetChildrenForTmsId(self, tmsId: str) -> list[str]:
print(f'TMS: Get children from tms for id {tmsId}.')
return ['Child1', 'Child2']