vscode+robotframework的實踐-selenium(更新中)

hiayap發表於2024-06-21

一 說明

  • 上一次使用robotframework還是2019年畢業剛進入工作的時候,使用的是robotframework的官方配套編輯器RIDE進行自動化指令碼編寫,在使用的過程中偶爾會遭遇卡頓、閃退等問題,當時排查問題大多數是因為RIDE自身與python版本以及作業系統之間的相容性問題導致的,那時候沒有程式設計意識,程式碼功底也相對薄弱,RIDE是一個對新手很好的編輯工具。但有前端編碼經驗後,使用vscode編輯器編寫指令碼的效率會更高,有相對應的外掛支援,也是官方推薦的IDE之一。
  • 寫這篇文章的目的主要是為了方便自己重新回憶robotframework的使用,結合vscode達到實戰的目的,不足之處隨時歡迎私信溝通鴨
  • 該文章比較適合有python+RF基礎,想從RIDE改成用VScode編寫用例的同學,聽到測試套件(test_suite)、關鍵字(uesr_keyword)、資源(resorce)能立刻理解的,沒有基礎的同學可以先看相關書籍學習,此處推薦《自動化測試實戰寶典》、《RobotFramework自動化測試修煉寶典》
  • 最好的RF教程其實都在RF官網,英語能力強的小夥伴建議直接看官網文件(或者藉助翻譯工具也行)

二 工具安裝版本

  • vscode-V1.90.2
  • python-V3.11.9
  • 谷歌瀏覽器-V126.0.6478.115
  • 根據自己的谷歌瀏覽器安裝對應的瀏覽器驅動,具體可檢視SeleniumLibrary的git說明,其中也有講解了怎麼下載瀏覽器驅動

三 安裝

3.1 安裝RF(V7.0.1):pip install robotframework

3.2 安裝Selenium Library(V6.5.0):pip install --upgrade robotframework-seleniumlibrary

3.3 在vscode上安裝RF相關外掛

寫一個熟悉的helloworld。*** Test Cases ***此類的語法可以參考官網語法

*** Test Cases ***
test_case01
    Log    helloworld!

四 實踐(持續更新中)

4.1 實踐1:開啟谷歌瀏覽器,進入百度介面,搜尋並進入robotframe官網。

4.1.1 對應程式碼
點選檢視程式碼
*** Comments ***
#此處用來填寫說明
開啟谷歌瀏覽器,進入百度介面,搜尋並進入robotframe官網。
*** Settings ***
#此處用來設定用例,常見的有引入庫、設定setup teardown
Library    SeleniumLibrary    
Test Teardown    Close Browser
*** Variables ***
#此處用來設定用例,常見的有引入庫、設定setup teardown

*** Test Cases ***
#此處用來設定測試用例
Open Page    #用例名稱
    [Teardown]    Run Keyword If Test Failed    Close Browser    #用例如果失敗了就關閉瀏覽器
    Open Browser    url=https://www.baidu.com   browser=chrome    #開啟百度搜尋頁面
    Maximize Browser Window    #視窗最大化
    Wait Until Page Contains Element    locator=id=kw    #等待元素出現,預設等待時間是5S
    Input Text    locator=id=kw    text=Robot Framework    #在id為kw的輸入框裡輸入Robot Framework 
    Click Button    locator=id=su    #點選id為su的搜尋按鈕
    Wait Until Page Contains Element    locator=//div[contains(@mu, 'robotframework.org')]    #等待想要的搜尋網址出現,這裡是xpath選擇器
    Click Element    locator=//div[contains(@mu, 'robotframework.org')]/div/div/h3/a    #點選對應標題
    Switch Window    locator=NEW    # 切換到新標籤頁,進入到rf網址
*** Keywords ***
#此處用來設定變數
4.1.2 使用vscode除錯程式碼。這時候使用IDE的好處就出來了,斷點除錯在編寫用例時非常使用,可以迅速幫我們找到BUG,以及隨時停在我們需要檢查的程式碼上,RIDE編輯器則無法做到這一步。

除錯功能如下:

  • 繼續:直接跳到下一個斷點處,點選後就會順序執行程式碼到斷點2處時停下
  • 逐過程:如果程式碼中有迴圈或者子函式的話,進入帶迴圈裡和子函式,但是當前沒有迴圈,所以點選後的效果也相當於單步除錯
  • 單步除錯:從當前斷點處,點選一次逐步執行一行程式碼(不打斷點也可以)
  • 單步跳出:進入程式碼中有迴圈或者子函式的時候,可以點選這個跳出迴圈和子函式進入到下一行程式碼
  • 重啟:顧名思義,重新執行程式碼
  • 停止:顧名思義,停止當前程式碼

4.1.3 其他說明
  • vscode可以在使用關鍵字時快速匹配相關關鍵字列表

  • 滑鼠移動到關鍵字上,也可以快速給出關鍵字說明

  • 遺漏哪些必填項,也能給出對應錯誤資訊

4.2 實踐2:登陸介面功能測試

4.2.1 環境配置

4.2.1.1 先簡單寫一個登陸介面,用於測試。把這兩個html程式碼放置在一個檔案目錄下,對login.html右鍵使用open with live sever可以在瀏覽器中開啟對應網址。open with live sever功能可以建立一個服務,方便我們除錯html程式碼

點選檢視login.html程式碼
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Login Page</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        text-align: center;
      }
      .container {
        margin-top: 100px;
        width: 300px;
        margin-left: auto;
        margin-right: auto;
      }
      input[type='text'],
      input[type='password'],
      input[type='submit'] {
        width: 100%;
        padding: 12px 20px;
        margin: 8px 0;
        display: inline-block;
        border: 1px solid #ccc;
        box-sizing: border-box;
        font-size: 16px;
      }
      input[type='submit'] {
        background-color: #4caf50;
        color: white;
        border: none;
        cursor: pointer;
      }
      input[type='submit']:hover {
        background-color: #45a049;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h2>Login</h2>
      <form id="loginForm" onsubmit="return checkLogin()">
        <label for="username">Username:</label><br />
        <input type="text" id="username" name="username" /><br />
        <label for="password">Password:</label><br />
        <input type="password" id="password" name="password" /><br /><br />
        <input type="submit" value="Login" />
      </form>
      <p id="loginMessage" style="display: none; color: green">
        Login successful!
      </p>
    </div>

    <script>
      function checkLogin() {
        var username = document.getElementById('username').value
        var password = document.getElementById('password').value
        if (!username || !password) {
          alert('請輸入賬號密碼後再點選登入!')
          return false
        } else if (username === 'root' && password === 'root1234') {
          document.getElementById('loginMessage').style.display = 'block'
          window.location.href = './mainPage.html'
          return false // Prevent form submission
        } else if (username === 'root' && password != 'root1234') {
          alert('密碼錯誤,請輸入正確的密碼!')
          return false
        } else {
          alert('賬號密碼錯誤,請檢查賬號密碼!')
          return false
        }
      }
    </script>
  </body>
</html>
點選檢視mainPage.html程式碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>資料搜尋頁面</title>
    <style>
        table {
            border-collapse: collapse;
            width: 100%;
        }
        th, td {
            border: 1px solid #dddddd;
            text-align: left;
            padding: 8px;
        }
        th {
            background-color: #f2f2f2;
        }
    </style>
</head>
<body>
    <h1>資料搜尋頁面</h1>
    <form id="searchForm">
        <label for="name">姓名:</label>
        <input type="text" id="name" name="name">
        <label for="gender">性別:</label>
        <select id="gender" name="gender">
            <option value="">全部</option>
            <option value="male">男</option>
            <option value="female">女</option>
        </select>
        <button type="button" onclick="searchData()">搜尋</button>
    </form>

    <br>

    <table id="dataTable">
        <thead>
            <tr>
                <th>序號</th>
                <th>姓名</th>
                <th>性別</th>
                <th>年齡</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>張三</td>
                <td>男</td>
                <td>25</td>
            </tr>
            <tr>
                <td>2</td>
                <td>李四</td>
                <td>男</td>
                <td>30</td>
            </tr>
            <tr>
                <td>3</td>
                <td>王芳</td>
                <td>女</td>
                <td>28</td>
            </tr>
        </tbody>
    </table>

    <script>
        function searchData() {
            var inputName = document.getElementById('name').value.toLowerCase();
            var inputGender = document.getElementById('gender').value.toLowerCase();
            var table = document.getElementById('dataTable');
            var rows = table.getElementsByTagName('tr');
            
            for (var i = 1; i < rows.length; i++) {
                var name = rows[i].getElementsByTagName('td')[1].innerText.toLowerCase();
                var gender = rows[i].getElementsByTagName('td')[2].innerText.toLowerCase();
                
                var nameMatch = name.includes(inputName);
                var genderMatch = (inputGender === '' || (inputGender === 'male' && gender === '男') || (inputGender === 'female' && gender === '女'));
                
                if (nameMatch && genderMatch) {
                    rows[i].style.display = '';
                } else {
                    rows[i].style.display = 'none';
                }
            }
        }
    </script>
</body>
</html>

登陸頁面功能設計如下:

  • 功能1:輸入正確的賬號密碼(root/root1234),登入成功,跳轉到主頁
  • 功能2:輸入正確的賬號,錯誤的密碼,登入失敗並給出提示資訊:密碼錯誤,請輸入正確的密碼
  • 功能3:輸入錯誤的賬號密碼,登入失敗並給出提示資訊:賬號密碼錯誤,請檢查賬號密碼
  • 功能4:不輸入賬號密碼點選登入,登入失敗並給出提示資訊:請輸入賬號密碼後再點選登入!

4.2.1.2 根據頁面功能設計用例

  • 用例1:輸入正確的賬號密碼(root/root1234)。 預期:登入成功,跳轉到搜尋介面
  • 用例2:輸入正確的賬號,錯誤的密碼。 預期:登入失敗並給出提示資訊:密碼錯誤,請輸入正確的密碼
  • 用例3:不輸入賬號輸入密碼點選登入。 預期:登入失敗並給出提示資訊:請輸入賬號密碼後再點選登入!
  • 用例4:輸入賬號不輸入密碼點選登入。 預期:登入失敗並給出提示資訊:請輸入賬號密碼後再點選登入!
  • 用例5:不輸入賬號密碼點選登入。 預期:登入失敗並給出提示資訊:請輸入賬號密碼後再點選登入!
  • 用例6:輸入錯誤的賬號密碼。 預期:登入失敗並給出提示資訊:賬號密碼錯誤,請檢查賬號密碼
4.2.1 編寫RF程式碼

4.2.1.1 目錄結構

4.2.1.2 相關程式碼

點選檢視login_keywords.robot程式碼
*** Comments ***
登入相關的全域性關鍵字
*** Settings ***
Library    SeleniumLibrary   
*** Variables ***
${IMPLICIT_WAIT_TIME}    5
${LOGIN_URL}    http://127.0.0.1:5500/view/login.html
*** Keywords ***
OPEN LOGIN PAGE
    Open Browser    ${LOGIN_URL}    chrome
    Set Selenium Implicit Wait    ${IMPLICIT_WAIT_TIME}
點選檢視keywords.robot程式碼
*** Comments ***
登陸頁面用到的關鍵字
*** Settings ***
Library    SeleniumLibrary   
*** Keywords ***
INPUT USER AND PASSWORD
    [Arguments]    ${username}   ${password}
    [Documentation]    輸入使用者名稱(username)和密碼(password)
    Input Text    locator=//input[@id="username"]    text=${username}
    Input Text    locator=//input[@id="password"]    text=${password}
    Click Element    locator=//input[@type="submit"]
點選檢視login.robot程式碼
*** Comments ***
測試登陸頁面
*** Settings ***
Library    SeleniumLibrary    
Resource    ../keywords/login_keywords.robot
Resource    ./keywords.robot
Suite Setup    OPEN LOGIN PAGE    #自定義關鍵字
Suite Teardown    Close Browser
*** Test Cases ***
登入成功
    [Tags]    smoke    login    P    #標籤
    INPUT USER AND PASSWORD    username=root    password=root1234    #使用自定義關鍵字
    Element Should Be Visible    locator=//h1[text()='資料搜尋頁面']
登入失敗-賬號正確密碼錯誤
    [Tags]    smoke    login    N
    Go To    url=${LOGIN_URL}
    INPUT USER AND PASSWORD    username=root    password=root12345
    ${alert_message} =    Handle Alert 
    Should Be Equal As Strings    ${alert_message}    密碼錯誤,請輸入正確的密碼!
登入失敗-不輸入賬號
    [Tags]    smoke    login    N
    Go To    url=${LOGIN_URL}
    INPUT USER AND PASSWORD    username=    password=root1234   
    ${alert_message} =    Handle Alert 
    Should Be Equal As Strings    ${alert_message}    請輸入賬號密碼後再點選登入!
登入失敗-不輸入密碼
    [Tags]    smoke    login    N
    Go To    url=${LOGIN_URL}
    INPUT USER AND PASSWORD    username=root    password=  
    ${alert_message} =    Handle Alert 
    Should Be Equal As Strings    ${alert_message}    請輸入賬號密碼後再點選登入!  
登入失敗-不輸入賬號和密碼
    [Tags]    smoke    login    N
    Go To    url=${LOGIN_URL}
    INPUT USER AND PASSWORD    username=    password=    
    ${alert_message} =    Handle Alert 
    Should Be Equal As Strings    ${alert_message}    請輸入賬號密碼後再點選登入! 
登入失敗-賬號密碼錯誤
    [Tags]    smoke    login    N
    Go To    url=${LOGIN_URL}
    INPUT USER AND PASSWORD    username=root1   password=root1234
    ${alert_message} =    Handle Alert 
    Should Be Equal As Strings    ${alert_message}    賬號密碼錯誤,請檢查賬號密碼!
*** Keywords ***
#此處用來設定變數

4.2.1.3 其他說明

  • 有一些步驟是重複的,此時可以採用自定義關鍵字的寫法,提高效率。robot檔案之間是可以相互引用的,例如A.robot要引用B.robot裡的關鍵字,只需要在A.robot的Settings處透過使用Resource關鍵字引用B.robot檔案,即可使用B.robot檔案裡頭的Keywords。至於檔案命名以及目錄命名這個就需要自己結合專案的實際情況去建立,一個好的清晰的目錄結構有利於專案分工合作和後期擴充,所以還是需要想一下的。
  • 在vscode也支援單個執行用例、按套件執行用例、按目錄執行用例,除錯同理。

五 可能遇到的問題

5.1 怎麼判斷自己寫的xpath、css選擇器是否正確?

可以利用谷歌開發者工具,在元素這裡按f出現搜尋框,再將我們的xpath貼上去,如果能搜尋到就代表我們寫的路徑沒錯。需注意檢查一下有幾個搜尋結果,使用相對路徑的情況下,匹配條件不充分可能會匹配到多個結果。

5.2 怎麼了解Library裡面的關鍵字,或者說怎麼快速判斷應該使用哪一個關鍵字

對關鍵字的使用基本上是熟能生巧,不熟悉的情況可以藉助chatGPT也可以去Library對應的官網,會有關鍵字文件說明

  • 去官網查閱關鍵字文件說明

  • 藉助chatGPT,但chatGPT是有可能輸出錯誤答案的,要適當的舉一反三

相關文章