Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
indigo_2024.1_documentation:plugin_testing_tutorial [2024/10/18 14:33] – [Test File Structure] davel17indigo_2024.1_documentation:plugin_testing_tutorial [2024/10/21 18:51] (current) – [Folder Structure] davel17
Line 1: Line 1:
-====== Plugin Testing Tutorial ====== +====== Plugin Testing Guide ====== 
-Once you have developed a functioning plugin, it's a good idea to add automated methods to test your code before publishing updates. Code testing is considered a best practice, and Python provides built-in tools to help facilitate testing. There are many ways to formulate your tests, and this guide demonstrates only one way to do it. The approach described below has advantages within the Indigo plugin framework because it allows direct access to the IOM (Indigo Object Model). //**It is extremely important to become familiar with the IOM and Indigo plugin development before attempting to tackle this guide.**//+Once you've developed a functioning plugin, it's a good idea to add automated methods to test your code before publishing plugins and plugin updates. "Unit testingis considered a best practice, and Python provides built-in tools to help facilitate it. There are many ways to formulate unit tests, and this guide demonstrates one way to do it. The approach described below has advantages within the Indigo plugin framework because it allows direct access to the IOM (Indigo Object Model). //**It is extremely important to become familiar with the IOM and Indigo plugin development before attempting to tackle this guide.**//
  
 ===== Python Unit Testing ===== ===== Python Unit Testing =====
Line 6: Line 6:
  
 ===== Unit Testing Indigo Plugins ===== ===== Unit Testing Indigo Plugins =====
-Because Indigo runs plugins in a separate thread (to avoid having a misbehaving plugin bring down the whole system), plugin unit tests have to be constructed a little bit differently. For example, while some tests can be run in the "traditional" way, tests that need access to the IOM can't be run from within an IDE or from the command line without using the Indigo Integration API (which doesn't expose the full suite of IOM commands). However, it is possible to construct tests that do allow for full IOM access through the plugin itself.+Because Indigo runs plugins in a separate thread (to avoid having a misbehaving plugin bring down the whole system), plugin unit tests that need access to the IOM have to be constructed a little bit differently. For example, while some tests can be run in the "traditional" way, tests that need access to the IOM can't be run from within an IDE or from the command line without using the Indigo Integration API (which doesn't expose the full suite of IOM commands). However, it is possible to construct tests that do allow for full IOM access through the plugin itself.
  
 ==== Testing Elements ==== ==== Testing Elements ====
Line 12: Line 12:
   - The ''//unittest//'' library - this is a standard Python library and should be already available.   - The ''//unittest//'' library - this is a standard Python library and should be already available.
   - The ''//python-dotenv//'' library - used for creating and managing Python environment variables.   - The ''//python-dotenv//'' library - used for creating and managing Python environment variables.
-  - An IDE that supports unit testing - which not required, having an IDE that supports unit testing can be very helpful.+  - An IDE that supports unit testing - while not required, having an IDE that supports unit testing can be very helpful.
  
 === Testing Structure === === Testing Structure ===
Line 18: Line 18:
  
 === Environment Variables === === Environment Variables ===
-While optional, it is a good idea to create an environment variable framework that allows you to create and make references to elements of your development environment. Once you have installed ''//python-dotenv//'', create a ''//.ENV//'' file at the ''//Server Plugin//'' level of your plugin (or other location that Indigo's environment path search will find it). It is a plain text file. The advantage of using an environment file is that it is a great place to store references that are unique to your system and -- for shared development -- each developer can have their own individual environment. **<color #ed1c24>IMPORTANT!</color> Remember to add the ''//.ENV//'' file to your ''//.gitignore//'' list.**+While optional, it is a good idea to create an environment variable framework that allows you to create and make references to elements of your development environment. Once you have installed ''//python-dotenv//'', create a ''//.ENV//'' file at the ''//Server Plugin//'' level of your plugin (or another location that Indigo's environment path will search). It is a plain text file. The advantage of using an environment file is that it is a great place to store references that are unique to your system and -- for shared development -- each developer can have their own individual environment. **<color #ed1c24>IMPORTANT!</color> Remember to add the ''//.ENV//'' file to your ''//.gitignore//'' list.**
  
 .ENV file .ENV file
Line 30: Line 30:
  
 === Folder Structure === === Folder Structure ===
-While optional, it's probably best to organize your test files and keep them separate from your main plugin files. For the purposes of this tutorial, we will store them in a ''//Tests//'' subfolder of the ''//Server Plugin//'' folder. For example,+While optional, it's probably best to organize your test files and keep them separate from your main plugin files. For the purposes of this guide, we will store them in a ''//Tests//'' subfolder of the ''//Server Plugin//'' folder. For example,
  
 <code> <code>
Line 39: Line 39:
      |_ ...      |_ ...
 </code> </code>
-Of course, you can put them anywhere that your plugin can see them. Depending on your development environment, you may also want to add the ''//Tests//'' folder to your ''//.gitignore//'' file to reduce the footprint of your published plugin.+Of course, you can put them anywhere your plugin can see them. Depending on your development environment, you may also want to add the ''//Tests//'' folder to your ''//.gitignore//'' file to reduce the footprint of your published plugin.
  
 === Main Plugin === === Main Plugin ===
-You'll need to add a few things to your plugin to support this approach.+You'll need to add a few things to your plugin to support this testing approach.
   * A Plugin Action Item - add a plugin action to your Actions.xml file that will be used to run the tests. It is recommended that you hide the action so it's not visible to users.   * A Plugin Action Item - add a plugin action to your Actions.xml file that will be used to run the tests. It is recommended that you hide the action so it's not visible to users.
 <code> <code>
Line 71: Line 71:
  
 === Test File Structure === === Test File Structure ===
-This is where the bulk of your testing code will reside. You could add your tests directly to your plugin but, as mentioned above, it offers a way to segregate your testing code from your published plugin to reduce its footprint by adding them to your ''//.gitignore//'' file. There is, of course, wide latitude (and debate) on how to structure tests and this tutorial tries to evade all that and provide a simple example just to get you started.+This is where the bulk of your testing code will reside. You could add your tests directly to your plugin but, as mentioned above, it offers a way to segregate your testing code from your published plugin to reduce its footprint by adding them to your ''//.gitignore//'' file. There is, of course, wide latitude (and debate) on how to structure tests and this guide tries to evade all that and provide a simple example just to get you started.
  
   * an __init__() file - to make your Tests available for module level imports.   * an __init__() file - to make your Tests available for module level imports.
Line 77: Line 77:
  
 === Test File Structure === === Test File Structure ===
-The ''//test_my_plugin.py//'' file contains your testing code. If you're familiar with unit testing (which you should be if you're this deep in the tutorial), the structure of these tests can be as complex as you like. A simple example:+The ''//test_my_plugin.py//'' file contains your testing code. If you're familiar with unit testing (which you should be if you're this deep in the guide), the structure of these tests can be as complex as you like. A simple example:
  
 <code> <code>
Line 116: Line 116:
  
 Once you have your core testing framework established and functional, it's a good idea to get in the habit of adding new tests over time as plugin errors are identified. For example, if a user encounters a traceback error--in addition to fixing the source of the problem--add a new unit test that will help you catch future errors before any other users encounter them. Once you have your core testing framework established and functional, it's a good idea to get in the habit of adding new tests over time as plugin errors are identified. For example, if a user encounters a traceback error--in addition to fixing the source of the problem--add a new unit test that will help you catch future errors before any other users encounter them.
 +
 +=== Running Your Tests ===
 +Once you have your tests written, you'll need a way to run them. The easiest way is to create an Action item in the Indigo UI to call your (hidden) testing action. This can easily be done with a short embedded script:
 +
 +<code>
 +plugin_id = "com.some.indigo.plugin"
 +plugin = indigo.server.getPlugin(plugin_id)
 +
 +try:
 +    if indigo.PluginInfo.isRunning(plugin):
 +        plugin.executeAction("my_tests")
 +    else:
 +        indigo.server.log("Plugin not enabled.")
 +except Exception as error:
 +    indigo.server.log(f"{error}")
 +</code>
 +
 +That's all you need to run tests that access the IOM. If all went according to plan, you should see something like:
 +<code>
 +   Action Group                    Unit Test - Run My Tests
 +   My Indigo Plugin                Execute Action tests passed.
 +   My Indigo Plugin                Device creation tests passed.
 +   My Indigo Plugin                JSON parse tests passed.
 +   ...
 +</code>
 +=== Even More Tests ===
 +You can, of course, build tests that run independent of the IOM such as: 
 +  * testing the structure of supporting files (like a constants file), or 
 +  * using Indigo's integrations API for remote plugin testing. 
 +
 +These approaches are a bit more "traditional", can often be run directly inside an IDE, and are beyond the scope of this guide. 
  • /www/perceptive/wiki/data/attic/indigo_2024.1_documentation/plugin_testing_tutorial.1729262038.txt.gz
  • Last modified: 2024/10/18 14:33
  • by davel17