# 7/15共筆 {%hackmd 1lpg7PuqRoaui6XyJcrylw %} :::info :heart: 這禮拜收到很多好問題!感謝Nickson, Tommy, Jimmy, Delbert, Jim, Sabrina, Mike提問。 ::: ## 目標提醒 ## Function越寫越多,怎麼維護? 維護成本是高的。有人用的東西,才會有維護的價值。所以維護的原則除了讓開發者本身好開發和管理外,另一個原則是要使用者能夠持續的使用。用下列四種類型說明: - Implement Code - Test Cases - Configuration File - 其他(Resource File, Variable File) ### Implement Code 如同使用別人寫好的library/module/package時的做法一樣,身為使用者的我們會想要: - 能夠取得健康的library - 有說明文件參照使用法方法和範例 - 可以根據naming和docstring推敲功能和使用方法 #### 能夠取得健康的library - 做好版本控制 - Branch model - Commit, Push, Merge rules - Review rules - Manual - Automation (e.g. GitLab CI) - Release rules - 參考Git/GitLab/GitHub Flow - [A successful git branching model](https://nvie.com/posts/a-successful-git-branching-model/) - [What are GitLab Flow best practices?](https://about.gitlab.com/topics/version-control/what-are-gitlab-flow-best-practices/) - [Introduction to GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) - [Understanding the GitHub flow](https://guides.github.com/introduction/flow/) > 如果行有餘力的話,針對 Implment Code 做 Unit Test 可以讓 library 更健康 [name=Chuck] #### 有說明文件參照使用法方法和範例 - ==文件也要一起做版本控制== - 參考你常用和相關的library怎麼寫和呈現文件? - [behave API](https://behave.readthedocs.io/en/stable/api.html) - [Robot API](https://robot-framework.readthedocs.io/en/stable/) - [Selenium with Python](https://selenium-python.readthedocs.io/) - [Genie](https://developer.cisco.com/docs/genie-docs/) - 工具 - [Read The Docs](https://docs.readthedocs.io/en/stable/index.html) - [NBG GitLab Wiki](http://mhqnetgitlab.moxa.com/help/user/project/wiki/index.md) #### 可以根據naming和docstring推敲功能和使用方法 - [PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) - [PEP 257 -- Docstring Conventions](https://www.python.org/dev/peps/pep-0257/) - Function naming convention(參考) - [Genie的functions](https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/apis) - 我原本的規則 | Function Name | | ---------------------- | | login | | logout | | reload | | reload_factory_default | | export | | import | | Prefix | Example | | -------- | ------------------- | | add_ | add_static_route | | delete_ | delete_static_route | | enable_ | enable_ospf | | disable_ | disable_ospf | | set_ | set_hostname | | default_ | default_hostname | | get_ | get_system_info | ### Test Cases 同樣以Test Case使用者的角度來看,我會希望: - 可以獲取完整的測項 - 能夠與測試機種和FWR版本對應 - 格式一致 - 能夠看得懂的描述 - 內容有組織 #### 參考==通用==的撰寫規則 - 參考標準化的詞彙和文件架構 - [ISTQB Glossary](https://glossary.istqb.org/en/search/) - [ISO/IEC/IEEE 29119 Software Testing](https://en.wikipedia.org/wiki/ISO/IEC_29119) - ISO/IEC 29119-1: Concepts & definitions - ISO/IEC 29119-3: Test documentation - 用Gherhkin語法組織測試步驟 #### 用工具協助Review和==版本控制== - GitLab - Cucumber(.feature) ![](https://i.imgur.com/Pks2dvf.png) - Robot Framework (.robot) ![](https://i.imgur.com/FtkmTZm.png) ### Configuration file - 會需要有Networking的專業。 - 參考小茂(Cisco, Westermo)怎麼做? - Device - [Set up your testbed file and connect to a device](https://pubhub.devnetcloud.com/media/genie-docs/docs/cookbooks/genie.html#book-setup-testbed) - [Ixia device](https://developer.cisco.com/docs/genie-trafficgen/) - Topology - [Creating Topology](https://pubhub.devnetcloud.com/media/pyats/docs/topology/creation.html#topology-testbed-file) - [Westermo - Automated test mapping and coverage for network topologies](https://www.researchgate.net/publication/326365930_Automated_test_mapping_and_coverage_for_network_topologies) > ![](https://i.imgur.com/0fA4ID0.png) - Testbed - [Describe Your Testbed](https://pubhub.devnetcloud.com/media/pyats/docs/getting_started/index.html#describe-your-testbed) - 參考==通用的==資料格式 - [YAML](http://yaml.org/) ### 其他(Resource File, Variable File) 因為Robot Framework有自己的檔案Resource file, Variable file,所與額外維護。 ![](https://i.imgur.com/crnXRng.png) - 參考Robot Framework Library的文件格式和內容。 - [Build-In](https://robotframework.org/robotframework/latest/libraries/BuiltIn.html) - [Telnet](https://robotframework.org/robotframework/latest/libraries/Telnet.html) - [Selenium](https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html) ## Debug 1. [Install Visual Studio Code and the Python Extension](https://code.visualstudio.com/docs/python/python-tutorial#_install-visual-studio-code-and-the-python-extension) 2. [Initialize debug configurations](https://code.visualstudio.com/docs/python/debugging#_initialize-configurations) 3. 將cucumber和robot的debug configurations加入`launch.json`中`configurations:[]`裡面。 === ```json= "configurations": [ { "name": "behave: Current File Debug", "type": "python", "request": "launch", "module": "behave", "console": "integratedTerminal", "args": [ "-f", "html", "-o", "result/log.html", "-f", "pretty", "${file}" ] }, { "name": "robot: Current File Debug", "type": "python", "request": "launch", "module": "robot", "console": "integratedTerminal", "args": [ "-d", "result", "${file}" ] }, ] ``` 4. 重新開啟VS Code。 5. 設置Config Mode ![](https://i.imgur.com/KfIHk3h.png) 6. 按下`F5`開始Debug。 - 用break point暫停程式。 - 善用watch和debug console來看變數的值。 - ==用`F11`來了解執行的順序== ## Fixture (Setup, Teardown) Fixtures are functions, which will run before or after specific part of test cases. ### In behave (Cucumber) - Syntax - 用`@fixture`裝飾 - 用yield來切分setup和teardown - 配合`try... finally...`來確保發生錯誤時,也會執行tear down。 ```python= from behave import fixture @fixture def open_brower(context): try: context.driver = webdriver.Remote( command_executor = context.remote_webdriver, desired_capabilities = DesiredCapabilities.CHROME) context.driver.implicitly_wait(10) context.wait = WebDriverWait(context.driver, 60) yield context.driver # 用yield來切分setup和teardown的部分 finally: context.driver.quit() ``` - 發動時機 | Context Layer | Fixture-Setup Point | Fixture-Cleanup Point | | ------------- | ---------------------- | ------------------------------------------------------------------ | | test run | In `before_all()` hook | After `after_all()` at end of test-run. | | feature | In `before_feature()` | After `after_feature()`, at end of feature. | | feature | In `before_tag()` | After `after_feature()` for feature tag. | | scenario | In `before_scenario()` | After `after_scenario()`, at end of scenario. | | scenario | In `before_tag()` | After `after_scenario()` for scenario tag. | | scenario | In a step | ==After `after_scenario()`.== Fixture is usable until end of scenario. | :::info :link: [behave fixture](https://behave.readthedocs.io/en/stable/tutorial.html#fixtures) :link: [behave fixture in details](https://behave.readthedocs.io/en/stable/fixtures.html#) ::: ### In Robot Framework - 主要在`.robot`檔案中撰寫。 - Syntax - Test-Suite level ``` *** Settings *** Test Setup Open Application App A Test Teardown Close Application ``` - Test-Case level ``` *** Test Cases *** Using variables [Setup] ${SETUP} Do Something [Teardown] ${TEARDOWN} ``` - Keyword level ``` *** Keywords *** With Teardown Do Something [Teardown] Log keyword teardown ``` - 發動時機為該level開始和結束時執行Setup和Teardown。 :::info :link: [test suite setup and teardwon](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#suite-setup-and-teardown) :link: [test suite setup and teardwon](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#test-setup-and-teardown) :link: [keyword teardown](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#user-keyword-teardown) ::: ## 補充 > Q. Nickson遇到robot的class會反覆開啟instance的問題? > A. Library的Class的Scope要設成Global(這邊的Global指的是在Robot Framework下使用的Scope) > [name=Nickson] > Q. 上述是否可以用singleton改寫?[name=Hilbert] > 參考資料[python 實現 singleton 模式](https://mark1002.github.io/2018/07/31/python-%E5%AF%A6%E7%8F%BE-singleton-%E6%A8%A1%E5%BC%8F/)[name=Chuck] > 因為螢幕投出來的時間很短,我沒有看得很清楚 singleton 是用在什麼地方,或者是不是一定需要用。 雖然 singleton 最大的特色是共用資源,但是同時也是它使用上最需要注意的地方,沒做好資料存取保護,在平行運算的時候就有可能不定期出現資料同時存取的問題(Race Condition),如果讓測試結果偶發性的不穩定,放在這麼核心的地方會非常找 bug。 所以雖然存在這種設計方式,但是會建議在使用前先詳閱公開說明書,再決定是不是要使用。[name=Chuck] > 不管什麼什麼設計模式都有適用或不適用的場合,舉例來說如果團隊合作想要把某種特定測試、但是該測試又想確定資源只被 access / create... 一次,就可以考慮使用 singleton 的設計來 release lib,這樣可以有效的避免使用者誤用造成重複 access 資源而產生不可預期的執行結果、也不需要擔心全域符號覆用 > 沒記錯的話 java instance 就是這樣的設計,但這設計是符合早期瀏覽器使用情境,在現代瀏覽器的使用情境卻造成很多限制。 > 然後 singleton 不是共用資源的目的,目的是找到全宇宙的唯一,共用資源不代表資源只能有一份,但你要指定為一的真愛就可以用 singleton 把它包起來。 [name=Hilbert] >