---
# System prepended metadata

title: 7/15共筆

---

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