blob: d69f935e52c2082618c70c08343f3c88006ef6a9 [file] [log] [blame]
Attila Fazekas23fdf1d2013-06-09 16:35:23 +02001Tempest Coding Guide
2====================
3
4
Matthew Treinish8b372892012-12-07 17:13:16 -05005Test Data/Configuration
6-----------------------
7- Assume nothing about existing test data
8- Tests should be self contained (provide their own data)
9- Clean up test data at the completion of each test
10- Use configuration files for values that will vary by environment
11
12
13General
14-------
15- Put two newlines between top-level code (funcs, classes, etc)
16- Put one newline between methods in classes and anywhere else
17- Long lines should be wrapped in parentheses
18 in preference to using a backslash for line continuation.
19- Do not write "except:", use "except Exception:" at the very least
20- Include your name with TODOs as in "#TODO(termie)"
21- Do not name anything the same name as a built-in or reserved word Example::
22
23 def list():
24 return [1, 2, 3]
25
26 mylist = list() # BAD, shadows `list` built-in
27
28 class Foo(object):
29 def list(self):
30 return [1, 2, 3]
31
32 mylist = Foo().list() # OKAY, does not shadow built-in
33
34Imports
35-------
36- Do not import objects, only modules (*)
37- Do not import more than one module per line (*)
38- Do not make relative imports
39- Order your imports by the full module path
40- Organize your imports according to the following template
41
42Example::
43
44 # vim: tabstop=4 shiftwidth=4 softtabstop=4
45 {{stdlib imports in human alphabetical order}}
46 \n
47 {{third-party lib imports in human alphabetical order}}
48 \n
49 {{tempest imports in human alphabetical order}}
50 \n
51 \n
52 {{begin your code}}
53
54
55Human Alphabetical Order Examples
56---------------------------------
57Example::
58
59 import httplib
60 import logging
61 import random
62 import StringIO
ivan-zhu1feeb382013-01-24 10:14:39 +080063 import testtools
Matthew Treinish8b372892012-12-07 17:13:16 -050064 import time
Matthew Treinish8b372892012-12-07 17:13:16 -050065
66 import eventlet
67 import webob.exc
68
69 import tempest.config
70 from tempest.services.compute.json.limits_client import LimitsClientJSON
71 from tempest.services.compute.xml.limits_client import LimitsClientXML
72 from tempest.services.volume.volumes_client import VolumesClientJSON
73 import tempest.test
74
75
76Docstrings
77----------
78Example::
79
80 """A one line docstring looks like this and ends in a period."""
81
82
83 """A multi line docstring has a one-line summary, less than 80 characters.
84
85 Then a new paragraph after a newline that explains in more detail any
86 general information about the function, class or method. Example usages
87 are also great to have here if it is a complex class for function.
88
89 When writing the docstring for a class, an extra line should be placed
90 after the closing quotations. For more in-depth explanations for these
91 decisions see http://www.python.org/dev/peps/pep-0257/
92
93 If you are going to describe parameters and return values, use Sphinx, the
94 appropriate syntax is as follows.
95
96 :param foo: the foo parameter
97 :param bar: the bar parameter
98 :returns: return_type -- description of the return value
99 :returns: description of the return value
100 :raises: AttributeError, KeyError
101 """
102
103
104Dictionaries/Lists
105------------------
106If a dictionary (dict) or list object is longer than 80 characters, its items
107should be split with newlines. Embedded iterables should have their items
108indented. Additionally, the last item in the dictionary should have a trailing
109comma. This increases readability and simplifies future diffs.
110
111Example::
112
113 my_dictionary = {
114 "image": {
115 "name": "Just a Snapshot",
116 "size": 2749573,
117 "properties": {
118 "user_id": 12,
119 "arch": "x86_64",
120 },
121 "things": [
122 "thing_one",
123 "thing_two",
124 ],
125 "status": "ACTIVE",
126 },
127 }
128
129
130Calling Methods
131---------------
132Calls to methods 80 characters or longer should format each argument with
133newlines. This is not a requirement, but a guideline::
134
135 unnecessarily_long_function_name('string one',
136 'string two',
137 kwarg1=constants.ACTIVE,
138 kwarg2=['a', 'b', 'c'])
139
140
141Rather than constructing parameters inline, it is better to break things up::
142
143 list_of_strings = [
144 'what_a_long_string',
145 'not as long',
146 ]
147
148 dict_of_numbers = {
149 'one': 1,
150 'two': 2,
151 'twenty four': 24,
152 }
153
154 object_one.call_a_method('string three',
155 'string four',
156 kwarg1=list_of_strings,
157 kwarg2=dict_of_numbers)
158
159
Attila Fazekas10fd63d2013-07-04 18:38:21 +0200160Exception Handling
161------------------
162According to the ``The Zen of Python`` the
163 ``Errors should never pass silently.``
164Tempest usually runs in special environment (jenkins gate jobs), in every
165error or failure situation we should provide as much error related
166information as possible, because we usually do not have the chance to
167investigate the situation after the issue happened.
168
169In every test case the abnormal situations must be very verbosely explained,
170by the exception and the log.
171
172In most cases the very first issue is the most important information.
173
174Try to avoid using ``try`` blocks in the test cases, both the ``except``
175and ``finally`` block could replace the original exception,
176when the additional operations leads to another exception.
177
178Just letting an exception to propagate, is not bad idea in a test case,
179 at all.
180
181Try to avoid using any exception handling construct which can hide the errors
182origin.
183
184If you really need to use a ``try`` block, please ensure the original
185exception at least logged. When the exception is logged you usually need
186to ``raise`` the same or a different exception anyway.
187
188Use the ``self.assert*`` methods provided by the unit test framework
189 the signal failures early.
190
191Avoid using the ``self.fail`` alone, it's stack trace will signal
192 the ``self.fail`` line as the origin of the error.
193
194Avoid constructing complex boolean expressions for assertion.
195The ``self.assertTrue`` or ``self.assertFalse`` will just tell you the
196single boolean, and you will not know anything about the values used in
197the formula. Most other assert method can include more information.
198For example ``self.assertIn`` can include the whole set.
199
200If the test case fails you can see the related logs and the information
201carried by the exception (exception class, backtrack and exception info).
202This and the service logs are your only guide to find the root cause of flaky
203issue.
204
205
Matthew Treinish997da922013-03-19 11:44:12 -0400206Test Skips
207----------
208If a test is broken because of a bug it is appropriate to skip the test until
209bug has been fixed. However, the skip message should be formatted so that
210Tempest's skip tracking tool can watch the bug status. The skip message should
211contain the string 'Bug' immediately followed by a space. Then the bug number
212should be included in the message '#' in front of the number.
213
214Example::
215
216 @testtools.skip("Skipped until the Bug #980688 is resolved")
217
218
Matthew Treinish89273ee2013-02-12 13:52:09 -0500219openstack-common
220----------------
221
222A number of modules from openstack-common are imported into the project.
223
224These modules are "incubating" in openstack-common and are kept in sync
225with the help of openstack-common's update.py script. See:
226
227 http://wiki.openstack.org/CommonLibrary#Incubation
228
229The copy of the code should never be directly modified here. Please
230always update openstack-common first and then run the script to copy
231the changes across.
232
233
Matthew Treinish8b372892012-12-07 17:13:16 -0500234OpenStack Trademark
235-------------------
236
Matthew Treinish89273ee2013-02-12 13:52:09 -0500237OpenStack is a registered trademark of the OpenStack Foundation, and uses the
Matthew Treinish8b372892012-12-07 17:13:16 -0500238following capitalization:
239
240 OpenStack
241
242
243Commit Messages
244---------------
245Using a common format for commit messages will help keep our git history
246readable. Follow these guidelines:
247
248 First, provide a brief summary (it is recommended to keep the commit title
249 under 50 chars).
250
251 The first line of the commit message should provide an accurate
252 description of the change, not just a reference to a bug or
253 blueprint. It must be followed by a single blank line.
254
255 If the change relates to a specific driver (libvirt, xenapi, qpid, etc...),
256 begin the first line of the commit message with the driver name, lowercased,
257 followed by a colon.
258
259 Following your brief summary, provide a more detailed description of
260 the patch, manually wrapping the text at 72 characters. This
261 description should provide enough detail that one does not have to
262 refer to external resources to determine its high-level functionality.
263
264 Once you use 'git review', two lines will be appended to the commit
265 message: a blank line followed by a 'Change-Id'. This is important
266 to correlate this commit with a specific review in Gerrit, and it
267 should not be modified.
268
269For further information on constructing high quality commit messages,
270and how to split up commits into a series of changes, consult the
271project wiki:
272
273 http://wiki.openstack.org/GitCommitMessages