這次是結合 pytest 和 uiautomator2 完成一個 UI 自動化項目。裡面會包含一個完整的 Android UI 自動化項目該有的基本内容,額外的功能可以自行擴充。不打算說廢話,接下來會先放上目錄結構,後面直接是代碼,具體的講解内容放在代碼注釋中。
目錄結構
- testcases
- example_test.py
- package
- com.example.apk
- conftest.py
- main.py
- pytest.ini
testcases 檔案夾記憶體放的是測試用例,裡面可以再建立檔案夾來根據用例頁面或功能來分别存放不同的測試用例檔案。
package 檔案夾記憶體放安裝包。
conftest.py 此檔案内實作手機連接配接、應用安裝等操作的 fixture 函數。
main.py 程式化運作入口。
pytest.ini pytest 的配置檔案。
代碼及講解
我們假設被測應用的包名是 com.example,存放路徑是 package/com.example.com。
代碼運作需要安裝 pytest,uiautomator2,pytest-html
首先看下 pytest.ini 檔案内容
[pytest]
filterwarnings:
ignore::UserWarning
testpaths:
testcases/
addopts:
-s
-v
--lf
--html=report.html
--capture=fd
--self-contained-html
markers:
login: 登入
filterwarnings:配置項 ignore::UserWarning 為忽略使用者錯誤,比如 markers 裡沒有完整包含測試用例裡的标記,就會有警告錯誤,添加此項配置,就不會再提示此警告。
testpaths:測試檔案夾或測試檔案,可以配置多項。
addopts:測試參數,運作測試時和傳入的參數取并集。
markers:注冊測試用例的标記。
conftest.py 檔案内容
import pytest
import uiautomator2
d = None
def pytest_addoption(parser):
"""pytest 自帶的參數解析函數,可以讓我們自定義傳入一些參數,如果要傳入自定義參數需要将參數指派給--cmdopt"""
parser.addoption("--cmdopt", action="store", default="{}")
@pytest.fixture(scope="session", autouse=True)
def driver(request):
"""此 fixture 函數在整個測試運作之前運作一次"""
global d # 将 d 聲明為全局變量,友善其它函數使用
cmd_opt = request.config.getoption("--cmdopt") # 此處擷取自定義參數
cmd = eval(cmd_opt) # 此處解析自定義參數
d = uiautomator2.connect() # 連接配接手機
if cmd.get("apk_path"): # 判斷是否傳入自定義參數 apk_path,如果傳入了該參數則執行安裝步驟
d.app_install(cmd.get("apk_path"))
yield d # 傳回手機連接配接,可以使其它函數或方法使用 d
print("測試結束") # 整個測試結束會輸出”測試結束“
@pytest.fixture(autouse=True)
def teardown():
"""每條測試用例執行結束,會關閉測試應用"""
yield
d.app_stop("com.example")
測試用例檔案
import pytest
@pytest.mark.login
class TestLogin:
"""測試登入,打标記為 login"""
def test_of_login(self, driver):
driver.open_url("example://example.com/login") # 通過 url 方式打開應用登入界面
driver(resourceID="com.example:id/user_name").click() # 點選使用者名輸入框
driver.send_keys("test_user") # 第一種輸入内容方式,使焦點在輸入框時,直接輸入内容
driver(resourceID="com.example:id/user_name").send_keys("123456") # 第二種輸入内容的方式,直接向指定的元素輸入内容
driver(resourceID="com.example:id/submit").click() # 點選登入
exists = driver(resourceID="com.example:id/user_center").exists() # 判斷是否進入了個人中心
assert exists is True # 進入個人中心則對應的元素存在,即 exists 為 True,測試用例通過
main.py 檔案内容
import pytest
from os import path
ROOT_PATH = path.dirname(__file__) # 擷取項目根目錄
apk_path = path.join(ROOT_PATH, "package", "com.example.apk") # 擷取安裝包路徑
# --cmdopt傳入的就是自定義參數,參數為 apk_path,是安裝包的路徑
# 如果手機已安裝測試包,可以将 apk_path 設定為 None,則在測試最開始就不會執行安裝應用的步驟
pytest.main(["--cmdopt={'apk_path':" + apk_path + "}"]) # 運作測試
最後
上面代碼内應用相關的内容替換成自己所要測試的應用,就可以運作起來一個簡單的 UI 自動化測試。其實上面的内容雖然簡單,但五髒已經俱全,大家可以在此基礎上進行擴充,比如可以将連接配接手機操作進行二次封裝,增加重試等操作,元素相關的方法也可以進行二次封裝,添加一些等待,或設定好逾時時間,來增加代碼穩定性;元素表達式可以單獨存放,避免後期元素修改的麻煩;一些固定的操作也可以封裝起來,友善代碼編寫,減少重複代碼等。
pytest 和 uiautomator2 都很強大,功能非常多,是很值得用心去探索的。由于比較忙,隻能比較簡單的介紹相關的内容,大家有問題可以私信,有時間可以一起讨論交流,互相學習。