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