avatarWis

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

3966

Abstract

mage: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div> </div> </div> </a> </div><p id="2c61">下載完成後執行安裝檔,選擇所需要的 Tools 。</p><blockquote id="ad15"><p>當然~你想要全部裝也是可以:D</p></blockquote><figure id="12d3"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*tK8ldZMGwLqp4WcC.png"><figcaption></figcaption></figure><p id="e074">安裝完成後可至安裝路徑開啟 Inspector.exe</p><div id="0b55"><pre><span class="hljs-attribute">C</span>:\Program Files (x86)\Windows Kits<span class="hljs-number">10</span>\bin<span class="hljs-number">10</span>.<span class="hljs-number">0</span>.<span class="hljs-number">19041</span>.<span class="hljs-number">0</span>\x64</pre></div><figure id="ab18"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*5dxfaU7gWHzxH41sPtGbcw.png"><figcaption></figcaption></figure><p id="2c6a">接著,開啟小算盤作為範例,打開標記顯示。</p><p id="08fa">當選取元件時,可以清楚的知道目前所選的是哪個元件。</p><figure id="625a"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ADjBdYjbyPX4CE5cp9JC6w.png"><figcaption></figcaption></figure><p id="17ef">來理解一下,元件屬性與 Appium Client API 的對應關係表:</p><figure id="5784"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*mbxdZeca7-1ciDlqJcfkBQ.png"><figcaption></figcaption></figure><figure id="4c01"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*MIxLjXAq8A05JA0hvgp1ZA.png"><figcaption></figcaption></figure><p id="a90f">當選擇標記某個 Application GUI 元件時,會在 inspector.exe 內看到這些屬性,當你了解屬性的對應之後就可以開始寫程式囉~</p><h1 id="8ad6">程式碼開發</h1><h2 id="87ba">Python 套件安裝</h2><div id="4ca0"><pre>pip install Appium-Python-<span class="hljs-built_in">Client</span></pre></div><h2 id="5b87">連接 Application</h2><p id="ef7e">這裡使用 Speccy 為例,想做出一個右邊黃色框框主要資訊畫面的截圖。</p><figure id="a166"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*TzV01o8P4i2KIlNkmnGL1g.png"><figcaption></figcaption></figure><div id="f324"><pre><span class="hljs-keyword">from</span> appium <span class="hljs-keyword">import</span> webdriver</pre></div><div id="5cf8"><pre><span class="hljs-keyword">def</span> <span class="hljs-title function_">setup_application_driver</span>(): desired_caps = {} desired_caps[<span class="hljs-string">'app'</span>] = <span class="hljs-string">r"C:\Program Files\Speccy\Speccy64.exe"</span> desired_caps[<span class="hljs-string">'paltformName'</span>] = <span class="hljs-string">"Windows"</span> desired_caps[<span class="hljs-string">'deviceName'</span>] = <span class="hljs-string">"WindowsPC"</span> driver = webdriver.Remote( command_executor=<span class="hljs-string">'http://127.0.0.1:4723'</span>, desired_capabilities=desired_caps) <span class="hljs-keyword">return</span> driver</pre></div><p id="020a">使用上面這段程式碼,連結已啟動的 WinAppDriver。</p><p id="c384"><i>( 注意:如果有改 IP or Port 記得修改程式碼內容 )</i></p><figure id="09a5"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ctpnJj7QLI_rgQzPU1TCpA.png"><figcaption></figcaption></figure><p id="c75e">如上圖,在 inspector.exe 選擇使用 class name 作為定位元件的方式 ( <i>因為其他的屬性都不夠單一 ,容易造成定位錯誤</i> )。</p><p id="f5e9">接著,透過下面這段程式碼實現截圖功能:</p><div id="7cb9"><pre><span class="hljs-keyword">from</span> <span class="hljs-built_in">io</span> <span class="hljs-keyword">import</span> BytesIO <span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image</pre></div><div id="dee3"><pre>def <span class="hljs-built_in">operate_speccy</span>(driver: webdriver): full_png = driver.<span class="hljs-built_in">get_screenshot_as_png</span>() <span class="hljs-built_in">take_element_screenshot</span>(full_png, driver.<span class="hljs-built_in">find_element_by_class_name</span>(<span class="hljs-string">"SpeccyTree"</span>), <span class="hljs-string">"main_window.png"</span>)</pre></div><div id="3429"><pre><span class="hljs-function">def <span class="hljs-title">take_element_screenshot</span><span class="hljs-params">(full_png, element, fi

Options

lename)</span>: location =</span> element.location size = element.size left = location[<span class="hljs-string">"x"</span>] top = location[<span class="hljs-string">"y"</span>] right = location[<span class="hljs-string">"x"</span>] + size[<span class="hljs-string">"width"</span>] bottom = location[<span class="hljs-string">"y"</span>] + size[<span class="hljs-string">"height"</span>]</pre></div><div id="81e0"><pre> <span class="hljs-keyword">im</span> = Image.<span class="hljs-keyword">open</span>(BytesIO(full_png)) <span class="hljs-keyword">im</span> = <span class="hljs-keyword">im</span>.crop((<span class="hljs-keyword">left</span>, top, <span class="hljs-keyword">right</span>, bottom)) <span class="hljs-keyword">im</span>.save(filename)</pre></div><p id="bd2c">因為使用 Appium 所提供的 element screenshot api 出現未知錯誤導致無法完成物件截圖,所以這裡這段 element screenshot 的做法,是一個 workaround.</p><p id="42ca">這段採用的邏輯是,先用 Appium 提供的完整 Application 截圖,把整張畫面擷取下來,再使用 Appium 定位的元件的位置(長,寬,高),當作圖片裁切的點位依據,也就是對應到上方的 function “take_element_screenshot” 程式碼片段。</p><h1 id="5423">結果</h1><p id="11fd">下圖是經由程式碼截圖出來的結果,可以發現到因為程式碼執行的很快速,在 Speccy 還在 loading 時,就已經把圖片截圖完成,如果是要擷取正確的資訊,需要做一些等待或是找一個判斷條件來使程式做優雅的等待:D</p><figure id="b9e7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*jTOV1JS5lKeeposi0wi1dg.png"><figcaption></figcaption></figure><p id="0d4a">初次玩玩的小筆記,等之後多踩一點地雷~再繼續研究~</p><p id="5ecb">附上完整程式碼:</p> <figure id="b7e7"> <div> <div>

            <iframe class="gist-iframe" src="/gist/WisChang005/88cafcb71a5814b19b2c01d83b20d78f.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><blockquote id="9690"><p>那我們就下集待續吧~:D</p></blockquote><h1 id="370f">Reference</h1><div id="59a1" class="link-block">
      <a href="https://github.com/microsoft/WinAppDriver/blob/master/Docs/CI_AzureDevOps.md">
        <div>
          <div>
            <h2>microsoft/WinAppDriver</h2>
            <div><h3>Microsoft Docs: Azure Pipelines Agents - guidelines for setting up your own private "self-hosted" agent. UI testing for…</h3></div>
            <div><p>github.com</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*xTdkxZ5yQuy4FH_O)"></div>
          </div>
        </div>
      </a>
    </div><div id="0b66" class="link-block">
      <a href="https://maestralsolutions.com/windows-desktop-application-test-automation-with-winappdriver-and-net-core/">
        <div>
          <div>
            <h2>Windows Desktop Application Test Automation with WinAppDriver and .NET Core - Maestral Solutions</h2>
            <div><h3>To date, almost all QA Engineers have been testing Web and Mobile applications almost exclusively. But have you ever…</h3></div>
            <div><p>maestralsolutions.com</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*qL_PrSGXjrbS914n)"></div>
          </div>
        </div>
      </a>
    </div><div id="d755" class="link-block">
      <a href="https://www.dotblogs.com.tw/yc421206/2019/03/19/via_Appium_and_WinAppDriver_UI_Test_Automation_on_Windows_Applications">
        <div>
          <div>
            <h2>余小章 @ 大內殿堂</h2>
            <div><h3>他是一套類 Selenium 的 UI 測試框架,先來看看他的架構,由下圖可以得知 WinAppDriver 可以驅動 Windows 的應用程式,用 JSON 跟外部程式進行資料交換、控制,WinAppDriver 也整合…</h3></div>
            <div><p>www.dotblogs.com.tw</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div>
          </div>
        </div>
      </a>
    </div></article></body>

[Python] Windows 應用程式自動化 GUI Automation — WinAppDriver

最近心血來潮玩玩 WinAppDriver ,使用起來簡單方便,也能夠整合 Appium,程式語法跟 Selenium 很接近,還能跟 Azure Pipeline 做整合,就來寫個筆記記錄下來~

使用者介面 (UI) 的測試一直是所有 QA & RD 的痛點吧 QAQ 每次有新的版本就必需跑一遍 Regression,為了確保品值穩定。

但往往使用者介面如果做了自動化測試常常會有不穩定的情況,Windows Application GUI 自動化雖然很多工具可以選擇,例如早期使用過 Pywinauto 做 Windows 使用者介面自動化,長期下來顯得難以維護,程式碼龐大,語法複雜...實在有點悲劇。

就來看看 WinAppDriver 是怎麼做的吧!

https://maestralsolutions.com/windows-desktop-application-test-automation-with-winappdriver-and-net-core/

WinAppDriver 安裝

可以到微軟的 WinAppDriver GitHub. 下載安裝包 msi 檔。

安裝完成之後 WinAppDriver 會安裝到 C:\Program Files (x86)\Windows Application Driver 這個路徑底下。

打開 cmd.exe 之後執行 WinAppDriver.exe 會發現,出現了錯誤。原因是因為需要先把 Win10 的開發人員模式開啟。

設定 > 開發人員專用 > 開發人員模式。

接著,再次執行 WinAppDriver.exe 就能在 console 上看到 WinAppDriver 已啟動成功在 http://127.0.0.1:4723

也可以自行改變 IP and Port,可以使用:

WinAppDriver.exe /h

如果是想把 WinAppDriver 寫下 log 檔並且跑在背景執行,可以使用:

Start /B WinAppDriver.exe > C:\WinAppDriver.log

Windows 應用程式元件定位

如果之前有寫過 Selenium 必定知道元件定位需要一些屬性例如 id, name, class…,這些元件屬性需要透過 Element Inspector 去定位,微軟爸爸有提供一個工具讓開發者使用,需要先安裝 Windows 10 SDK。

下載完成後執行安裝檔,選擇所需要的 Tools 。

當然~你想要全部裝也是可以:D

安裝完成後可至安裝路徑開啟 Inspector.exe

C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64

接著,開啟小算盤作為範例,打開標記顯示。

當選取元件時,可以清楚的知道目前所選的是哪個元件。

來理解一下,元件屬性與 Appium Client API 的對應關係表:

當選擇標記某個 Application GUI 元件時,會在 inspector.exe 內看到這些屬性,當你了解屬性的對應之後就可以開始寫程式囉~

程式碼開發

Python 套件安裝

pip install Appium-Python-Client

連接 Application

這裡使用 Speccy 為例,想做出一個右邊黃色框框主要資訊畫面的截圖。

from appium import webdriver
def setup_application_driver():
    desired_caps = {}
    desired_caps['app'] = r"C:\Program Files\Speccy\Speccy64.exe"
    desired_caps['paltformName'] = "Windows"
    desired_caps['deviceName'] = "WindowsPC"
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        desired_capabilities=desired_caps)
    return driver

使用上面這段程式碼,連結已啟動的 WinAppDriver。

( 注意:如果有改 IP or Port 記得修改程式碼內容 )

如上圖,在 inspector.exe 選擇使用 class name 作為定位元件的方式 ( 因為其他的屬性都不夠單一 ,容易造成定位錯誤 )。

接著,透過下面這段程式碼實現截圖功能:

from io import BytesIO
from PIL import Image
def operate_speccy(driver: webdriver):
    full_png = driver.get_screenshot_as_png()
    take_element_screenshot(full_png, driver.find_element_by_class_name("SpeccyTree"), "main_window.png")
def take_element_screenshot(full_png, element, filename):
    location = element.location
    size = element.size
    left = location["x"]
    top = location["y"]
    right = location["x"] + size["width"]
    bottom = location["y"] + size["height"]
    im = Image.open(BytesIO(full_png))
    im = im.crop((left, top, right, bottom))
    im.save(filename)

因為使用 Appium 所提供的 element screenshot api 出現未知錯誤導致無法完成物件截圖,所以這裡這段 element screenshot 的做法,是一個 workaround.

這段採用的邏輯是,先用 Appium 提供的完整 Application 截圖,把整張畫面擷取下來,再使用 Appium 定位的元件的位置(長,寬,高),當作圖片裁切的點位依據,也就是對應到上方的 function “take_element_screenshot” 程式碼片段。

結果

下圖是經由程式碼截圖出來的結果,可以發現到因為程式碼執行的很快速,在 Speccy 還在 loading 時,就已經把圖片截圖完成,如果是要擷取正確的資訊,需要做一些等待或是找一個判斷條件來使程式做優雅的等待:D

初次玩玩的小筆記,等之後多踩一點地雷~再繼續研究~

附上完整程式碼:

那我們就下集待續吧~:D

Reference

Selenium
Appium
Winappdriver
Automation Testing
Python
Recommended from ReadMedium