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