From 05e177dd6880764be4c45afe29644fcd37dcd843 Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Wed, 6 Mar 2024 09:29:37 +0000 Subject: [PATCH 1/7] Version enum name wrong From f03313e856b573b54fd165eabe7aeb7e2ac1b80f Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Thu, 21 Mar 2024 11:00:56 +0000 Subject: [PATCH 2/7] Fix the unit tests --- src/wiotp/sdk/api/dsc/connectors.py | 10 +- src/wiotp/sdk/api/registry/diag.py | 5 +- src/wiotp/sdk/api/services/__init__.py | 16 +- src/wiotp/sdk/api/state/deviceTypes.py | 2 + src/wiotp/sdk/api/state/schemas.py | 1 - src/wiotp/sdk/api/state/thingTypes.py | 1 + src/wiotp/sdk/application/config.py | 9 +- src/wiotp/sdk/client.py | 4 +- src/wiotp/sdk/device/command.py | 10 +- src/wiotp/sdk/device/config.py | 2 + test/testUtils/__init__.py | 9 + test/test_api_actions.py | 10 +- test/test_api_dsc_cloudant.py | 4 +- test/test_api_dsc_db2.py | 4 +- test/test_api_dsc_eventstreams.py | 2 + test/test_api_dsc_postgres.py | 4 +- test/test_api_registry_devicetypes.py | 2 +- test/test_api_state_device_types.py | 8 +- test/test_api_state_eventTypes.py | 4 +- test/test_api_state_logical_interfaces.py | 4 +- test/test_api_state_physical_interfaces.py | 4 +- test/test_api_state_rules.py | 4 +- test/test_api_state_schemas.py | 4 +- test/test_api_state_thingState.py | 28 +- test/test_api_state_thing_types.py | 8 +- test/test_api_state_things.py | 2 +- test/test_api_usage.py | 1 + test/test_application_cfg.py | 23 +- test/test_codecs.py | 14 +- test/test_codecs_raw.py | 4 +- test/test_device_cfg.py | 11 +- test/test_state_utils.py | 528 +++++++++++---------- tox.ini | 35 ++ 33 files changed, 435 insertions(+), 342 deletions(-) create mode 100644 tox.ini diff --git a/src/wiotp/sdk/api/dsc/connectors.py b/src/wiotp/sdk/api/dsc/connectors.py index 667c5f3c..a8476495 100644 --- a/src/wiotp/sdk/api/dsc/connectors.py +++ b/src/wiotp/sdk/api/dsc/connectors.py @@ -79,16 +79,16 @@ def __init__(self, apiClient): def find(self, nameFilter=None, typeFilter=None, enabledFilter=None, serviceId=None): """ Gets the list of Historian connectors, they are used to configure the Watson IoT Platform to store IoT data in compatible services. - + Parameters: - + - nameFilter(string) - Filter the results by the specified name - typeFilter(string) - Filter the results by the specified type, Available values : cloudant, eventstreams - - enabledFilter(boolean) - Filter the results by the enabled flag + - enabledFilter(boolean) - Filter the results by the enabled flag - serviceId(string) - Filter the results by the service id - limit(number) - Max number of results returned, defaults 25 - bookmark(string) - used for paging through results - + Throws APIException on failure. """ @@ -106,7 +106,7 @@ def find(self, nameFilter=None, typeFilter=None, enabledFilter=None, serviceId=N def create(self, name, type, serviceId, timezone=None, description=None, enabled=None, configuration=None): """ - Create a connector for the organization in the Watson IoT Platform. + Create a connector for the organization in the Watson IoT Platform. The connector must reference the target service that the Watson IoT Platform will store the IoT data in. Parameters: - name (string) - Name of the service diff --git a/src/wiotp/sdk/api/registry/diag.py b/src/wiotp/sdk/api/registry/diag.py index cb618ffe..4dc509f2 100644 --- a/src/wiotp/sdk/api/registry/diag.py +++ b/src/wiotp/sdk/api/registry/diag.py @@ -11,10 +11,11 @@ import json from datetime import datetime from collections import defaultdict + try: - from collections.abc import MutableSequence + from collections.abc import MutableSequence except ImportError: - from collections import MutableSequence + from collections import MutableSequence from wiotp.sdk.exceptions import ApiException diff --git a/src/wiotp/sdk/api/services/__init__.py b/src/wiotp/sdk/api/services/__init__.py index 01b7d994..b4dca2ac 100644 --- a/src/wiotp/sdk/api/services/__init__.py +++ b/src/wiotp/sdk/api/services/__init__.py @@ -165,16 +165,16 @@ def __init__(self, apiClient): def find(self, nameFilter=None, typeFilter=None, bindingModeFilter=None, boundFilter=None): """ - Gets the list of services that the Watson IoT Platform can connect to. + Gets the list of services that the Watson IoT Platform can connect to. The list can include a mixture of services that are either bound or unbound. - + Parameters: - + - nameFilter(string) - Filter the results by the specified name - typeFilter(string) - Filter the results by the specified type, Available values : cloudant, eventstreams - bindingModeFilter(string) - Filter the results by the specified binding mode, Available values : automatic, manual - - boundFilter(boolean) - Filter the results by the bound flag - + - boundFilter(boolean) - Filter the results by the bound flag + Throws APIException on failure. """ @@ -192,9 +192,9 @@ def find(self, nameFilter=None, typeFilter=None, bindingModeFilter=None, boundFi def create(self, serviceBinding): """ - Create a new external service. - The service must include all of the details required to connect - and authenticate to the external service in the credentials property. + Create a new external service. + The service must include all of the details required to connect + and authenticate to the external service in the credentials property. Parameters: - serviceName (string) - Name of the service - serviceType (string) - must be either eventstreams or cloudant diff --git a/src/wiotp/sdk/api/state/deviceTypes.py b/src/wiotp/sdk/api/state/deviceTypes.py index fd6f1e9d..514a361a 100644 --- a/src/wiotp/sdk/api/state/deviceTypes.py +++ b/src/wiotp/sdk/api/state/deviceTypes.py @@ -21,6 +21,7 @@ from wiotp.sdk.api.state.logicalInterfaces import BaseLogicalInterface from wiotp.sdk.api.state.physicalInterfaces import PhysicalInterface + # ========================================================================= # Physical Interface for the Device Type # ========================================================================= @@ -166,6 +167,7 @@ def __init__(self, apiClient, deviceTypeId): # Mappings for the Device Type # ========================================================================= + # define the common properties found on most Rest API Items class DeviceTypeMapping(defaultdict): def __init__(self, **kwargs): diff --git a/src/wiotp/sdk/api/state/schemas.py b/src/wiotp/sdk/api/state/schemas.py index 638128b8..8a46e7a0 100644 --- a/src/wiotp/sdk/api/state/schemas.py +++ b/src/wiotp/sdk/api/state/schemas.py @@ -78,7 +78,6 @@ def __init__(self, apiClient): super(DraftSchemas, self).__init__(apiClient, Schema, IterableSchemaList, "api/v0002/draft/schemas") def create(self, name, schemaFileName, schemaContents, description): - """ Create a schema for the org. Returns: schemaId (string), response (object). diff --git a/src/wiotp/sdk/api/state/thingTypes.py b/src/wiotp/sdk/api/state/thingTypes.py index 5efd8494..75ccc0f3 100644 --- a/src/wiotp/sdk/api/state/thingTypes.py +++ b/src/wiotp/sdk/api/state/thingTypes.py @@ -179,6 +179,7 @@ def __init__(self, apiClient, thingTypeId): # Mappings for the Thing Type # ========================================================================= + # define the common properties found on most Rest API Items class ThingTypeMapping(defaultdict): def __init__(self, **kwargs): diff --git a/src/wiotp/sdk/application/config.py b/src/wiotp/sdk/application/config.py index 94fda852..7fd4b41e 100644 --- a/src/wiotp/sdk/application/config.py +++ b/src/wiotp/sdk/application/config.py @@ -18,9 +18,9 @@ class ApplicationClientConfig(defaultdict): def __init__(self, **kwargs): - if "auth" not in kwargs or kwargs["auth"] is None: + # previously quickstart supported unauthenticated connections but has been removed + if "auth" not in kwargs: raise ConfigurationException("Missing auth from configuration") - if "key" not in kwargs["auth"] or kwargs["auth"]["key"] is None: raise ConfigurationException("Missing auth.key from configuration") if "token" not in kwargs["auth"] or kwargs["auth"]["token"] is None: @@ -248,6 +248,11 @@ def parseEnvVars(): "auth": {"key": authKey, "token": authToken} } +<<<<<<< HEAD +======= + cfg["auth"] = {"key": authKey, "token": authToken} + +>>>>>>> 1ec819d (Fix the unit tests) return ApplicationClientConfig(**cfg) diff --git a/src/wiotp/sdk/client.py b/src/wiotp/sdk/client.py index 869727f2..33ec9f3e 100644 --- a/src/wiotp/sdk/client.py +++ b/src/wiotp/sdk/client.py @@ -132,7 +132,9 @@ def __init__( # paho 2.0.0 has a breaking change for callbacks to support both 2.0.0 and 1.x we need # to create a client in version1 mode if using 2.0.0 if pahoVersion >= "2.0.0": - self.client = paho.Client(paho.CallbackAPIVersion.VERSION1, self.clientId, transport=transport, clean_session=(not cleanStart)) + self.client = paho.Client( + paho.CallbackAPIVersion.VERSION1, self.clientId, transport=transport, clean_session=(not cleanStart) + ) else: self.client = paho.Client(self.clientId, transport=transport, clean_session=(not cleanStart)) diff --git a/src/wiotp/sdk/device/command.py b/src/wiotp/sdk/device/command.py index 6b21aa22..20424293 100644 --- a/src/wiotp/sdk/device/command.py +++ b/src/wiotp/sdk/device/command.py @@ -15,12 +15,12 @@ class Command: """ Represents a command sent to a device. - + # Parameters pahoMessage (?): ? - messageEncoderModules (dict): Dictionary of Python modules, keyed to the - message format the module should use. - + messageEncoderModules (dict): Dictionary of Python modules, keyed to the + message format the module should use. + # Attributes command (string): Identifies the command. format (string): The format can be any string, for example JSON. @@ -28,7 +28,7 @@ class Command: timestamp (datetime): The date and time of the event. # Raises - InvalidEventException: If the command was recieved on a topic that does + InvalidEventException: If the command was recieved on a topic that does not match the regular expression `iot-2/cmd/(.+)/fmt/(.+)` """ diff --git a/src/wiotp/sdk/device/config.py b/src/wiotp/sdk/device/config.py index f66a34a0..e9b02d12 100644 --- a/src/wiotp/sdk/device/config.py +++ b/src/wiotp/sdk/device/config.py @@ -216,6 +216,8 @@ def parseEnvVars(): "auth": {"token": authToken} } + cfg["auth"] = {"token": authToken} + return DeviceClientConfig(**cfg) diff --git a/test/testUtils/__init__.py b/test/testUtils/__init__.py index b20cddff..00afdd9a 100644 --- a/test/testUtils/__init__.py +++ b/test/testUtils/__init__.py @@ -10,6 +10,7 @@ import wiotp.sdk.application import pytest import os +import sys oneJobOnlyTest = pytest.mark.skipif( os.getenv("ONE_JOB_ONLY_TESTS", "true") == "false", @@ -17,6 +18,14 @@ ) +def isstring(s): + # if we use Python 3 + if sys.version_info[0] >= 3: + return isinstance(s, str) + else: + return isinstance(s, basestring) # noqa: F821 + + class AbstractTest(object): WIOTP_API_KEY = os.getenv("WIOTP_API_KEY") diff --git a/test/test_api_actions.py b/test/test_api_actions.py index 68f33af9..8adfbe3e 100644 --- a/test/test_api_actions.py +++ b/test/test_api_actions.py @@ -69,12 +69,6 @@ class TestActions(testUtils.AbstractTest): testActionName = "test-action-new" updated_action_name = testActionName + "-updated" - def isstring(self, s): - # if we use Python 3 - if sys.version_info[0] >= 3: - basestring = str - return isinstance(s, basestring) - # ========================================================================= # Set up services # ========================================================================= @@ -125,9 +119,9 @@ def checkAction(self, action, name, type, description, configuration, enabled): assert action.configuration[configElement] is not None assert action.enabled == enabled assert isinstance(action.created, datetime) - assert self.isstring(action.createdBy) + assert testUtils.isstring(action.createdBy) assert isinstance(action.updated, datetime) - assert self.isstring(action.updatedBy) + assert testUtils.isstring(action.updatedBy) def doesActionNameExist(self, name): for a in self.appClient.actions.find({"name": name}): diff --git a/test/test_api_dsc_cloudant.py b/test/test_api_dsc_cloudant.py index e3edfd4e..5b283902 100644 --- a/test/test_api_dsc_cloudant.py +++ b/test/test_api_dsc_cloudant.py @@ -12,11 +12,13 @@ import testUtils import time import pytest +import os from wiotp.sdk.api.services import CloudantServiceBindingCredentials, CloudantServiceBindingCreateRequest from wiotp.sdk.exceptions import ApiException @testUtils.oneJobOnlyTest +@pytest.mark.skipif(os.getenv("CLOUDANT_HOST", None) is None, reason="Cloudant host not specified") class TestDscCloudant(testUtils.AbstractTest): # ========================================================================= @@ -153,7 +155,7 @@ def testCreateService2(self): assert rule1.logicalInterfaceId == None assert rule1.columnMappings == None assert rule1.enabled == True - assert isinstance(rule1.id, str) + assert testUtils.isstring(rule1.id) assert isinstance(rule1.updated, datetime) assert isinstance(rule1.created, datetime) diff --git a/test/test_api_dsc_db2.py b/test/test_api_dsc_db2.py index 55964f91..dd162134 100644 --- a/test/test_api_dsc_db2.py +++ b/test/test_api_dsc_db2.py @@ -12,6 +12,7 @@ import testUtils import time import pytest +import os from wiotp.sdk.api.services import ( CloudantServiceBindingCredentials, CloudantServiceBindingCreateRequest, @@ -20,6 +21,7 @@ from wiotp.sdk.exceptions import ApiException +@pytest.mark.skipif(os.getenv("DB2_PASSWORD") is None, reason="DB2 settings not provided") @testUtils.oneJobOnlyTest class TestDscDb2(testUtils.AbstractTest): def checkDB2Service(self, service, name, description): @@ -170,7 +172,7 @@ def checkDB2ForwardingRule(self, createdRule, name, destination, description, lo assert createdRule.columnMappings == columnMappings assert createdRule.typeId == None assert createdRule.eventId == None - assert isinstance(createdRule.id, str) + assert testUtils.isstring(createdRule.id) assert isinstance(createdRule.updated, datetime) assert isinstance(createdRule.created, datetime) diff --git a/test/test_api_dsc_eventstreams.py b/test/test_api_dsc_eventstreams.py index b6d07494..36b5fc43 100644 --- a/test/test_api_dsc_eventstreams.py +++ b/test/test_api_dsc_eventstreams.py @@ -12,11 +12,13 @@ import pytest import testUtils import time +import os from wiotp.sdk.api.services import EventStreamsServiceBindingCredentials, EventStreamsServiceBindingCreateRequest from wiotp.sdk.exceptions import ApiException +@pytest.mark.skipif(os.getenv("EVENTSTREAMS_API_KEY") is None, reason="Eventstreams details not test") @testUtils.oneJobOnlyTest class TestDscEventStreams(testUtils.AbstractTest): diff --git a/test/test_api_dsc_postgres.py b/test/test_api_dsc_postgres.py index 29bf13ff..735244c6 100644 --- a/test/test_api_dsc_postgres.py +++ b/test/test_api_dsc_postgres.py @@ -12,6 +12,7 @@ import testUtils import time import pytest +import os from wiotp.sdk.api.services import ( CloudantServiceBindingCredentials, CloudantServiceBindingCreateRequest, @@ -21,6 +22,7 @@ from wiotp.sdk.exceptions import ApiException +@pytest.mark.skipif(os.getenv("POSTGRES_DATABASE") is None, reason="postgres database not specified") @testUtils.oneJobOnlyTest class TestDscPostgres(testUtils.AbstractTest): def checkPostgresService(self, service, name, description): @@ -173,7 +175,7 @@ def checkPostgresForwardingRule( assert createdRule.columnMappings == columnMappings assert createdRule.typeId == None assert createdRule.eventId == None - assert isinstance(createdRule.id, str) + assert testUtils.isstring(createdRule.id) assert isinstance(createdRule.updated, datetime) assert isinstance(createdRule.created, datetime) diff --git a/test/test_api_registry_devicetypes.py b/test/test_api_registry_devicetypes.py index 0ffdfacd..02d61fa1 100644 --- a/test/test_api_registry_devicetypes.py +++ b/test/test_api_registry_devicetypes.py @@ -155,4 +155,4 @@ def testDeleteTypeId(self, device, deviceType): {"id": typeId, "description": "This is still a test", "metadata": {"test": "test"}} ) self.appClient.registry.devicetypes.delete(typeId) - assert typeId not in deviceType.devices \ No newline at end of file + assert typeId not in deviceType.devices diff --git a/test/test_api_state_device_types.py b/test/test_api_state_device_types.py index 3bb53fe8..7c4c96c7 100644 --- a/test/test_api_state_device_types.py +++ b/test/test_api_state_device_types.py @@ -16,7 +16,7 @@ import string import json import sys -from test_state_utils import TestStateUtils +import test_state_utils as TestStateUtils @testUtils.oneJobOnlyTest @@ -87,12 +87,6 @@ def testCleanup(self): self.appClient, (TestDeviceTypes.testEventSchemaName, TestDeviceTypes.testLiSchemaName) ) - def isstring(self, s): - # if we use Python 3 - if sys.version_info[0] >= 3: - basestring = str - return isinstance(s, basestring) - def createAndCheckDT( self, name, description, deviceInfo=None, metadata=None, edgeConfiguration=None, classId="Device" ): diff --git a/test/test_api_state_eventTypes.py b/test/test_api_state_eventTypes.py index 98adfefd..504e5824 100644 --- a/test/test_api_state_eventTypes.py +++ b/test/test_api_state_eventTypes.py @@ -62,9 +62,9 @@ def checkEventType(self, eventType, name, description, schemaId): assert eventType.version == "draft" assert isinstance(eventType.created, datetime) - assert isinstance(eventType.createdBy, str) + assert testUtils.isstring(eventType.createdBy) assert isinstance(eventType.updated, datetime) - assert isinstance(eventType.updatedBy, str) + assert testUtils.isstring(eventType.updatedBy) def doesSchemaNameExist(self, name): for a in self.appClient.state.draft.schemas.find({"name": name}): diff --git a/test/test_api_state_logical_interfaces.py b/test/test_api_state_logical_interfaces.py index 6258d52d..58d96ecd 100644 --- a/test/test_api_state_logical_interfaces.py +++ b/test/test_api_state_logical_interfaces.py @@ -66,9 +66,9 @@ def checkLI(self, logicalInterface, name, description, schemaId, version, alias) assert logicalInterface.alias == alias assert isinstance(logicalInterface.created, datetime) - assert isinstance(logicalInterface.createdBy, str) + assert testUtils.isstring(logicalInterface.createdBy) assert isinstance(logicalInterface.updated, datetime) - assert isinstance(logicalInterface.updatedBy, str) + assert testUtils.isstring(logicalInterface.updatedBy) def doesSchemaNameExist(self, name): for a in self.appClient.state.draft.schemas.find({"name": name}): diff --git a/test/test_api_state_physical_interfaces.py b/test/test_api_state_physical_interfaces.py index 2057cf25..0ce93592 100644 --- a/test/test_api_state_physical_interfaces.py +++ b/test/test_api_state_physical_interfaces.py @@ -72,9 +72,9 @@ def checkPI(self, physicalInterface, name, description): assert physicalInterface.description == description assert isinstance(physicalInterface.created, datetime) - assert isinstance(physicalInterface.createdBy, str) + assert testUtils.isstring(physicalInterface.createdBy) assert isinstance(physicalInterface.updated, datetime) - assert isinstance(physicalInterface.updatedBy, str) + assert testUtils.isstring(physicalInterface.updatedBy) def doesSchemaNameExist(self, name): for a in self.appClient.state.draft.schemas.find({"name": name}): diff --git a/test/test_api_state_rules.py b/test/test_api_state_rules.py index 5b2be47a..b858726a 100644 --- a/test/test_api_state_rules.py +++ b/test/test_api_state_rules.py @@ -71,9 +71,9 @@ def checkRule(self, rule, name, description, logicalInterfaceId, condition, noti assert rule.notificationStrategy == notificationStrategy assert isinstance(rule.created, datetime) - assert isinstance(rule.createdBy, str) + assert testUtils.isstring(rule.createdBy) assert isinstance(rule.updated, datetime) - assert isinstance(rule.updatedBy, str) + assert testUtils.isstring(rule.updatedBy) def doesSchemaNameExist(self, name): for a in self.appClient.state.draft.schemas.find({"name": name}): diff --git a/test/test_api_state_schemas.py b/test/test_api_state_schemas.py index f6d83638..460b75db 100644 --- a/test/test_api_state_schemas.py +++ b/test/test_api_state_schemas.py @@ -73,9 +73,9 @@ def checkSchema(self, schema, name, schemaFileName, schemaContents, description, assert schema.version == version assert isinstance(schema.created, datetime) - assert isinstance(schema.createdBy, str) + assert testUtils.isstring(schema.createdBy) assert isinstance(schema.updated, datetime) - assert isinstance(schema.updatedBy, str) + assert testUtils.isstring(schema.updatedBy) def doesDraftSchemaNameExist(self, name): for a in self.appClient.state.draft.schemas.find({"name": name}): diff --git a/test/test_api_state_thingState.py b/test/test_api_state_thingState.py index 61054277..fdf5edcf 100644 --- a/test/test_api_state_thingState.py +++ b/test/test_api_state_thingState.py @@ -14,7 +14,7 @@ import pytest import string import json -from test_state_utils import TestStateUtils +import test_state_utils as TestStateUtils @testUtils.oneJobOnlyTest @@ -115,7 +115,7 @@ def testCleanup(self): # delete any left over logical interfaces for li in self.appClient.state.draft.logicalInterfaces: - if li.name == TestThing.testLogicalInterfaceName: + if li.name in (TestThing.testLogicalInterfaceName, TestThing.testThingLISchema): print("Deleting old test LI: %s" % (li)) del self.appClient.state.draft.logicalInterfaces[li.id] @@ -131,7 +131,12 @@ def testCleanup(self): del self.appClient.state.draft.eventTypes[et.id] for s in self.appClient.state.draft.schemas: - if s.name in (TestThing.testEventSchemaName, TestThing.testLiSchemaName): + if s.name in ( + TestThing.testEventSchemaName, + TestThing.testLiSchemaName, + TestThing.thingLISchemaName, + TestThing.thingSchemaName, + ): print("Deleting old test schema instance: %s" % (s)) del self.appClient.state.draft.schemas[s.id] @@ -333,7 +338,7 @@ def testCreatePreReqs(self): } # create thing type schema - thingSchema = TestStateUtils.createSchema( + TestThing.createdThingSchema = TestStateUtils.createSchema( self.appClient, TestThing.thingSchemaName, "liThingSchema.json", @@ -343,7 +348,7 @@ def testCreatePreReqs(self): # create and check thing type TestThing.createdTT = self.createAndCheckTT( - TestThing.thingTypeId, "temperature type", "Test Device Type description", thingSchema.id + TestThing.thingTypeId, "temperature type", "Test Device Type description", TestThing.createdThingSchema.id ) testThingTypeLISchema = { @@ -356,7 +361,7 @@ def testCreatePreReqs(self): } # create thing type LI schema - thingLISchema = TestStateUtils.createSchema( + TestThing.createdThingLISchema = TestStateUtils.createSchema( self.appClient, TestThing.thingLISchemaName, "liThingSchema.json", @@ -366,7 +371,7 @@ def testCreatePreReqs(self): # Create a Logical Interface TestThing.createdThingLI = self.createLI( - TestThing.testThingLISchema, "Test Logical Interface description", thingLISchema.id + TestThing.testThingLISchema, "Test Logical Interface description", TestThing.createdThingLISchema.id ) # create logical interface for thingType @@ -493,9 +498,18 @@ def testDeletePreReqs(self): del self.appClient.state.draft.logicalInterfaces[TestThing.createdLI.id] assert self.doesLINameExist(TestThing.testLogicalInterfaceName) == False + # Delete the LI + del self.appClient.state.draft.logicalInterfaces[TestThing.createdThingLI.id] + assert self.doesLINameExist(TestThing.testThingLISchema) == False + # Delete the schema del self.appClient.state.draft.schemas[TestThing.createdLISchema.id] assert self.doesSchemaNameExist(TestThing.testLiSchemaName) == False + del self.appClient.state.draft.schemas[TestThing.createdThingSchema.id] + assert self.doesSchemaNameExist(TestThing.thingSchemaName) == False + del self.appClient.state.draft.schemas[TestThing.createdThingLISchema.id] + assert self.doesSchemaNameExist(TestThing.thingLISchemaName) == False + # diff --git a/test/test_api_state_thing_types.py b/test/test_api_state_thing_types.py index 7ea45fcb..9495b5bd 100644 --- a/test/test_api_state_thing_types.py +++ b/test/test_api_state_thing_types.py @@ -15,7 +15,7 @@ import string import json import sys -from test_state_utils import TestStateUtils +import test_state_utils as TestStateUtils @testUtils.oneJobOnlyTest @@ -104,12 +104,6 @@ def testCleanup(self): print("Deleting old test schema instance: %s" % (s)) del self.appClient.state.draft.schemas[s.id] - def isstring(self, s): - # if we use Python 3 - if sys.version_info[0] >= 3: - basestring = str - return isinstance(s, basestring) - def createAndCheckTT(self, id, name, description, schemaId, metadata=None): createdTT = TestStateUtils.createTT(self.appClient, id, name, description, schemaId, metadata) diff --git a/test/test_api_state_things.py b/test/test_api_state_things.py index 98df5828..6515cb42 100644 --- a/test/test_api_state_things.py +++ b/test/test_api_state_things.py @@ -16,7 +16,7 @@ import string import json from wiotp.sdk.api.registry.devices import DeviceUid, DeviceInfo, DeviceCreateRequest, DeviceLocation -from test_state_utils import TestStateUtils +import test_state_utils as TestStateUtils @testUtils.oneJobOnlyTest diff --git a/test/test_api_usage.py b/test/test_api_usage.py index 66cdc306..17f5ea8d 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -12,6 +12,7 @@ import testUtils from wiotp.sdk.api.usage import DayDataTransfer, DataTransferSummary + # @pytest.mark.skip(reason="See: https://github.ibm.com/wiotp/tracker/issues/1914") class TestRegistryUsage(testUtils.AbstractTest): diff --git a/test/test_application_cfg.py b/test/test_application_cfg.py index 26d85924..20f4ae28 100644 --- a/test/test_application_cfg.py +++ b/test/test_application_cfg.py @@ -89,13 +89,26 @@ def testCleanMustBeABoolean(self): ) assert e.value.reason == "Optional setting options.cleanSession must be a boolean if provided" - def testMissingArgs(self): + def testMissingAuth(self): with pytest.raises(wiotp.sdk.ConfigurationException) as e: - appCliInstance = wiotp.sdk.application.ApplicationClient({}) - assert ( - e.value.reason - == "Missing auth from configuration" + wiotp.sdk.application.ApplicationClient( + { + "identity": {"appId": "myAppId"}, + "options": {"mqtt": {"instanceId": "myInstance"}}, + } + ) + assert e.value.reason == "Missing auth from configuration" + + def testMissingOptionalArgs(self): + appId = str(uuid.uuid4()) + appCliInstance = wiotp.sdk.application.ApplicationClient( + { + "auth": {"key": os.getenv("WIOTP_API_KEY"), "token": os.getenv("WIOTP_API_TOKEN")}, + } ) + appCliInstance.connect() + assert appCliInstance.isConnected() == True + appCliInstance.disconnect() def testMissingConfigFile(self): applicationFile = "test/notAFile.yaml" diff --git a/test/test_codecs.py b/test/test_codecs.py index 33c200f3..0fb5ef14 100644 --- a/test/test_codecs.py +++ b/test/test_codecs.py @@ -23,12 +23,12 @@ class MyCodec(wiotp.sdk.MessageCodec): def encode(data=None, timestamp=None): """ Dedicated encoder for supporting a very specific dataset, serialises a dictionary object - of the following format: + of the following format: { - 'hello' : 'world', + 'hello' : 'world', 'x' : 10 } - + into a simple comma-seperated message: world,10 """ @@ -37,14 +37,14 @@ def encode(data=None, timestamp=None): @staticmethod def decode(message): """ - The decoder understands the comma-seperated format produced by the encoder and + The decoder understands the comma-seperated format produced by the encoder and allocates the two values to the correct keys: - + data['hello'] = 'world' data['x'] = 10 The MQTT message is a byte array, after splitting it convert to string and int - + """ (hello, x) = message.payload.decode("utf-8").split(",") @@ -68,7 +68,7 @@ class TestDevice(testUtils.AbstractTest): @classmethod def setup_class(self): if self.DEVICE_TYPE not in self.appClient.registry.devicetypes: - self.appClient.api.registry.devicetypes.create({"id": self.DEVICE_TYPE}) + self.appClient.registry.devicetypes.create({"id": self.DEVICE_TYPE}) self.registeredDevice = self.appClient.registry.devices.create( {"typeId": self.DEVICE_TYPE, "deviceId": self.DEVICE_ID} diff --git a/test/test_codecs_raw.py b/test/test_codecs_raw.py index 364919c0..1a47a5de 100644 --- a/test/test_codecs_raw.py +++ b/test/test_codecs_raw.py @@ -24,10 +24,12 @@ def __init__(self, object): # python 3 self.payload.extend(map(ord, object)) + class NonByteDummyPahoMessage(object): def __init__(self, object): self.payload = "not a byteArray" + class TestDevice(testUtils.AbstractTest): def testFileObject(self): cwd = os.getcwd() @@ -51,5 +53,3 @@ def testInvalidRawDecode(self): with pytest.raises(InvalidEventException) as e: message = RawCodec.decode(NonByteDummyPahoMessage("{sss,eee}")) assert e.value.reason == "Unable to decode message, it is not a bytearray" - - diff --git a/test/test_device_cfg.py b/test/test_device_cfg.py index b7c8c246..4a2728ab 100644 --- a/test/test_device_cfg.py +++ b/test/test_device_cfg.py @@ -11,6 +11,7 @@ import wiotp.sdk.device import testUtils import pytest +import os class TestDeviceCfg(testUtils.AbstractTest): @@ -58,7 +59,7 @@ def testPortNotInteger(self): wiotp.sdk.device.DeviceClient( { "identity": {"orgId": "myOrg", "typeId": "myType", "deviceId": "myDevice"}, - "auth": {"token": "myToken"}, + "auth": {"apikey": "myApp-myOrg", "token": "myToken"}, "options": {"mqtt": {"port": "notAnInteger"}}, } ) @@ -89,3 +90,11 @@ def testConfigFileWrongLogLevel(self): with pytest.raises(wiotp.sdk.ConfigurationException) as e: wiotp.sdk.device.parseConfigFile(deviceFile) assert e.value.reason == "Optional setting options.logLevel must be one of error, warning, info, debug" + + def testMissingOptionalArgs(self): + devCliInstance = wiotp.sdk.application.ApplicationClient( + {"auth": {"key": os.getenv("WIOTP_API_KEY"), "token": os.getenv("WIOTP_API_TOKEN")}} + ) # Attempting to connect without any arguments - testing the autofill + devCliInstance.connect() + assert devCliInstance.isConnected() == True + devCliInstance.disconnect() diff --git a/test/test_state_utils.py b/test/test_state_utils.py index b62f9bc1..7ae128e5 100644 --- a/test/test_state_utils.py +++ b/test/test_state_utils.py @@ -19,262 +19,272 @@ import sys -class TestStateUtils: - def deleteThingTypes(appClient, TTNameList): - # delete any left over device types - for tt in appClient.state.active.thingTypes: - # print("Device type instance: %s" % (dt)) - if tt.id in TTNameList: - for thing in tt.things: - print("Deleting things %s for active thing type instance: %s" % (thing.thingId, tt.id)) - del tt.devices[thing.thingId] - print("Deactivating old test thing type instance: %s" % (tt.id)) - appClient.state.active.thingTypes[tt.id].deactivate() - for tt in appClient.state.draft.thingTypes: - # print("Device type instance: %s" % (dt)) - if tt.id in TTNameList: - for thing in tt.things: - print("Deleting things %s for draft thing type instance: %s" % (thing.thingId, tt.id)) - del tt.devices[thing.thingId] - print("Deleting old test thing type instance: %s" % (tt.id)) - del appClient.state.draft.thingTypes[tt.id] - - -class TestStateUtils: - def deleteDeviceTypes(appClient, DTNameList): - # delete any left over device types - for dt in appClient.state.active.deviceTypes: - # print("Device type instance: %s" % (dt)) - if dt.id in DTNameList: - for dev in dt.devices: - print("Deleting devices %s for device type instance: %s" % (dev.deviceId, dt.id)) - del dt.devices[dev.deviceId] - print("Deleting old test device type instance: %s" % (dt.id)) - del appClient.state.active.deviceTypes[dt.id] - - def deleteDraftLIs(appClient, LINameList): - # delete any left over logical interfaces - for li in appClient.state.draft.logicalInterfaces: - if li.name in LINameList: - print("Deleting old test LI: %s" % (li)) - del appClient.state.draft.logicalInterfaces[li.id] - - def deleteDraftPIs(appClient, NameList): - # delete any left over physical interfaces, event type and schema - for pi in appClient.state.draft.physicalInterfaces: - if pi.name in NameList: - print("Deleting old test PI: %s" % (pi)) - del appClient.state.draft.physicalInterfaces[pi.id] - - def deleteDraftEventTypes(appClient, NameList): - for et in appClient.state.draft.eventTypes: - if et.name in NameList: - print("Deleting old test event type: %s" % (et)) - try: - del appClient.state.draft.eventTypes[et.id] - except: - print( - "Deleting old test event types could not be completed as the object is referenced by another resource" - ) - - def deleteDraftSchemas(appClient, NameList): - for s in appClient.state.draft.schemas: - if s.name in NameList: - print("Deleting old test schema instance: %s" % (s)) - try: - del appClient.state.draft.schemas[s.id] - except: - print( - "Deleting old test schema instances could not be completed as the object is referenced by another resource" - ) - - def isstring(s): - # if we use Python 3 - if sys.version_info[0] >= 3: - basestring = str - return isinstance(s, basestring) - - def checkDT( - deviceType, name, description, deviceInfo=None, metadata=None, edgeConfiguration=None, classId="Device" - ): - # print("Checking Device Type: %s" % (deviceType)) - assert deviceType.id == name - assert deviceType.description == description - assert deviceType.deviceInfo == deviceInfo - assert deviceType.metadata == metadata - assert deviceType.edgeConfiguration == edgeConfiguration - assert deviceType.classId == classId - - def checkTT(thingType, id, name, description, schemaId, metadata=None): - assert thingType.id == id - assert thingType.name == name - assert thingType.description == description - assert thingType.schemaId == schemaId - assert thingType.metadata == metadata - - def checkThing(thing, thingTypeId, thingId, name, description, aggregatedObjects, metadata=None): - assert thing.thingTypeId == thingTypeId - assert thing.thingId == thingId - assert thing.description == description - assert thing.name == name - assert thing.metadata == metadata - assert thing.aggregatedObjects == aggregatedObjects - - def checkMapping(mapping, logicalInterfaceId, notificationStrategy, propertyMappings, version="draft"): - # print("Checking Device Type: %s" % (deviceType)) - assert mapping.logicalInterfaceId == logicalInterfaceId - assert mapping.notificationStrategy == notificationStrategy - assert mapping.propertyMappings == propertyMappings - assert mapping.logicalInterfaceId == logicalInterfaceId - assert mapping.version == version - assert isinstance(mapping.created, datetime) - assert TestStateUtils.isstring(mapping.createdBy) - assert isinstance(mapping.updated, datetime) - assert TestStateUtils.isstring(mapping.updatedBy) - # TBD more needed here - - def doesSchemaNameExist(appClient, name): - for a in appClient.state.draft.schemas.find({"name": name}): - if a.name == name: - return True - return False - - def doesEventTypeNameExist(appClient, name): - for et in appClient.state.draft.eventTypes.find({"name": name}): - if et.name == name: - return True - return False - - def doesPINameExist(appClient, name): - for pi in appClient.state.draft.physicalInterfaces.find({"name": name}): - if pi.name == name: - return True - return False - - def doesLINameExist(appClient, name): - for li in appClient.state.draft.logicalInterfaces.find({"name": name}): - if li.name == name: - return True - return False - - def doesDTNameExist(appClient, name): - for dt in appClient.state.active.deviceTypes.find({"id": name}): - if dt.id == name: - return True - return False - - def doesTTNameExist(appClient, name): - for tt in appClient.state.draft.thingTypes.find({"id": name}): - if tt.id == name: - return True - return False - - def doesThingIdExist(appClient, thingTypeId, name): - for thing in appClient.state.active.thingTypes[thingTypeId].things: - if thing.thingId == name: - return True - return False - - def doesActiveSchemaNameExist(appClient, name): - for a in appClient.state.active.schemas.find({"name": name}): - if a.name == name: - return True - return False - - def doesActiveEventTypeNameExist(appClient, name): - for et in appClient.state.active.eventTypes.find({"name": name}): - if et.name == name: - return True - return False - - def doesActivePINameExist(appClient, name): - for pi in appClient.state.active.physicalInterfaces.find({"name": name}): - if pi.name == name: - return True - return False - - def doesActiveLINameExist(appClient, name): - for li in appClient.state.active.logicalInterfaces.find({"name": name}): - if li.name == name: - return True - return False - - def doesActiveDTNameExist(appClient, name): - for dt in appClient.state.active.deviceTypes.find({"id": name}): - if dt.id == name: - return True - return False - - def doesActiveTTNameExist(appClient, name): - for tt in appClient.state.active.thingTypes.find({"id": name}): - if tt.id == name: - return True - return False - - def createSchema(appClient, name, schemaFileName, schemaContents, description): - jsonSchemaContents = json.dumps(schemaContents) - createdSchema = appClient.state.draft.schemas.create(name, schemaFileName, jsonSchemaContents, description) - return createdSchema - - def createEventType(appClient, name, description, schemaId): - createdEventType = appClient.state.draft.eventTypes.create( - {"name": name, "description": description, "schemaId": schemaId} - ) - return createdEventType - - def createPI(appClient, name, description): - createdPI = appClient.state.draft.physicalInterfaces.create({"name": name, "description": description}) - return createdPI - - def comparePIs(PI1, PI2): - assert PI1.id == PI2.id - assert PI1.name == PI2.name - assert PI1.description == PI2.description - assert PI1.version == PI2.version - assert PI1.events == PI2.events - - def createLI(appClient, name, description, schemaId): - createdLI = appClient.state.draft.logicalInterfaces.create( - {"name": name, "description": description, "schemaId": schemaId} - ) - return createdLI - - def createDT( - appClient, name, description, deviceInfo=None, metadata=None, edgeConfiguration=None, classId="Device" - ): - payload = { - "id": name, - "description": description, - "deviceInfo": deviceInfo, - "metadata": metadata, - "classId": classId, - "edgeConfiguration": edgeConfiguration, - } - createdDT = appClient.state.active.deviceTypes.create(payload) - return createdDT - - def createTT(appClient, id, name, description, schemaId, metadata=None): - payload = {"id": id, "name": name, "description": description, "schemaId": schemaId, "metadata": metadata} - createdDT = appClient.state.draft.thingTypes.create(payload) - return createdDT - - def createThing(appClient, thingTypeId, thingId, name, description, aggregatedObjects, metadata=None): - payload = { - "thingTypeId": thingTypeId, - "thingId": thingId, - "name": name, - "description": description, - "aggregatedObjects": aggregatedObjects, - "metadata": metadata, - } - createdThing = appClient.state.active.thingTypes[thingTypeId].things.create(payload) - return createdThing - - def createMapping(appClient, deviceType, logicalInterfaceId, notificationStrategy, propertyMappings): - payload = { - "logicalInterfaceId": logicalInterfaceId, - "notificationStrategy": notificationStrategy, - "propertyMappings": propertyMappings, - } - createdMapping = deviceType.mappings.create(payload) - return createdMapping +def deleteDeviceTypes(appClient, DTNameList): + # delete any left over device types + for dt in appClient.state.active.deviceTypes: + # print("Device type instance: %s" % (dt)) + if dt.id in DTNameList: + for dev in dt.devices: + print("Deleting devices %s for device type instance: %s" % (dev.deviceId, dt.id)) + del dt.devices[dev.deviceId] + print("Deleting old test device type instance: %s" % (dt.id)) + del appClient.state.active.deviceTypes[dt.id] + + +def deleteDeviceTypes(appClient, DTNameList): + # delete any left over device types + for dt in appClient.state.active.deviceTypes: + # print("Device type instance: %s" % (dt)) + if dt.id in DTNameList: + for dev in dt.devices: + print("Deleting devices %s for device type instance: %s" % (dev.deviceId, dt.id)) + del dt.devices[dev.deviceId] + print("Deleting old test device type instance: %s" % (dt.id)) + del appClient.state.active.deviceTypes[dt.id] + + +def deleteDraftLIs(appClient, LINameList): + # delete any left over logical interfaces + for li in appClient.state.draft.logicalInterfaces: + if li.name in LINameList: + print("Deleting old test LI: %s" % (li)) + del appClient.state.draft.logicalInterfaces[li.id] + + +def deleteDraftPIs(appClient, NameList): + # delete any left over physical interfaces, event type and schema + for pi in appClient.state.draft.physicalInterfaces: + if pi.name in NameList: + print("Deleting old test PI: %s" % (pi)) + del appClient.state.draft.physicalInterfaces[pi.id] + + +def deleteDraftEventTypes(appClient, NameList): + for et in appClient.state.draft.eventTypes: + if et.name in NameList: + print("Deleting old test event type: %s" % (et)) + try: + del appClient.state.draft.eventTypes[et.id] + except: + print( + "Deleting old test event types could not be completed as the object is referenced by another resource" + ) + + +def deleteDraftSchemas(appClient, NameList): + for s in appClient.state.draft.schemas: + if s.name in NameList: + print("Deleting old test schema instance: %s" % (s)) + try: + del appClient.state.draft.schemas[s.id] + except: + print( + "Deleting old test schema instances could not be completed as the object is referenced by another resource" + ) + + +def checkDT(deviceType, name, description, deviceInfo=None, metadata=None, edgeConfiguration=None, classId="Device"): + # print("Checking Device Type: %s" % (deviceType)) + assert deviceType.id == name + assert deviceType.description == description + assert deviceType.deviceInfo == deviceInfo + assert deviceType.metadata == metadata + assert deviceType.edgeConfiguration == edgeConfiguration + assert deviceType.classId == classId + + +def checkTT(thingType, id, name, description, schemaId, metadata=None): + assert thingType.id == id + assert thingType.name == name + assert thingType.description == description + assert thingType.schemaId == schemaId + assert thingType.metadata == metadata + + +def checkThing(thing, thingTypeId, thingId, name, description, aggregatedObjects, metadata=None): + assert thing.thingTypeId == thingTypeId + assert thing.thingId == thingId + assert thing.description == description + assert thing.name == name + assert thing.metadata == metadata + assert thing.aggregatedObjects == aggregatedObjects + + +def checkMapping(mapping, logicalInterfaceId, notificationStrategy, propertyMappings, version="draft"): + # print("Checking Device Type: %s" % (deviceType)) + assert mapping.logicalInterfaceId == logicalInterfaceId + assert mapping.notificationStrategy == notificationStrategy + assert mapping.propertyMappings == propertyMappings + assert mapping.logicalInterfaceId == logicalInterfaceId + assert mapping.version == version + assert isinstance(mapping.created, datetime) + assert testUtils.isstring(mapping.createdBy) + assert isinstance(mapping.updated, datetime) + assert testUtils.isstring(mapping.updatedBy) + # TBD more needed here + + +def doesSchemaNameExist(appClient, name): + for a in appClient.state.draft.schemas.find({"name": name}): + if a.name == name: + return True + return False + + +def doesEventTypeNameExist(appClient, name): + for et in appClient.state.draft.eventTypes.find({"name": name}): + if et.name == name: + return True + return False + + +def doesPINameExist(appClient, name): + for pi in appClient.state.draft.physicalInterfaces.find({"name": name}): + if pi.name == name: + return True + return False + + +def doesLINameExist(appClient, name): + for li in appClient.state.draft.logicalInterfaces.find({"name": name}): + if li.name == name: + return True + return False + + +def doesDTNameExist(appClient, name): + for dt in appClient.state.active.deviceTypes.find({"id": name}): + if dt.id == name: + return True + return False + + +def doesTTNameExist(appClient, name): + for tt in appClient.state.draft.thingTypes.find({"id": name}): + if tt.id == name: + return True + return False + + +def doesThingIdExist(appClient, thingTypeId, name): + for thing in appClient.state.active.thingTypes[thingTypeId].things: + if thing.thingId == name: + return True + return False + + +def doesActiveSchemaNameExist(appClient, name): + for a in appClient.state.active.schemas.find({"name": name}): + if a.name == name: + return True + return False + + +def doesActiveEventTypeNameExist(appClient, name): + for et in appClient.state.active.eventTypes.find({"name": name}): + if et.name == name: + return True + return False + + +def doesActivePINameExist(appClient, name): + for pi in appClient.state.active.physicalInterfaces.find({"name": name}): + if pi.name == name: + return True + return False + + +def doesActiveLINameExist(appClient, name): + for li in appClient.state.active.logicalInterfaces.find({"name": name}): + if li.name == name: + return True + return False + + +def doesActiveDTNameExist(appClient, name): + for dt in appClient.state.active.deviceTypes.find({"id": name}): + if dt.id == name: + return True + return False + + +def doesActiveTTNameExist(appClient, name): + for tt in appClient.state.active.thingTypes.find({"id": name}): + if tt.id == name: + return True + return False + + +def createSchema(appClient, name, schemaFileName, schemaContents, description): + jsonSchemaContents = json.dumps(schemaContents) + createdSchema = appClient.state.draft.schemas.create(name, schemaFileName, jsonSchemaContents, description) + return createdSchema + + +def createEventType(appClient, name, description, schemaId): + createdEventType = appClient.state.draft.eventTypes.create( + {"name": name, "description": description, "schemaId": schemaId} + ) + return createdEventType + + +def createPI(appClient, name, description): + createdPI = appClient.state.draft.physicalInterfaces.create({"name": name, "description": description}) + return createdPI + + +def comparePIs(PI1, PI2): + assert PI1.id == PI2.id + assert PI1.name == PI2.name + assert PI1.description == PI2.description + assert PI1.version == PI2.version + assert PI1.events == PI2.events + + +def createLI(appClient, name, description, schemaId): + createdLI = appClient.state.draft.logicalInterfaces.create( + {"name": name, "description": description, "schemaId": schemaId} + ) + return createdLI + + +def createDT(appClient, name, description, deviceInfo=None, metadata=None, edgeConfiguration=None, classId="Device"): + payload = { + "id": name, + "description": description, + "deviceInfo": deviceInfo, + "metadata": metadata, + "classId": classId, + "edgeConfiguration": edgeConfiguration, + } + createdDT = appClient.state.active.deviceTypes.create(payload) + return createdDT + + +def createTT(appClient, id, name, description, schemaId, metadata=None): + payload = {"id": id, "name": name, "description": description, "schemaId": schemaId, "metadata": metadata} + createdDT = appClient.state.draft.thingTypes.create(payload) + return createdDT + + +def createThing(appClient, thingTypeId, thingId, name, description, aggregatedObjects, metadata=None): + payload = { + "thingTypeId": thingTypeId, + "thingId": thingId, + "name": name, + "description": description, + "aggregatedObjects": aggregatedObjects, + "metadata": metadata, + } + createdThing = appClient.state.active.thingTypes[thingTypeId].things.create(payload) + return createdThing + + +def createMapping(appClient, deviceType, logicalInterfaceId, notificationStrategy, propertyMappings): + payload = { + "logicalInterfaceId": logicalInterfaceId, + "notificationStrategy": notificationStrategy, + "propertyMappings": propertyMappings, + } + createdMapping = deviceType.mappings.create(payload) + return createdMapping diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..0cc54d10 --- /dev/null +++ b/tox.ini @@ -0,0 +1,35 @@ +# Tox (https://tox.readthedocs.io/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. +# +# tox -e py37 -- test/test_api_registry_devices.py +# +# Sometimes tox fails to install the module being developed ... if hit this again +# add the following line to commands list +# python setup.py install + +[tox] +envlist = py27, py38, py39, py311-paho161, py311-paho200 + +[testenv] +deps = + flake8 + nose + pytest + pytest-cov + coverage + py38: black + paho161: paho-mqtt==1.6.1 + paho200: paho-mqtt==2.0.0 +commands = + py38: pip install black + py38: black -l 120 src samples test + flake8 --count --select=E9,F63,F72,F82 --show-source --statistics src samples test + pytest --cov=wiotp.sdk {posargs} + python -c "import paho.mqtt; print(paho.mqtt.__version__)" +passenv = * + +[pytest] +minversion=2.0 +python_files=test/test_*.py test/testUtils/*.py From 17a5d8ceeb5cb7c0f821cb8c62c568a25c5ddfa8 Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Wed, 19 Jun 2024 08:30:51 +0100 Subject: [PATCH 3/7] change skip logic --- test/test_api_dsc_db2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_api_dsc_db2.py b/test/test_api_dsc_db2.py index dd162134..b418d5d5 100644 --- a/test/test_api_dsc_db2.py +++ b/test/test_api_dsc_db2.py @@ -21,7 +21,7 @@ from wiotp.sdk.exceptions import ApiException -@pytest.mark.skipif(os.getenv("DB2_PASSWORD") is None, reason="DB2 settings not provided") +@pytest.mark.skipif(os.getenv("DB2_PASSWORD") is None or os.getenv("DB2_PASSWORD") == "", reason="DB2 settings not provided") @testUtils.oneJobOnlyTest class TestDscDb2(testUtils.AbstractTest): def checkDB2Service(self, service, name, description): From 0caf7551bf28283dbfeec9d333ec560f436f8a55 Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Wed, 19 Jun 2024 08:35:38 +0100 Subject: [PATCH 4/7] missed merge conflict --- src/wiotp/sdk/application/config.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/wiotp/sdk/application/config.py b/src/wiotp/sdk/application/config.py index 7fd4b41e..9c24ad9d 100644 --- a/src/wiotp/sdk/application/config.py +++ b/src/wiotp/sdk/application/config.py @@ -248,11 +248,8 @@ def parseEnvVars(): "auth": {"key": authKey, "token": authToken} } -<<<<<<< HEAD -======= cfg["auth"] = {"key": authKey, "token": authToken} ->>>>>>> 1ec819d (Fix the unit tests) return ApplicationClientConfig(**cfg) From cdbf54743cd629436da700fe94520073b3196256 Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Wed, 19 Jun 2024 08:40:10 +0100 Subject: [PATCH 5/7] run pytest on branches --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 744c535b..8aec5a62 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -37,7 +37,7 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 src --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest (only on Python 3.11 to avoid concurrency issues) - if: ${{ (github.ref == 'refs/heads/master') && (matrix.primary-config == 'true') }} + if: ${{ matrix.primary-config == 'true' }} env: ONE_JOB_ONLY_TESTS: ${{ matrix.primary-config }} WIOTP_API_KEY: ${{ secrets.WIOTP_API_KEY }} From dcff7f26893e586b2999a111af73530e2c879481 Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Wed, 19 Jun 2024 08:43:40 +0100 Subject: [PATCH 6/7] Revert "change skip logic" This reverts commit 17a5d8ceeb5cb7c0f821cb8c62c568a25c5ddfa8. --- test/test_api_dsc_db2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_api_dsc_db2.py b/test/test_api_dsc_db2.py index b418d5d5..dd162134 100644 --- a/test/test_api_dsc_db2.py +++ b/test/test_api_dsc_db2.py @@ -21,7 +21,7 @@ from wiotp.sdk.exceptions import ApiException -@pytest.mark.skipif(os.getenv("DB2_PASSWORD") is None or os.getenv("DB2_PASSWORD") == "", reason="DB2 settings not provided") +@pytest.mark.skipif(os.getenv("DB2_PASSWORD") is None, reason="DB2 settings not provided") @testUtils.oneJobOnlyTest class TestDscDb2(testUtils.AbstractTest): def checkDB2Service(self, service, name, description): From c534efdf98df8f91338c66f0d4ff01a6c8dffccc Mon Sep 17 00:00:00 2001 From: Ian Boden Date: Thu, 20 Jun 2024 07:51:54 +0100 Subject: [PATCH 7/7] tidy up --- test/test_api_state_thingState.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_api_state_thingState.py b/test/test_api_state_thingState.py index fdf5edcf..4920c70f 100644 --- a/test/test_api_state_thingState.py +++ b/test/test_api_state_thingState.py @@ -41,7 +41,7 @@ class TestThing(testUtils.AbstractTest): testPhysicalInterfaceName = "python-api-test-dt-pi" # Logical Interface Stuff - testLiSchemaName = "python-api-test-dt-li-schema" + testLISchemaName = "python-api-test-dt-li-schema" testLISchema = { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -133,7 +133,7 @@ def testCleanup(self): for s in self.appClient.state.draft.schemas: if s.name in ( TestThing.testEventSchemaName, - TestThing.testLiSchemaName, + TestThing.testLISchemaName, TestThing.thingLISchemaName, TestThing.thingSchemaName, ): @@ -234,7 +234,7 @@ def createAndCheckDT( def testCreatePreReqs(self): # LI - test_schema_name = TestThing.testLiSchemaName + test_schema_name = TestThing.testLISchemaName assert self.doesSchemaNameExist(test_schema_name) == False testLIName = TestThing.testLogicalInterfaceName assert self.doesLINameExist(testLIName) == False @@ -443,9 +443,9 @@ def testResetThingState(self): def testThingStateErrors(self): # Check state for a non existent LI try: - dummyLiId = "DummyLI" - thingState = TestThing.createdThing.states[dummyLiId] - print("There should be no thing state for LI %s. We have: %s" % (dummyLiId, thingState)) + dummyLIId = "DummyLI" + thingState = TestThing.createdThing.states[dummyLIId] + print("There should be no thing state for LI %s. We have: %s" % (dummyLIId, thingState)) assert False == True # fail except KeyError as e: assert True # This is what we expect @@ -504,7 +504,7 @@ def testDeletePreReqs(self): # Delete the schema del self.appClient.state.draft.schemas[TestThing.createdLISchema.id] - assert self.doesSchemaNameExist(TestThing.testLiSchemaName) == False + assert self.doesSchemaNameExist(TestThing.testLISchemaName) == False del self.appClient.state.draft.schemas[TestThing.createdThingSchema.id] assert self.doesSchemaNameExist(TestThing.thingSchemaName) == False