xref: /openbmc/openbmc-test-automation/CONTRIBUTING.md (revision 200d9df0551cc6a95f1128ccb1434b83c878dbee)
1# Contributing to OpenBMC Test Automation
2
3Guide to working on OpenBMC test automation. This document will always be a
4work-in-progress, feel free to propose changes.
5
6## Submitting changes via Gerrit server
7
8- Reference
9  [OpenBMC CLA](https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md#submitting-changes-via-gerrit-server-to-openbmc)
10- Reference
11  [OpenBMC docs](https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md#submitting-changes-via-gerrit-server)
12
13## Commit Message Guidelines
14
15- Reference
16  [Formatting Commit Messages](https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md#formatting-commit-messages)
17
18## Links
19
20- [Redfish Coding Guidelines](docs/redfish_coding_guidelines.md)
21
22## Robot Coding Guidelines
23
24- For this project, we will write Robot keyword definitions in either Robot or
25  Python. Robot code should be quite simple. Therefore, if the algorithm in
26  question is the least bit complex, please write it in Python.
27
28  See the following for support on writing most keywords in python.
29  - [Quit Writing Ugly Robot Code](https://esalagea.wordpress.com/2014/11/24/robot-framework-quit-writing-ugly-robot-code-just-write-proper-python/)
30  - [Robot Dos and Don'ts](https://www.slideshare.net/pekkaklarck/robot-framework-dos-and-donts)
31
32- Observe a maximum line length of 110 characters.
33- Avoid trailing space at the end of any line of Robot code.
34- Avoid the use of tabs.
35- Robot supports delimiting cells with either two or more spaces or with a pipe
36  symbol (e.g. "\|"). Our team has chosen to use spaces rather than the pipe
37  character. Make sure all space delimiters in Robot code are the **minimum** of
38  two spaces. There may be some exceptions to this rule.
39
40  Exceptions to two-space delimiter rule:
41  - When you wish to line up resource, library or variable values:
42    ```
43    Library         Lib1
44    Resource        Resource1
45    *** Variables ***
46    ${var1}         ${EMPTY}
47    ```
48  - When you wish to line up fields for test templates:
49    ```
50    [Template]  Set System LED State
51    # LED Name  LED State
52    power       On
53    power       Off
54    ```
55  - When you wish to indent if/else or loop bodies for visual effect:
56    ```
57    IF  '${this}' == '${that}'
58         Log  Bla, bla...
59    ELSE
60         Run Keywords  Key1  parms
61         ...    AND  Key2  parms
62    END
63    ```
64
65- Use single spaces to make conditions more readable:
66
67  Correct example:
68
69  ```
70  IF  '${var1}' == '${0}'  My Keyword
71  ```
72
73  Incorrect example:
74
75  ```
76  IF  '${var1}'=='${0}'  My Keyword
77  ```
78
79- When you define or call a Robot keyword, Robot pays no attention to spaces,
80  underscores or case. However, our team will observe the following conventions
81  in both our definitions and our calls:
82  - Separate words with single spaces.
83  - Capitalize the first character of each word.
84  - Capitalize all characters in any word that is an acronym (e.g. JSON, BMC,
85    etc).
86
87  Examples:
88
89  ```
90  *** Keywords ***
91
92  This Is Correct
93
94      # This keyword name is correct.
95
96  this_is_incorrect
97
98      # This keyword name is incorrect because of 1) the
99      # underscores instead of spaces and 2) the failure to
100      # capitalize each word in the keyword.
101
102  soisthis
103
104      # This keyword name is incorrect because of 1) a failure to
105      # separate words with single spaces and 2) a failure to capitalize
106      # each word in the keyword.
107
108  BMC Is An Acronym
109
110      # This keyword name is correct.  Note that "BMC" is an
111      # acronym and as such is entirely uppercase.
112  ```
113
114- Documentation strings:
115  - Each documentation string should be phrased as an **English command**.
116    Punctuate it correctly with the first word capitalized and a period at the
117    end.
118
119    Correct example:
120
121    ```
122    Boot BMC
123        [Documentation]  Boot the BMC.
124    ```
125
126    Incorrect example:
127
128    ```
129    Boot BMC
130        [Documentation]  This keyword boots the BMC.
131
132        # The doc string above is not phrased as a command.
133    ```
134
135  - Doc strings should be just one terse, descriptive sentence. Remember that
136    this doc string shows up in the HTML log file. Put additional commentary
137    below in standard comment lines.
138
139    Correct example:
140
141    ```
142    Stop SOL Console Logging
143
144        [Documentation]  Stop system console logging and return log output.
145    ```
146
147    Incorrect example:
148
149    ```
150    Stop SOL Console Logging
151
152        [Documentation]  Stop system console logging.  If there are multiple
153        ...              system console processes, they will all be
154        ...              stopped.  If there is no existing log file this
155        ...              keyword will return an error message to that
156        ...              effect (and write that message to targ_file_path,
157        ...              if specified).  NOTE: This keyword will not fail
158        ...              if there is no running system console process.
159
160        # This doc string is way too long.
161    ```
162
163- Tags:
164  - Create a tag for every test suite with a tag name that represents the suite
165    name as follows:
166
167    ```
168    Create a suite Tag name from the test file name
169    Example:
170        Suite:  test_boot_progress_code.robot
171
172        Test Tags    Boot_Progress_Code
173    ```
174
175  - Create a tag for every test case with a tag name that mirrors the test case
176    name as follows:
177
178    ```
179    Create Intermediate File
180
181        [Tags]  Create_Intermediate_File
182    ```
183
184- Description of argument(s):
185  - As shown in the following example, if your keyword has any arguments,
186    include a "**Description of argument(s)**" section. This effectively serves
187    as the help text for anyone wanting to use or understand your keyword.
188    Include real data examples wherever possible and applicable. Leave at least
189    2 spaces between the argument name and the description. Align all
190    description text as shown in the example below.
191
192    Example:
193
194    ```
195    Get URL List
196        [Documentation]  Return list of URLs under given URL.
197        [Arguments]  ${openbmc_url}  ${policy}   ${verify}
198
199        # Description of argument(s):
200        # openbmc_url  URL for list operation (e.g.
201        #              "/xyz/openbmc_project/inventory").
202        # policy       Power restore policy (e.g "RESTORE_LAST_STATE",
203        #              ${RESTORE_LAST_STATE}, etc.).
204        # verify       Verify the results (${TRUE}/${FALSE}).
205    ```
206
207    Additional rules for example text in descriptions:
208    - Put parentheses around your examples. Leave one space prior to the left
209      parenthesis.
210    - Use "e.g." (which effectively means "for example") to set introduce your
211      examples.
212    - Quote string examples.
213    - Include ", etc." after multiple examples.
214    - For cases where you're providing an complete list of possible values
215      (${TRUE}/${FALSE} or "PASS"/"FAIL"), do NOT use "e.g." and do NOT use
216      "etc.". Separate such values with a slash.
217
218- Variable assignments:
219
220  When assigning a variable as output from a keyword, do not precede the equal
221  sign with a space.
222
223  Correct examples:
224
225  ```
226  ${var1}=  Set Variable  ${1}
227  ${var1}=  My Keyword
228  ```
229
230  Incorrect examples:
231
232  ```
233  ${var1} =  Set Variable  ${1}
234  ${var1} =  My Keyword
235  ```
236
237- General variable naming conventions:
238  - Variable names should be lower case with few exceptions (listed here):
239    - Environment variables should be all upper case.
240    - Variables intended to be set by Robot -v parameters may be all upper case.
241  - Words within a variable name should be separated by underscores:
242
243    Correct examples:
244
245    ```
246    ${host_name}
247    ${program_pid}
248    ```
249
250    Incorrect examples:
251
252    ```
253    ${HostName}
254    ${ProgramPid}
255    ```
256
257  - Use good judgement in choosing variable names that are neither way too short
258    nor way too long.
259
260    Correct examples:
261
262    ```
263    ${host_name}
264    ${program_pid}
265    ```
266
267    Incorrect examples:
268
269    ```
270    ${HostName}
271    ${ProgramPid}
272    ```
273
274  - Avoid having the variable's type as a suffix portion of the name:
275
276    Incorrect examples:
277
278    ```
279    ${inventory_dict}
280    ${led_list}
281    ```
282
283    Incorrect examples:
284
285    ```
286    ${inventory}
287    # Use plural name to indicate that it is a list.
288    ${leds}
289    ```
290
291    A possible exception to this rule is when your keyword or function has an
292    ongoing need to refer to one piece of data in more than one format (e.g.
293    date_str, date_epoch, etc.).
294
295  - Consistency of variable names:
296
297    Try to avoid referring to the same data entity by multiple different names.
298    It creates a lot of confusion for the reader.
299
300    Incorrect example:
301
302    ```
303    # Why call the receiving variable rc (return code) when the keyword is
304    # supposed to return status.
305    ${rc}=  Run Keyword And Return Status  Bla Bla
306    ```
307
308    Correct example:
309
310    ```
311    ${status}=  Run Keyword And Return Status  Bla Bla
312    ```
313
314- Special variable naming conventions.
315
316  For certain very commonly used kinds of variables, please observe these
317  conventions in order to achieve consistency throughout the code.
318  - hosts
319
320    When a variable is intended to contain **either** an IP address **or** a
321    host name (whether long or short), please give it a suffix of "\_host".
322
323    Examples:
324
325    ```
326    openbmc_host
327    os_host
328    pdu_host
329    openbmc_serial_host
330    ```
331
332  - host names
333
334    For host names (long or short, e.g. "bmc1" or "bmc1.example.com"), use a
335    suffix of \_host_name.
336
337    Examples:
338
339    ```
340    openbmc_host_name
341    os_host_name
342    pdu_host_name
343    openbmc_serial_host_name
344    ```
345
346  - Short host names
347
348    For short host names (e.g. "bmc1"), use a suffix of \_host_short_name.
349
350    Examples:
351
352    ```
353    openbmc_host_short_name
354    os_host_short_name
355    pdu_host_short_name
356    openbmc_serial_host_short_name
357    ```
358
359  - IP addresses
360
361    For IP addresses, use a suffix of \_ip.
362
363    Example:
364
365    ```
366    openbmc_ip
367    os_ip
368    pdu_ip
369    openbmc_serial_ip
370    ```
371
372  - Files and directories:
373    - Files:
374      - If your variable is to contain only the file's name, use a suffix of
375        \_file_name.
376
377        Examples:
378
379        ```
380        ffdc_file_name = "bmc1.170428.120200.ffdc"
381        ```
382
383      - If your variable is to contain the path to a file, use a suffix of
384        \_file_path. Bear in mind that a file path can be relative or absolute,
385        so that should not be a consideration in whether to use the
386        "\_file_path" suffix.
387
388        Examples:
389
390        ```
391        status_file_path = "bmc1.170428.120200.status"
392        status_file_path = "subdir/bmc1.170428.120200.status"
393        status_file_path = "./bmc1.170428.120200.status"
394        status_file_path = "../bmc1.170428.120200.status"
395        status_file_path = "/home/user1/status/bmc1.170428.120200.status"
396        ```
397
398        To re-iterate, it doesn't matter whether the contents of the variable
399        are a relative or absolute path (as shown in the examples above). A file
400        path is simply a value with enough information in it for the program to
401        find the file.
402
403      - If the variable **must** contain an absolute path (which should be the
404        rare case), use a suffix \_abs_file_path.
405
406    - Directories:
407      - Directory variables should follow the same conventions as file
408        variables.
409
410      - If your variable is to contain only the directory's name, use a suffix
411        of \_dir_name.
412
413        Example:
414
415        ```
416        ffdc_dir_name = "ffdc"
417        ```
418
419      - If your variable is to contain the path to a directory, use a suffix of
420        \_dir_path. Bear in mind that a dir path can be relative or absolute, so
421        that should not be a consideration in whether to use \_dir_path.
422
423        Examples:
424
425        ```
426        status_dir_path = "status/"
427        status_dir_path = "subdir/status"
428        status_dir_path = "./status/"
429        status_dir_path = "../status/"
430        status_dir_path = "/home/user1/status/"
431        ```
432
433        To re-iterate, it doesn't matter whether the contents of the variable
434        are a relative or absolute path (as shown in the examples above). A dir
435        path is simply a value with enough information in it for the program to
436        find the directory.
437
438      - If the variable **must** contain an absolute path (which should be the
439        rare case), use a suffix \_abs_dir_path.
440      - IMPORTANT: As a programming convention, do pre- processing on all
441        dir_path variables to ensure that they contain a trailing slash. If we
442        follow that convention religiously, then when changes are made in other
443        parts of the program, the programmer can count on the value having a
444        trailing slash. Therefore, they can safely do this kind of thing:
445        ```
446        my_file_path = my_dir_path + my_file_name
447        ```
448
449  - Setup/Teardown keywords
450
451    Use standardized names for setup and teardown keywords:
452    - Suite Setup Execution
453    - Suite Teardown Execution
454    - Test Setup Execution
455    - Test Teardown Execution
456
457- Traditional comments (i.e. using the hashtag style comments)
458  - Please leave one space following the hashtag.
459
460    ```
461    #wrong
462
463    # Right
464    ```
465
466  - Please use proper English punctuation:
467    - Capitalize the first word in the sentence or phrase.
468    - End sentences (or stand-alone phrases) with a period.
469
470  - Do not keep commented-out code in your program. Instead, remove it entirely.
471
472- Robot Template Test Cases
473  - Follow this format for Robot template test cases:
474
475    Note: Documentation, Tags and Template lines are all required and should be
476    coded in the order shown.
477
478    ```
479    Test Case Name
480        [Documentation]
481        [Tags]
482        [Template]
483        # arg1  arg2  etc.
484        <arg1>  <arg2>
485
486    Example:
487
488    Get Response Codes
489        [Documentation]  REST "Get" response status test.
490        [Tags]  Get_Response_Codes
491        [Template]  Execute Get And Check Response
492
493        # expected_response_code  url_path
494        ${HTTP_OK}                /org/
495        ${HTTP_OK}                /xyz/
496        ${HTTP_OK}                /xyz/openbmc_project/
497        ${HTTP_OK}                /xyz/openbmc_project/state/enumerate
498        ${HTTP_NOT_FOUND}         /xyz/i/dont/exist/
499    ```
500
501    Note: Normally, a template test case would have many rows of data arguments
502    as in the example above. However, contributors frequently define multiple
503    template test cases that each have only one row of data which may seem to
504    defeat the value of using templates in the first place. However, it is done
505    for these reasons: 1) Template tests are counted as a single test. The user
506    may wish to have separate results for each call to the template function. 2)
507    If any call to the template function fails, one would like FFDC data
508    collected immediately and would like one set of FFDC data for EACH such
509    failure.
510
511## Python Coding Guidelines
512
513- The minimum required Python version is 2.7.x. In the very near future, we will
514  stop supporting python 2 and will require python 3.
515- Run pycodestyle on all Python files and correct errors to follow the
516  guidelines in https://www.python.org/dev/peps/pep-0008/. Note that when python
517  code is checked into gerrit, pycodestyle is run automatically on it.
518
519  Example as run from a Linux command line:
520
521  ```
522  pycodestyle my_pgm.py
523
524  my_pgm.py:41:1: E302 expected 2 blank lines, found 1
525  my_pgm.py:58:52: W291 trailing whitespace
526  ```
527
528- Include doc strings in every function and follow the guidelines in
529  https://www.python.org/dev/peps/pep-0257/.
530
531  Example:
532
533  ```
534      r"""
535      Return the function name associated with the indicated stack frame.
536
537      Description of argument(s):
538      stack_frame_ix                  The index of the stack frame whose
539                                      function name should be returned.  If
540                                      the caller does not specify a value,
541                                      this function will set the value to 1
542                                      which is the index of the caller's
543                                      stack frame.  If the caller is the
544                                      wrapper function "print_func_name",
545                                      this function will bump it up by 1.
546      """
547  ```
548
549- As shown in the prior example, if your function has any arguments, include a
550  "Description of argument(s)" section. This effectively serves as the help text
551  for anyone wanting to use or understand your function. Include real data
552  examples wherever possible and applicable.
553- Function definitions:
554  - Put each function parameter on its own line:
555
556    ```
557    def func1(parm1,
558
559              parm2):
560    ```
561
562- Do not keep commented-out code in your program. Instead, remove it entirely.
563- When you define a python function, observe the following conventions:
564  - Separate words with single underscores.
565  - Use lower-case letters.
566
567  Examples:
568
569  ```
570
571  def this_is_correct():
572
573      # This function name is correct.
574
575  def This_Is_Incorrect():
576
577      # This keyword name is incorrect because of the upper case letters used.
578
579  def soisthis():
580
581      # This keyword name is incorrect because of 1) a failure to
582      # separate words with underscores.
583
584  ```
585
586- Documentation strings:
587  - Each documentation string should be phrased as an **English command**.
588    Punctuate it correctly with the first word capitalized and a period at the
589    end.
590
591    Correct example:
592
593    ```
594    def boot_bmc():
595        r"""
596        Boot the BMC.
597        """
598    ```
599
600    Incorrect example:
601
602    ```
603    def boot_bmc():
604        r"""
605        This function boots the BMC.
606        """
607
608        # The doc string above is not phrased as a command.
609    ```
610
611  - Doc strings should begin with a summary line which is one terse, descriptive
612    sentence. Put additional commentary below.
613
614    Correct example:
615
616    ```
617    def stop_sol_console_logging():
618        r"""
619        Stop system console logging and return log output.
620
621        Additional comments...
622        """
623    ```
624
625    Incorrect example:
626
627    ```
628    def stop_sol_console_logging():
629        r"""
630        Stop system console logging.  If there are multiple system console
631        processes, they will all be stopped.  If there is no existing log file
632        this keyword will return an error message to that effect (and write that
633        message to targ_file_path, if specified).  NOTE: This keyword will not
634        fail if there is no running system console process.
635        """
636
637        # This summary is way too long.
638    ```
639
640- General variable naming conventions:
641  - Variable names should be lower case with few exceptions (listed here):
642    - Environment variables should be all upper case.
643  - Words within a variable name should be separated by underscores:
644
645    Correct examples:
646
647    ```
648    ${host_name}
649    ${program_pid}
650    ```
651
652    Incorrect examples:
653
654    ```
655    ${HostName}
656    ${ProgramPid}
657    ```
658
659- Special variable naming conventions.
660
661  For certain very commonly used kinds of variables, please observe these
662  conventions in order to achieve consistency throughout the code.
663  - hosts
664
665    When a variable is intended to contain **either** an IP address **or** a
666    host name (either long or short), please give it a suffix of "\_host".
667
668    Examples:
669
670    ```
671    openbmc_host
672    os_host
673    pdu_host
674    openbmc_serial_host
675    ```
676
677  - host names
678
679    For host names (long or short, e.g. "bmc1" or "bmc1.example.com"), use a
680    suffix of \_host_name.
681
682    Examples:
683
684    ```
685    openbmc_host_name
686    os_host_name
687    pdu_host_name
688    openbmc_serial_host_name
689    ```
690
691  - Short host names
692
693    For short host names (e.g. "bmc1"), use a suffix of \_host_short_name.
694
695    Examples:
696
697    ```
698    openbmc_host_short_name
699    os_host_short_name
700    pdu_host_short_name
701    openbmc_serial_host_short_name
702    ```
703
704  - IP addresses
705
706    For IP addresses, use a suffix of \_ip.
707
708    Example:
709
710    ```
711    openbmc_ip
712    os_ip
713    pdu_ip
714    openbmc_serial_ip
715    ```
716
717- Files and directories:
718  - Files:
719    - If your variable is to contain only the file's name, use a suffix of
720      \_file_name.
721
722      Examples:
723
724      ```
725      ffdc_file_name = "bmc1.170428.120200.ffdc"
726      ```
727
728    - If your variable is to contain the path to a file, use a suffix of
729      \_file_path. Bear in mind that a file path can be relative or absolute, so
730      that should not be a consideration in whether to use the "\_file_path"
731      suffix.
732
733      Examples:
734
735      ```
736      status_file_path = "bmc1.170428.120200.status"
737      status_file_path = "subdir/bmc1.170428.120200.status"
738      status_file_path = "./bmc1.170428.120200.status"
739      status_file_path = "../bmc1.170428.120200.status"
740      status_file_path = "/home/user1/status/bmc1.170428.120200.status"
741      ```
742
743      To re-iterate, it doesn't matter whether the contents of the variable are
744      a relative or absolute path (as shown in the examples above). A file path
745      is simply a value with enough information in it for the program to find
746      the file.
747
748    - If the variable **must** contain an absolute path (which should be the
749      rare case), use a suffix \_abs_file_path.
750
751  - Directories:
752    - Directory variables should follow the same conventions as file variables.
753
754    - If your variable is to contain only the directory's name, use a suffix of
755      \_dir_name.
756
757      Example:
758
759      ```
760      ffdc_dir_name = "ffdc"
761      ```
762
763    - If your variable is to contain the path to a directory, use a suffix of
764      \_dir_path. Bear in mind that a dir path can be relative or absolute so,
765      that should not be a consideration in whether to use \_dir_path.
766
767      Examples:
768
769      ```
770      status_dir_path = "status/"
771      status_dir_path = "subdir/status"
772      status_dir_path = "./status/"
773      status_dir_path = "../status/"
774      status_dir_path = "/home/user1/status/"
775      ```
776
777      To re-iterate, it doesn't matter whether the contents of the variable are
778      a relative or absolute path (as shown in the examples above). A dir path
779      is simply a value with enough information in it for the program to find
780      the directory.
781
782    - If the variable **must** contain an absolute path (which should be the
783      rare case), use a suffix \_abs_dir_path.
784    - IMPORTANT: As a programming convention, do pre- processing on all dir_path
785      variables to ensure that they contain a trailing slash. If we follow that
786      convention religiously, that when changes are made in other parts of the
787      program, the programmer can count on the value having a trailing slash.
788      Therefore they can safely do this kind of thing:
789      ```
790      my_file_path = my_dir_path + my_file_name
791      ```
792
793- Traditional comments (i.e. using the hashtag style comments)
794  - Please leave one space following the hashtag.
795
796    ```
797    #wrong
798
799    # Right
800    ```
801
802  - Please use proper English punction:
803    - Capitalize the first word in the sentence or phrase.
804    - End sentences (or stand-alone phrases) with a period.
805
806  - Do not keep commented-out code in your program. Instead, remove it entirely.
807
808## Template Usage Requirements
809
810We have several templates in the templates/ sub-directory. If there is a
811template that applies to your programming situation (Python, bash, etc.), it
812should be used to create new programs as in the following example
813
814- Example:
815
816  ```
817  $ cd templates
818  $ cp python_pgm_template] ../bin/my_new_program.py
819  ```
820
821These templates have much of your preliminary work done for you and will help us
822all follow a similar structure.
823
824See [python_pgm_template](templates/python_pgm_template) as an example.
825
826- Features:
827  - Help text and arg parsing started for you.
828  - Support for "stock" parameters like "quiet", "debug", "test_mode".
829  - "exit_function" pre-defined.
830  - "validate_parms" function pre-defined.
831  - "main" function follows conventional startup sequence:
832
833    ```
834        gen_get_options(parser, stock_list)
835
836        validate_parms()
837
838        qprint_pgm_header()
839
840        # Your code here.
841    ```
842