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