# 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)

- Robot Framework (.robot)

### 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)
> 
- 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,所與額外維護。

- 參考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

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]
>