blob: 964046910810ca5ceb0e984d1dc889242f0a27b9 [file] [log] [blame]
Matthew Treinish3a851dc2015-07-30 11:34:03 -04001=============================
2Tempest Test Plugin Interface
3=============================
4
5Tempest has an external test plugin interface which enables anyone to integrate
6an external test suite as part of a tempest run. This will let any project
7leverage being run with the rest of the tempest suite while not requiring the
8tests live in the tempest tree.
9
10Creating a plugin
11=================
12
13Creating a plugin is fairly straightforward and doesn't require much additional
Andrea Frittoli (andreaf)1370baf2016-04-29 14:26:22 -050014effort on top of creating a test suite using tempest.lib. One thing to note with
Matthew Treinish3a851dc2015-07-30 11:34:03 -040015doing this is that the interfaces exposed by tempest are not considered stable
16(with the exception of configuration variables which ever effort goes into
17ensuring backwards compatibility). You should not need to import anything from
Kiall Mac Innes9e6f9742016-05-23 16:20:55 +010018tempest itself except where explicitly noted.
19
20Stable Tempest APIs plugins may use
21-----------------------------------
22
23As noted above, several tempest APIs are acceptable to use from plugins, while
24others are not. A list of stable APIs available to plugins is provided below:
25
26* tempest.lib.*
27* tempest.config
28* tempest.test_discover.plugins
29
30If there is an interface from tempest that you need to rely on in your plugin
31which is not listed above, it likely needs to be migrated to tempest.lib. In
32that situation, file a bug, push a migration patch, etc. to expedite providing
33the interface in a reliable manner.
Matthew Treinish3a851dc2015-07-30 11:34:03 -040034
Marc Koderer66210aa2015-10-26 10:52:32 +010035Plugin Cookiecutter
36-------------------
37
38In order to create the basic structure with base classes and test directories
39you can use the tempest-plugin-cookiecutter project::
40
Yuiko Takadaccb2bbf2015-11-17 10:09:44 +090041 > pip install -U cookiecutter && cookiecutter https://git.openstack.org/openstack/tempest-plugin-cookiecutter
Marc Koderer66210aa2015-10-26 10:52:32 +010042
43 Cloning into 'tempest-plugin-cookiecutter'...
44 remote: Counting objects: 17, done.
45 remote: Compressing objects: 100% (13/13), done.
46 remote: Total 17 (delta 1), reused 14 (delta 1)
47 Unpacking objects: 100% (17/17), done.
48 Checking connectivity... done.
49 project (default is "sample")? foo
50 testclass (default is "SampleTempestPlugin")? FooTempestPlugin
51
52This would create a folder called ``foo_tempest_plugin/`` with all necessary
53basic classes. You only need to move/create your test in
54``foo_tempest_plugin/tests``.
55
56Entry Point
57-----------
58
59Once you've created your plugin class you need to add an entry point to your
60project to enable tempest to find the plugin. The entry point must be added
61to the "tempest.test_plugins" namespace.
62
63If you are using pbr this is fairly straightforward, in the setup.cfg just add
64something like the following::
65
66 [entry_points]
67 tempest.test_plugins =
68 plugin_name = module.path:PluginClass
69
Matthew Treinish00686f22016-03-09 15:39:19 -050070Standalone Plugin vs In-repo Plugin
71-----------------------------------
72
73Since all that's required for a plugin to be detected by tempest is a valid
74setuptools entry point in the proper namespace there is no difference from the
75tempest perspective on either creating a separate python package to
76house the plugin or adding the code to an existing python project. However,
77there are tradeoffs to consider when deciding which approach to take when
78creating a new plugin.
79
80If you create a separate python project for your plugin this makes a lot of
81things much easier. Firstly it makes packaging and versioning much simpler, you
82can easily decouple the requirements for the plugin from the requirements for
83the other project. It lets you version the plugin independently and maintain a
84single version of the test code across project release boundaries (see the
85`Branchless Tempest Spec`_ for more details on this). It also greatly
86simplifies the install time story for external users. Instead of having to
87install the right version of a project in the same python namespace as tempest
88they simply need to pip install the plugin in that namespace. It also means
89that users don't have to worry about inadvertently installing a tempest plugin
90when they install another package.
91
92.. _Branchless Tempest Spec: http://specs.openstack.org/openstack/qa-specs/specs/tempest/implemented/branchless-tempest.html
93
94The sole advantage to integrating a plugin into an existing python project is
95that it enables you to land code changes at the same time you land test changes
96in the plugin. This reduces some of the burden on contributors by not having
97to land 2 changes to add a new API feature and then test it and doing it as a
98single combined commit.
99
100
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400101Plugin Class
Marc Koderer66210aa2015-10-26 10:52:32 +0100102============
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400103
104To provide tempest with all the required information it needs to be able to run
105your plugin you need to create a plugin class which tempest will load and call
106to get information when it needs. To simplify creating this tempest provides an
107abstract class that should be used as the parent for your plugin. To use this
108you would do something like the following::
109
YAMAMOTO Takashicb2ac6e2015-10-19 15:54:42 +0900110 from tempest.test_discover import plugins
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400111
YAMAMOTO Takashicb2ac6e2015-10-19 15:54:42 +0900112 class MyPlugin(plugins.TempestPlugin):
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400113
114Then you need to ensure you locally define all of the methods in the abstract
115class, you can refer to the api doc below for a reference of what that entails.
116
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400117Abstract Plugin Class
Marc Koderer66210aa2015-10-26 10:52:32 +0100118---------------------
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400119
120.. autoclass:: tempest.test_discover.plugins.TempestPlugin
121 :members:
122
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400123Plugin Structure
Marc Koderer66210aa2015-10-26 10:52:32 +0100124================
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400125While there are no hard and fast rules for the structure a plugin, there are
126basically no constraints on what the plugin looks like as long as the 2 steps
127above are done. However, there are some recommended patterns to follow to make
128it easy for people to contribute and work with your plugin. For example, if you
129create a directory structure with something like::
130
131 plugin_dir/
132 config.py
133 plugin.py
134 tests/
135 api/
136 scenario/
137 services/
138 client.py
139
140That will mirror what people expect from tempest. The file
141
142* **config.py**: contains any plugin specific configuration variables
143* **plugin.py**: contains the plugin class used for the entry point
144* **tests**: the directory where test discovery will be run, all tests should
145 be under this dir
146* **services**: where the plugin specific service clients are
147
148Additionally, when you're creating the plugin you likely want to follow all
149of the tempest developer and reviewer documentation to ensure that the tests
150being added in the plugin act and behave like the rest of tempest.
151
Matthew Treinish9392a832015-08-24 10:00:49 -0400152Dealing with configuration options
Marc Koderer66210aa2015-10-26 10:52:32 +0100153----------------------------------
Matthew Treinish9392a832015-08-24 10:00:49 -0400154
155Historically Tempest didn't provide external guarantees on its configuration
156options. However, with the introduction of the plugin interface this is no
157longer the case. An external plugin can rely on using any configuration option
158coming from Tempest, there will be at least a full deprecation cycle for any
159option before it's removed. However, just the options provided by Tempest
160may not be sufficient for the plugin. If you need to add any plugin specific
161configuration options you should use the ``register_opts`` and
162``get_opt_lists`` methods to pass them to Tempest when the plugin is loaded.
163When adding configuration options the ``register_opts`` method gets passed the
164CONF object from tempest. This enables the plugin to add options to both
165existing sections and also create new configuration sections for new options.
166
Matthew Treinish3a851dc2015-07-30 11:34:03 -0400167Using Plugins
168=============
169
170Tempest will automatically discover any installed plugins when it is run. So by
171just installing the python packages which contain your plugin you'll be using
172them with tempest, nothing else is really required.
173
174However, you should take care when installing plugins. By their very nature
175there are no guarantees when running tempest with plugins enabled about the
176quality of the plugin. Additionally, while there is no limitation on running
177with multiple plugins it's worth noting that poorly written plugins might not
178properly isolate their tests which could cause unexpected cross interactions
179between plugins.
180
181Notes for using plugins with virtualenvs
182----------------------------------------
183
184When using a tempest inside a virtualenv (like when running under tox) you have
185to ensure that the package that contains your plugin is either installed in the
186venv too or that you have system site-packages enabled. The virtualenv will
187isolate the tempest install from the rest of your system so just installing the
188plugin package on your system and then running tempest inside a venv will not
189work.
190
191Tempest also exposes a tox job, all-plugin, which will setup a tox virtualenv
192with system site-packages enabled. This will let you leverage tox without
193requiring to manually install plugins in the tox venv before running tests.