跳到主要內容

發表文章

目前顯示的是有「Robot Framework」標籤的文章

升級SeleniumLibrary到4.5.0與Selenium到3.141.0

最近我們將RobotFramework升級至4.1.2,因為Jython的關係這個是目前可以使用Java執行的最後版本。 我們目前Selenium相關的Libraries版本如下: Selenium2Library - 3.0.0 (Latest, https://github.com/robotframework/Selenium2Library ) SeleniumLibrary - 3.0.0 ( https://github.com/robotframework/SeleniumLibrary/releases ) Selenium - 3.8.0 其中Selenium2Library已經沒在維護,也是最後一個版本,它所做的事情僅僅是把keyword forward給SeleniumLibrary。所以升級重點在SeleniumLibrary與Selenium。 而要升級這些Libraries,最重要的就是要知道它們彼此之間的相依,還有python版本的支援度。在我查詢套件的release note之後,因為4.1.2版本的jython只能支援到python 2.7.x,所以能升級的版本就有限制。其中SeleniumLibrary的情況如下: SeleniumLibrary 5.0.0 - 不支援Python 2 and Jython  SeleniumLibrary 4.5.0 - Python 2.7 and Selenium 3.141.0+  SeleniumLibrary 3.3.1 - Python 2.7 and Selenium 3.4+ 所以搭配了Selenium後,以下為我的第一個升級計畫: Selenium - 3.141.0 SeleniumLibrary - 3.3.。主要想確定是否會有deprecated items產生。 升級方式就是把以上原始碼丟到Lib底下,執行robot測試的時候會透過jython重新編譯。在我執行後,出現了urllib3找不到的問題: 我想可能是原本的套件中有包含urllib3,因此我到urllib3的package網站查了release note,找了可以匹配python 2.7的版本: urllib3 - 1.26.20 (https://pypi.org/project/...

Robot Framework升級到4.1.2之後,為何Jenkins的Report突然不會報錯了?

最近我們在把Robot升級到3.2.2之後,我想說試試看4.1.2,於是就直接升了上去。沒想到daily build的測試沒發生任何異常。 但不幸的是Jenkins的報表怪怪的: 發生錯誤確Build Success! 趁著颱風假,比較了一下發現新版本的Critical tests測試項目皆為0: 查了一下 官方文件 發現是因為4.0之後,已經把Critical tests概念刪除了,詳細可以參考: Migrating from criticality to SKIP。 解決方法有3種, 自己定義Critical tests,不過看起來5.0就移掉了。 可能可以更新robot framework plugin。我們版本很舊,是1.6.4。因為目前還沒有更新jenkins的計畫,所以我使用了第三個方法。 Build成功與否的Threshold別用Critical tests。 最後測試結果:

解決RobotFramework從3.1.2升級到3.2.2之後,Choose File突然會整個Hand住的問題

考慮到自動測試環境的維護,我們很久以前就使用java去執行robot framework。前陣子開始處理從3.1.2升級到3.2.2的事情,主要先把明確的runtime語法錯誤與deprecate item處理好,這部分內容可以參考: link 。 直到最近才發現,透過SeleniumLibrary執行Choose File去上傳檔案的動作,會導致測試案例timeout。本篇文章主要分享心路歷程與解決方法,我也送了一條issue給robot framework: link 。 我的環境如下: RobotFramework: 3.2.2 Selenium: 3.141.0 SeleniumLibrary: 3.3.1 Remote Selenium Version: selenium-server-standalone-3.141.59 首先並非所有Choose File的動作都會hang住,有些測試案例是可以執行的,但是上傳一個作業系統ISO檔案一定會發生問題。後來我透過wireshark去比對新舊版本的上傳動作,因為我使用 Remote Selenium ,所以Selenium會先把檔案透過REST API發送到Remote Selenium Server上。從下圖我們可以發現,在3.2.2的最後一個TCP封包,比3.1.2大概少了500個bytes。 於是就開始了我trace code之路。包含SeleniumLibrary產生要送給Remote Selenium Server的request內容,還有HTTP Content-Length的計算,我都確認過沒有問題。 最後發現問題是出在socket API的使用上,就是下圖的這支code: 最後發現可能因為開始使用nio的方式送資料,但沒處理到尚未送完的資料內容,而導致發生問題。加一個loop去做計算就可以解決了。 最後我有把解法提供給robot framework官方,在他們出新的版本之前,我是將改完的_socket.py放在我們自己的Lib底下,好讓我們測試可以正常進行。(shutil.py應該也是為了解某個bug而產生的樣子..)

Jython+Selenium2Library無法在Windows上啟動Firefox

Problem 這陣子開始著手於升級Selenium2,我們的環境是透過Java啟動RobotFramework(2.9),在Runtime時去編譯Selenium與Selenium2Library。這樣的模式在Linux上,可以正常的跑完測試用的測試案例;然而在Windows上卻會出現如下圖錯誤: How to? 首先會發現firefox並沒被啟動,然後有OSError: Operation not permitted。後來花了一些時間trace了Selenium的程式碼,發現錯誤是在複製firefox profile到暫存資料夾產生的: # firefox_profile.py的__init__ shutil . copytree ( self . profile_dir , newprof , ignore = shutil . ignore_patterns ( "parent.lock" , "lock" , ".parentlock" ) ) 雖然檔案都有被複製完成,但就是會發生錯誤;雖然嘗試將例外catch起來吃掉,但不只這地方會發生問題。於是我就開始找尋原因。我將robotframework.jar中Lib/shutil.py.class刪除,並將shutil.py複製到Lib資料夾下: 後來發現問題是在copystat>copystat做hasattr(os, 'chflags')的動作。原本程式碼中,有針對Windows發生例外(WindowsError)時,會做pass的動作: try : copystat ( src , dst ) except OSError , why: if WindowsError is not None and isinstance ( why , WindowsError ) : # Copying file access times may fail on Windows pass else : errors. append ( ( ...

Robot Framework - How to assert multiple text node?

Problem 傳統的網頁資料更新,都是透過刷新整頁方式;隨著javascript的普及化,進步到針對dom node刷新。而資料型態如果為遞增的方式,像jenkins build info或是動作執行過程,很可能為了效能不針對整個node刷新,而採用append的方式。透過瀏覽器所提供的Element檢測器,會看到如下圖情況: 一個pre code底下包含了三個text node,當在Selenium IDE與Chrome Developer Tools中使用以下xpath,由於是找到第一個,所以無法找到任何批配的節點: 本篇文章主要告訴你,如果某個節點資料是動態插入的,該如何透過selenium去做assertion。 How to? 以我的測試網頁為例子,要能搜尋到text包含g2的字串,可用以下兩個xpath: 透過index指定位置: //pre[contains(text()[2],'g2')] 先列出所有text()項目再給予條件: //pre[text()[contains(.,'g2')]] 但在動態生成的網頁中,很難直接指定index去做assertion。綜合這兩個做法,並試驗一些可能可用的keyword,如下: 除了第二個是我們原先問題會錯之外,其餘的都能正常找到指定項目。所以目前有兩個解法: text()優先的xpath。 使用Wait Until Element Contain與Element Should Contain: 通常適用於node有好辨別的特徵,如id。 測試網頁 <!DOCTYPE html> < html > < head > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js" >< / script > < script > $(document).ready(function(){ $("#gg").append('g1'); $("#gg").append('g2'); $("#gg...

Robot Framework - No active session with ID problem

Problem 這陣子將SeleniumLibrary升級至3.0.0,且selenium node中的server升級至3.8.1、firefox使用Mozilla GeckoDriver 0.19.0。沒想到當天晚上跑完自動測試後,出現了大量錯誤,其中一個就是No active session with ID: 在發生問題後,如果執行除了Open Browser以外的動作,如Set Selenium Timeout、Capture Page Screenshot或Close All Browsers,就會出現如上述訊息,而selenium node上的機器會有大量的瀏覽器開啟且沒有關閉。 本篇文章主要分享我發現的原因與避掉方式。 How to? 經過trace,在我們的測試中,必須經過一定步驟才會發生問題。以下是我簡化模擬出來的情況: 在testcase 1中close window後,目標機器瀏覽器會被關閉,這也導致close all browser會出問題;而在testcase 2雖然重新啟動了一個新的瀏覽器,但selenium卻無法獲得新的session id。 因此,最後將重複關閉(Close Window)的行為給拿掉就可以“避掉”問題了。

StaleElementReferenceException: Message: stale element reference: element is not attached to the page document

Problem 這陣子把SeleniumLibrary更新到了3.0後,開始發生測試不穩定的問題;其中一樣就是在呼叫Get Text時,發生StaleElementReferenceException: Message: stale element reference: element is not attached to the page document的問題。 How to resolve? 參考網路上資料,大都說是由於要存取的目標沒出現在網頁上;然而在我們測試報表中,Screenshot是看的到我們所要操作的目標。因此我們推測可能是由於websocket引起的refresh所造成的。面對這個問題,我們採取retry的做法: Get Text [ Arguments ] ${locator} ${text} Wait Until Keyword Succeeds 2x 10ms Selenium2Library.Get Text ${locator} [ Return ] ${text} 透過Wrapper的方式,把SeleniumLibrary的GetTex包在WrapperLibrary內去達到retry的效果。 與其說真的解決,不如說這是個workaround。 Reference stale element reference: element is not attached to the page document Stale Element Reference Exception

Robot Framework - SSL Certificate Error On IE11

Problem 這陣子我們將web連線預設由原本的http轉到https,然而在透過IE做驗收測試時,出現了Certificate Error而導致測試無法繼續下去: 本篇是分享我實驗過與可能的解決方法。 How to resolve? 我們使用selenium grid的方式做測試,selenium的node搭載環境如下: OS: Windows2012 R2 x64 IE: IE 11.0.9600.18618 selenium-server-standalone: 3.8.1 IEDriverServer: 3.4.0.0 (32.bit) 接下來分享我實驗的方法: 使用desired_capabilities 我在Open Browser的keyword之後加入以下參數: desired_capabilities=acceptSslCerts:true;trustAllSSLCerficates:true 透過grid node的console可以看到參數有傳過去,但無法解決問題。 更新IEDriverServer 我將版本更新到3.8.0.0,但Open Browser會有錯誤訊息;礙於時間關係,就不繼續追蹤下去。 調整IE11設定 起初我調整Internet Options > Advanced設定,但沒作用: 接著我改使用匯入Certificate的方式,點擊Certificate error > View Certificates > Install Certificate: 按照安裝步驟點下去,唯一要注意的是,憑證放置位置要選Trusted Root Certification Authorities: 完成之後重新啟動IE還是會看到Certificate Error,但錯誤已經變成Address Mismatch,這是由於簽發的名稱與實際連線主機名稱不同: 所以要去改IE設定,取消這個檢查: 重新啟動IE後應該就能夠正常執行測試。 這個方法只適用於專門測試的機器,一般正常使用的機器這樣做會降低安全性;此外,如果憑證有改或新增就要再執行匯入,比較不方便。 Reference Selenium Grid cannot launch IE11 and report IE driver cannot bypass insecure SS...

Robot Framework - Choose File在Remote Selenium上的問題

如果透過Remote Selenium Server去執行測試,在跑Robot上的測試資料該如何讓遠端機器取得呢? 經過爬文發現,Selenium2Library的Choose File已解決這問題; 目前Windows上常常有卡住的問題,即使設定timeout也無法解決: related issue 這個issue中有人使用2.4x版本,我們是使用2.48 根據IE driver changelog 內容,3.3版本後應該要有解。

Robot Framework - Element is not clickable issue on chrome

Problem 這陣子將SeleniumLibrary升級至3.0之後,在Firefox上測試遇到難以解決的問題,也因此將測試瀏覽器改為Chrome;然而移到chrome之後,原先可以在firefox上執行的測試,反而變得無法執行。其中一樣就是出現Element is not clickable的問題。 How to resolve? 我要點擊的位置是Refresh的button: 而我一開始使用的xpath是 //span[text()='Refresh'] 但卻出現了以下錯誤訊息: WebDriverException: Message: unknown error: Element < span class = "ui-button-text" > ... < / span > is not clickable at point (805, 96). Other element would receive the click: < span class = "ui-button-icon-primary ui-icon ui-icon-refresh" >< / span > (Session info: chrome=63.0.3239.132) (Driver info: chromedriver=2.34.522940 (1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 6.3.9600 x86_64) ChromeDriver使用模擬方式去點element中間的位置;假如你所給予的位置是使用者點不到的位置,就有可能會發生這樣的問題。 舉例來說,使用一個modal dialog會讓背景呈現蓋住的效果;對使用者來說,背景是無法點擊的。假如這時候透過ChromeDriver去點擊背景的element,就會發生無法點擊的問題。 以我的問題來說,將xpath改為圖片或button的xpath即可解決。 因此,Click Element的xpath最好是設定為使用者一定可以點擊的到的位置。 Reference Chrome - Element is not clickabl...

Robot Framework - 無效的Default Test Setup與Tear Down

Problem 某天同事問我,他在Setting Table中設定了Default Test Setup與Teardown,而TestCase如下圖並沒有設定: 為何Default Test Setup與Teardown不會被執行? How to resolve? 當下從RIDE外觀我看不出原因,只猜測可能是RIDE的bug。後來當我有空去回顧這問題時,我把RIDE切到Text Edit查看原始碼: 發現這是由於Test Setup與Teardown被設置為空的。解決這問題的方法也很容易,只要對個別欄位點擊Clear就能把無用的部份給拿掉。 此外,由於有這問題的測試不少,因此我用Eclipse的regular expression搜尋並做修改,我分享搜尋方式給大家:

Robot Framework: 如何控制div上的scrollbar?

Problem 在使用grid呈現大量資料時,很有可能會發生畫面的長度無法呈現出所有內容;因此在div的style中,會搭配overflow: auto讓長度不足時顯示出scrollbar,如下: 而我在使用Get Text去取得如畫面較右方(index大概第10個)的內容時,都會找不到對應的element;使用Get Source或Get Element Count也都拿不到如預期的資料與數量。經過測試,發現只要將scrollbar往右移就可以解決我們的問題。本篇文章要分享給大家控制div scrollbar的方法。 How to resolve? 我們主要的解決方式是透過Execute Javascript去控制div中的scrollbar,會使用到DOM element的兩個屬性: Element.scrollLeft: 控制橫向scrollbar位置。 Element.scrollTop: 控制垂直scrollbar位置。 假設我們要針對class為viewport element的橫向scrollbar做操作,會這樣寫: Execute Javascript | document.getElementByClassName ( 'viewport' ) [ 1 ] .scrollLeft = 500 如果要對id為grid的垂直scrollbar做操作,會這樣寫: Execute Javascript | document.getElementById ( 'grid' ) .scrollTop = 500 在寫之前,可以先嘗試使用瀏覽器的debug console實驗一下。 Reference selenium之 如何控制网页内嵌div中滚动条的滚动 Element.scrollLeft

WebDriverException: Message: Java heap space

Problem 大部份的軟體在某些情況,肯定會限制使用者所上傳的檔案大小。我們有一個測試想要上傳64M大小的檔案,確出現以下錯誤: How to resolve? 由於我們使用selenium grid方式管理與執行測試,我推測這應該與selenium node的jvm有關。原先我的腳本如下: @ echo off set BASE = % ~dp0 set JAVA_PATH = % BASE % jre\bin\java.exe set PATH = % PATH % ; % BASE % ; set HUB_IP =192.168.0.200   cd / d "%BASE%" "%JAVA_PATH%" -jar selenium-server-standalone-3.141.59.jar -role node -hub http: //% HUB_IP % : 4444 / grid / register -port 5555 我特別設定heap大小後,就能夠解決這個問題: "%JAVA_PATH%" -Xmx1024m -Xss1152k -jar selenium-server-standalone-3.141.59.jar -role node -hub http: //% HUB_IP % : 4444 / grid / register -port 5555

升級RobotFramework從3.0到3.1.2

Square brackets after variable like ${var}[xxx] is considered item access 升級後的錯誤訊息會類似這樣: Variable '${phymemory_tabletr_xpath_prefix}' is string, not list or dictionary, and thus accessing item '2' from it is not possible. 原本的語法如下: ${phymemory_tabletr_xpath_prefix} | Set Variable | // table [ @ class = 'deviceTable' ] / tbody / tr ${speed_or_size_locator} | Set Variable | ${phymemory_tabletr_xpath_prefix} [ 2 ] / th [ 8 ] Robot的 issue 有人和我遇到一樣問題,作者提供在index之前加入反斜線的改法: ${phymemory_tabletr_xpath_prefix} [ 2 ] / th [ 8 ] 改為 ${phymemory_tabletr_xpath_prefix} \ [ 2 ] / th [ 8 ] 應該是3.1版本的內容: link 。 Escaping empty cells with '\' before line continuation marker '...' is deprecated. Remove escaping before Robot Framework 3.2. 目前作者認為'…'是奇怪的語法,打算在3.2中廢掉它,可以參考 issue 3148 ;而我們最常會遇到的地方是在:For中較長的內容會透過反斜線加'…'去銜接。 另外在3.3要廢掉:FOR語法,改用FOR+END去替代它,可以參考 issue 3078 。 在FOR LOOP中,這個問題的解法就是使用FOR+END去取代原本的寫法;但不幸地,我目前用1.7.3的RIDE,會幫我把FOR變回:FOR。 因此我...

Robot Framework - Execute Java Script

Fix Issues 如何控制div上的scrollbar? Scripts Ctrl + A 65為A的key code: ${"body"} .trigger ( { type: 'keydown, which: 65, ctrlKey: true' } ) ; Ctrl + 滑鼠左鍵 假設你要點擊的element包含test_target字串: $ ( ":contains('test_target')" ) .trigger ( { type: 'click' , which: 1 , ctrlKey: true } ) ; 1是左鍵,3是右鍵。 Ctrl + 滑鼠左鍵 - JQuery的Selectable 由於 Selectable 的實作有根據座標位置,單純透過click是無法選到你要的東西,必須使用clickAt。如果要使用trigger,可以使用mousedown+mouseup搭配座標: $ ( ":contains('test_target')" ) .trigger ( { type: 'mousedown' , which: 1 , ctrlKey: true , pageX: 1 , pageY: 1 } ) ; $ ( ":contains('test_target')" ) .trigger ( { type: 'mouseup' , which: 1 , ctrlKey: true , pageX: 1 , pageY: 1 } ) ; (以上是根據JQuery的Source code研究出來的做法)

Robot Framework - How to trace the exception of java keyword library?

Problem 使用java based開發robot keyword的人,大都會遇到發生非預期例外時,不知道root cause在哪,因為你拿到的訊息通常如下: 今天在review前同事的東西時,就遇到了這個問題! 我將分享兩個方法給大家,該如何去拿到詳細的callstack或message。 How to? Run with debug mode 在不修改任何程式碼的情況下,請將以下參數加到你Robot啟動參數中: --loglevel DEBUG 以我的ride為例,會像這樣子: 假如有問題的程式再執行一次,就能看到以下內容: 有了這個call stack以後,相信可以幫助你減少許多追蹤問題的時間。 Catch exception and apply logger 前面的方式適用於問題容易被重現的情況,假如你是偶爾發生問題,就要考慮預先把例外捕捉起來且做Log。在透過java開發robot keyword時,如果你使用以下寫法,會被當作INFO level: System . out . println ( e. getMessage ( ) ) ; INFO level預設情況下,是可以讓你在報表中看到你想要呈現的結果(callstack or exception message);但語意是不是怪怪的呢? 上面那個寫法,等效於: System . out . println ( "*INFO* " + e. getMessage ( ) ) ; 如果你要讓語意清楚點,可以選擇寫成這樣: System . out . println ( "*WARN* " + e. getMessage ( ) ) ; System . out . println ( "*ERROR* " + e. getMessage ( ) ) ; 這個logger方式,可以放在你catch exception後,將callstack或者message印出。假如嫌這個寫法不夠漂亮,更進一步,你可以考慮與log4j或者是java Logger api做整合。 Reference How to pring/log the build-in exception stack trace? RobotFramework U...

Robot Framework+Sikuli(2)-Sikuli Library

Introduction 之前文章 中,介紹給大家透過Sikuli Script的方式將RobotFramework與Sikuli整合在一起的方法。這篇文章要教你另外一種透過將Sikuli API寫成RobotFramework Plugin的方式。 Plugin-Based Sikuli-Robot Integration High Level Architecture 讓我們來看看將Sikuli做成TestLibrary整合示意圖: 基本上就是我們需要去實做一個Sikuli的TestLibrary,我稱為SikuliLibrary,它會依靠Sikuli。實做方法據我所知有兩個,一個是依靠Sikuli自帶的sikuli-script.jar,另外一個是靠同樣SikuliLab的Sikuli API。由於Sikuli API已經將繁複的操作給包成API,因此我選擇它來實做TestLibrary。 Sikuli API 在Sikuli API的官方文件已經有一些Sample Code教導大家如何使用,我就不贅述只做總結。 它有幾個核心物件ScreenRegion、Target、Mouse、Keyboard與Canvas。 ScreenRegion: 螢幕區域,讓你可以在它的範圍內找尋Target。預設範圍為整個桌面。 Target: 目標,基本上就是指你要想操作的圖片。 Mouse: 提供滑鼠相關操作,包含Drag&Drop。 Keyboard: 提供鍵盤相關操作。 Canvas: 畫布,我把它拿來Debug用。可以針對你想要的ScreenRegion做一些畫框框或印文字的動作,讓你可以知道行為操作是否正常。 在Linux上,Sikuli API會相依於OpenCV的函式庫。我是將OpenCV 2.4版抓下來編譯後再將那些so取來用,讓TestLibrary可以portable。 Keywords 目前我想到的操作有: Send Combo Keys: 送出組合鍵。輸入值為AWT KeyEvent名稱,例如Ctrl + Alt + D為VK_CONTROL + VK_ALT + VK_D。 Type String: 輸入字串。 Move Image: 移動圖片到目標位置。 Click Image: 點擊圖片。 Find All Image: 搜尋圖片出現的所有...