This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
TestingBase is a git submodule providing shared testing infrastructure for Indigo plugin repos. It is mounted at tests/shared in consumer repos. It communicates with a running Indigo Server via its HTTP API and the local indigo-host CLI tool.
Dependencies listed in module-requirements.txt:
pip install python-dotenv httpx==0.25.2
Tests live in the consumer repo (e.g. WebServerPlugin/tests/), not in this repo. Tests are run from the consumer repo's tests/ directory:
python -m unittest test_something.py # run a test file
python -m unittest test_something.TestClass # run a test class
python -m unittest test_something.TestClass.test_method # run a single test__init__.py— exportsAPIBase,WebhookStatusCode, andValidateXmlFilefromclasses.py; exportsHTTP_CODES,CURL_CODES,DEVICE_FILTERS, andDIALOG_FIELD_TYPESfromconstants.pyclasses.py— core classes:APIBase(abstractunittest.TestCasesubclass),WebhookStatusCodeenum, andValidateXmlFile(abstract base for XML validation tests)constants.py— shared constant mappings:HTTP_CODES,CURL_CODES,DEVICE_FILTERS,DIALOG_FIELD_TYPESutils.py— standalone utility functionsexample_test_xml_files.py— example/reference file showing how to useValidateXmlFile; not included in__init__.pyand not meant to be run directly
Abstract base class combining unittest.TestCase and ABC. All API interaction methods are class methods (accessible as self.method() in tests).
Setup flow:
__init__loads.envviapython-dotenv(default path:../relative to test file, configurable)setUpClassreads shared env vars and setscls.good_api_key,cls.url_prefix,cls.api_prefix,cls.plugin_id, etc.tearDownmust callsuper()— adds a 2-second sleep so logs flush before test summary
Key methods:
send_raw_message(message_dict)— POST to/v2/api/commandwith Bearer authsend_simple_command(message_id, message, object_id, parameters)— constructs and sends a command dictget_indigo_object(endpoint, obj_id)— GET from/v2/api/indigo.<endpoint>[/<obj_id>]set_variable(message_id, variable, new_value)— sendsindigo.variable.updateValuecommandsend_webhook(message_dict, webhook_id, bearer_token)— sends GET or POST to/webhook/<webhook_id>restart_plugin()— calls/usr/local/indigo/indigo-restart-pluginsubprocess_get_shared_env_var(var_name, expected_type, default)— readsshared.<var_name>from env_get_testcase_env_var(var_name, ...)— reads<module>.<TestClass>[.<method>].<var_name>from env
Env vars are namespaced. Copy ENV_TEMPLATE to .env in the consumer repo's tests/ directory:
shared.<VAR_NAME>— shared across all test cases (read by_get_shared_env_var)<module>.<TestClass>.<var_name>— test-class-specific (read by_get_testcase_env_var)<module>.<TestClass>.<method>.<var_name>— test-method-specific
Abstract base class for validating Indigo plugin XML files (e.g. Actions.xml, Devices.xml). Intended to be mixed in with APIBase. See example_test_xml_files.py for usage examples — copy the pattern into your consumer repo's test file:
class TestActionsXml(ValidateXmlFile, APIBase): # ValidateXmlFile must be first
server_plugin_dir_path = "/some/path/MyPlugin.indigoPlugin/Contents/Server Folder"
file_name = "Actions.xml"Class variables to set:
server_plugin_dir_path— path to the plugin's Server Folder (no trailing slash)file_name— XML file name (no leading slash)additional_http_return_codes(optional) — list of extra HTTP status codes to accept when validatingSupportURLelements; default set is 200–208; values in this list are added to that set
Setup flow:
setUpClassverifies the plugin dir,plugin.py, and XML file all exist; loadsplugin.pycontent intocls.plugin_lines
Shared constant mappings imported by classes.py and available via from shared import ...:
HTTP_CODES—{int: str}mapping of HTTP status codes to descriptionsCURL_CODES—{str: str}mapping of curl error codes to descriptionsDEVICE_FILTERS— list of valid IndigodeviceFilterstring valuesDIALOG_FIELD_TYPES— list of valid ConfigUIFieldtypeattribute values
Standalone functions that wrap Indigo server calls:
run_host_script(script)— executes a Python script in the localindigo-hostprocess (/usr/local/indigo/indigo-host -e <script>), returns stdout as stringget_install_folder()— returns install path viarun_host_script; cached incls._install_folderatsetUpClasstimestr_to_bool(val)/reverse_bool_str_value(val)— delegate to IOM viarun_host_scriptfor consistent boolean handlingwithin_time_tolerance(dt1, dt2, tolerance_seconds=1)— compares two datetimes within a tolerancecompare_dicts(dict1, dict2, exclude_keys)— dict equality with optional key exclusion
Performance note: Each run_host_script call spawns a new IPH3 process — cache results at setUpClass time when the same value is needed across multiple tests.
Update this submodule in a consumer repo:
git submodule update --recursive --remote tests/sharedDo not commit changes to this repo from consumer repos — changes should go through the canonical TestingBase repo.