From 5aae93e635618f836900ec10733c0f2b2fe1d642 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 10 Dec 2024 21:27:44 +0100 Subject: [PATCH] Added first example to plugin unit test (#8636) * Start documentation chapter for plugin tests * Added env variables to the doc * Fix style errors * Further style bugs * Reformat environment variables * Reformat environment variables * Add comments from wolflu05 * Add text to the intro * Added first example the plugin unit test * Addred line it function * Typo * Typo * Typo --- docs/docs/extend/plugins/test.md | 81 +++++++++++++++++++++++++ docs/mkdocs.yml | 1 + src/backend/InvenTree/.config.yaml.swp | Bin 16384 -> 0 bytes 3 files changed, 82 insertions(+) create mode 100644 docs/docs/extend/plugins/test.md delete mode 100644 src/backend/InvenTree/.config.yaml.swp diff --git a/docs/docs/extend/plugins/test.md b/docs/docs/extend/plugins/test.md new file mode 100644 index 000000000000..26dfbe496e37 --- /dev/null +++ b/docs/docs/extend/plugins/test.md @@ -0,0 +1,81 @@ +--- +Title: Unit Tests +--- + +## Unit Tests +For complicated plugins it makes sense to add unit tests the code to ensure +that plugins work correctly and are compatible with future versions too. +You can run these tests as part of your ci against the current stable and +latest tag to get notified when something breaks before it gets released as +part of stable. InvenTree offers a framework for testing. Please refer +to [Unit Tests](../../develop/contributing.md) for more information. + +### Prerequisites +For plugin testing the following environment variables must be set to True: + +| Name | Function | Value | +| --- | --- | --- | +| INVENTREE_PLUGINS_ENABLED | Enables the use of 3rd party plugins | True | +| INVENTREE_PLUGIN_TESTING | Enables enables all plugins no matter of their active state in the db or built-in flag | True | +| INVENTREE_PLUGIN_TESTING_SETUP | Enables the url mixin | True | + +### Test program + +A file called test_plugin_name.py should be added to the plugin directory. It can have the +following structure: + +``` +# Basic unit tests for the plugin +from InvenTree.unit_test import InvenTreeTestCase + +class TestMyPlugin(InvenTreeTestCase): + def test_my_function(self): + do some work here... +``` + +The test can be executed using invoke: + +``` +invoke dev.test -r module.file.class +``` + +Plugins are usually installed outside of the InventTree directory, e.g. in .local/lib/... +I that case module must be omitted. + +``` +invoke dev.test -r plugin_directory.test_plugin_name.TestMyPlugin +``` + +### do some work here... A simple Example +A simple example is shown here. Assume the plugin has a function that converts a price string +that comes from a supplier API to a float value. The price might have the form "1.456,34 €". +It can be different based on country and local settings. +The function in the plugin will convert it to a float 1456.34. It is in the class MySupplier +and has the following structure: + +``` +class MySupplier(): + + def reformat_price(self, string_price): + + ... + return float_price +``` + +This function needs to be tested. The test can look like this: + +``` +from .myplugin import MySupplier + +def test_reformat_price(self): + + self.assertEqual(MySupplier.reformat_price(self, '1.456,34 €'), 1456.34) + self.assertEqual(MySupplier.reformat_price(self, '1,45645 €'), 1.45645) + self.assertEqual(MySupplier.reformat_price(self, '1,56 $'), 1.56) + self.assertEqual(MySupplier.reformat_price(self, ''), 0) + self.assertEqual(MySupplier.reformat_price(self, 'Mumpitz'), 0) +``` + +The function assertEqual flags an error in case the two arguments are not equal. In equal case +no error is flagged and the test passes. The test function tests five different +input variations. More might be added based on the requirements. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f34173362746..86011269e523 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -199,6 +199,7 @@ nav: - Developing a Plugin: extend/how_to_plugin.md - Model Metadata: extend/plugins/metadata.md - Tags: extend/plugins/tags.md + - Unit Test: extend/plugins/test.md - Plugin Mixins: - Action Mixin: extend/plugins/action.md - API Mixin: extend/plugins/api.md diff --git a/src/backend/InvenTree/.config.yaml.swp b/src/backend/InvenTree/.config.yaml.swp deleted file mode 100644 index c9776e1c012b221ba59656cf75c03c7118dad53d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 Dy|To)