android+app測試基礎4+簡單的安卓專案
阿新 • • 發佈:2019-01-10
測試一款安卓app,茄子醫生
主要測試了四個模組
第一個模組:四個引導頁,我們測試是否可以點選跳過,點選跳過後是否能夠找到體驗按鈕
第二個模組:就是登陸模組,簡單的測試一下
第三模組:就是日曆模組,日曆模組看數字是否和今天的日期一致
第四個模組:就是模擬新增預約模組的流程
不多說了,上程式碼,在這裡我用的是mvc封裝寫的
工具類,方便呼叫,建立util包
apputil.py
#-*- coding:utf-8 -*- # 匯入appium from appium import webdriver # 匯入time包 import time # 匯入列舉 from enum import Enum # 倒包from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 宣告類 class Apputil(object): # 類被例項化的時候init def __init__(self): # pep8 規範 # 將配置引數封裝進來 self.qiezi = {} # 開啟客戶端的方法def app_start(self): # 設定屬性 設定手機型別 self.qiezi['platformName'] = "Android" # 設定自動化測試工具 self.qiezi['automationName'] = "Appium" # 設定手機唯一識別碼 self.qiezi['deviceName'] = "emulator-5554" # 設定本地app載入的路徑 self.qiezi['app'] = "/Users/yuliguo/Desktop/com.qiezzi.eggplant.apk" # 是不是需要重寫安裝, True 不需要重新安裝 False 需要重新安裝self.qiezi['noReset'] = "false" # 設定啟動的包名 self.qiezi['appPackage'] = "com.qiezzi.eggplant" # 設定需要執行的手機的版本號 self.qiezi['platformVersion'] = "4.4" # 設定啟動頁面的activity self.qiezi['appActivity'] = "com.qiezzi.eggplant.base.WelcomeActivity" # 設定等待啟動的頁面的包名 self.qiezi['appWaitPackage'] = "com.qiezzi.eggplant" # 設定等待啟動的頁面的activity self.qiezi['appWaitActivity'] = "com.qiezzi.eggplant.base.WelcomeActivity" # 禁用軟體盤 # 使用 unicode 輸入法 self.qiezi['unicodeKeyboard'] = True # 禁用軟體盤 self.qiezi['resetKeyboard'] = True # 將手機啟動起來 self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub",self.qiezi) #設定休眠五秒 self.TimeSleep(ENUMS.FIVE_TIME) pass # 關閉客戶端的方法 def app_quit(self): # 關閉方法 self.driver.quit() pass # 關閉當前視窗 def app_close(self): # 關閉當前視窗 self.driver.close() pass # 使用休眠方法 強制休眠 def TimeSleep(self,number): time.sleep(number) pass # 隱式休眠 def TimeImplay(self,number): self.driver.implicitly_wait(number) # 通過id查詢 # 查詢控制元件 def FindID(self,ID): # 通過id ids = (By.ID,ID) # 休眠檢查元素 WebDriverWait(self.driver,ENUMS.TWENTY_TIME,ENUMS.ONE_HALF).until(EC.presence_of_element_located(ids)) # 開始查詢 return self.driver.find_element_by_id(ID) # 設定點選事件 def ClickID(self,ID): self.FindID(ID).click() # 輸入內容 def SendkeysID(self,ID,message): self.FindID(ID).send_keys(message) #查詢一組控制元件 def FindIDs(self,ID): ids=(By.ID,ID) WebDriverWait(self.driver,ENUMS.TWENTY_TIME,ENUMS.ONE_HALF).until(EC.presence_of_element_located(ids)) return self.driver.find_elements_by_id(ID) #通過下表點選第一個 def ClickIDs(self,ID,index): self.FindIDs(ID)[index].click() #從一個活動到另外一個 def swith_to_element(self,e1,e2): #從e1滑動到e2 self.driver.scroll(e1,e2) pass # 通過xpath查詢 def FindXpath(self,xpath): xpaths = (By.XPATH,xpath) WebDriverWait(self.driver,ENUMS.TWENTY_TIME,ENUMS.ONE_HALF).until(EC.presence_of_element_located(xpaths)) return self.driver.find_element_by_xpath(xpath) # xpath點選事件 def ClickXpath(self,xpath): self.FindXpath(xpath).click() # 設定休眠 以防止在跳轉的時候程式碼執行的速度超過頁面跳轉的速度 self.TimeSleep(ENUMS.TWO_TIME) # 輸入內容 def SendkeysXpath(self,xpath,message): self.FindXpath(xpath).send_keys(message) def FindXpaths(self,xpath): xpaths = (By.XPATH, xpath) WebDriverWait(self.driver, ENUMS.TWENTY_TIME, ENUMS.ONE_HALF).until(EC.presence_of_element_located(xpaths)) return self.driver.find_elements_by_xpath(xpath) def Clickxpaths(self,xpath,index): self.FindXpaths(xpath)[index].click() self.TimeSleep(ENUMS.TWO_TIME) # 根據內容查詢 def FindLink(self,link): links = (By.LINK_TEXT,link) WebDriverWait(self.driver,ENUMS.TWENTY_TIME,ENUMS.ONE_HALF).until(EC.presence_of_element_located(links)) return self.driver.find_element_by_link_text(link) # 設定點選事件 def ClickLink(self,link): self.FindLink(link).click() # 設定休眠 以防止在跳轉的時候程式碼執行的速度超過頁面跳轉的速度 self.TimeSleep(ENUMS.TWO_TIME) # 輸入內容 def SendkesLink(self,link,message): self.FindLink(link).send_keys(message) # 設定休眠 以防止在跳轉的時候程式碼執行的速度超過頁面跳轉的速度 self.TimeSleep(ENUMS.TWO_TIME) # 切換H5 def SwitchH5(self): # 設定休眠 self.TimeSleep(ENUMS.FIVE_TIME) self.driver.switch_to.context("") # 獲取寬度和高度 def getWidth(self): return self.driver.get_window_size()['width'] # 獲取高度發 def getHeight(self): return self.driver.get_window_size()['height'] # 滑動的方法 def swipe(self): # 設定休眠 self.TimeSleep(ENUMS.TWO_TIME) # 滑動 self.driver.swipe(self.getWidth()-50,self.getHeight()/2,50,self.getHeight()/2,1000) # 設定休眠 self.TimeSleep(ENUMS.TWO_TIME) # 獲取當前activity的方法 def getCurrentActivity(self): return self.driver.current_activity # 斷言頁面的方法 def AssertAcitity(self,self1,expect): # 設定休眠時間 self.TimeSleep(ENUMS.FIVE_TIME) # 進行斷言 self1.assertEqual(self.getCurrentActivity(),expect) pass def Assert(self,self1,a): self.TimeSleep(2) self1.assertEqual(self,a,True) pass def AssertCount(self, self1,count, expect): # 設定休眠時間 self.TimeSleep(ENUMS.TWO_TIME) # 進行斷言 self1.assertEqual(count, expect) pass # 定義列舉型別 class ENUMS(Enum): # 10 秒 TEN_TIME = 10 # 20秒 TWENTY_TIME = 20 # 0.5秒 ONE_HALF = 0.5 # 5秒 FIVE_TIME = 5 # 兩秒 TWO_TIME = 2
1.我們先搞歡迎的四個頁面
建立一個welcomec包,包裡建立control包
包下我們建welcomecontrol.py
#-*- coding:utf-8 -*- from util import apputil # 宣告類 class WelcomeControl(object): def __init__(self,app): # 例項化工具類 # self.app = apputil.Apputil() self.app = app pass # 點選新手引導頁 def welcome_next(self): # 使用for迴圈實現滑動 for index in range(0,4): if index< 3: self.app.swipe() else: self.app.ClickXpath("//android.widget.Button[@resource-id='com.qiezzi.eggplant:id/btn_feel_right_now']") pass # 點選新手引導頁 def welcome_next_hide(self): # 使用for迴圈實現滑動 for index in range(0, 4): if index < 3: self.app.swipe() else: # 使用try 方法 try: # 查詢跳過按鈕 self.app.FindID("com.qiezzi.eggplant:id/btn_firstinstall_intent") pass except: self.app.ClickXpath( "//android.widget.Button[@resource-id='com.qiezzi.eggplant:id/btn_feel_right_now']") pass # 滑動到第四個頁面,在往回滑動驗證按鈕能不能使用 # 點選跳過按鈕 # index 1 2 3 在這三個頁面分別點選跳過按鈕, def welcome_jumnp(self,index): # 使用for迴圈的目的就是為了幫助我們滑動頁面 for i in range(0,index): # 滑到我指定的頁面去點選按鈕 if i == index - 1: #查詢控制元件,點選跳過按鈕 self.app.ClickID("com.qiezzi.eggplant:id/btn_firstinstall_intent") # 跳出for迴圈的方法 break pass if i <3: self.app.swipe() passpass
建立unit包,包裡面我們放單元測試
welcome.py
#-*- coding:utf-8 -*- import unittest from util import apputil from welcomec.control import welcomcontrol class Welcome(unittest.TestCase): @classmethod def setUpClass(self): self.app=apputil.Apputil() self.welcome=welcomcontrol.WelcomeControl(self.app) pass def setUp(self): self.app.app_start() pass # def test_welcome_next(self): # u"""點選第四個頁面的立即體驗""" # #進行滑動,同時點選下一步 # self.welcome.welcome_next() # #進行斷言 # self.app.AssertAcitity(self,".login.activity.LoginActivity") # pass # def test_welcome_jump_first(self): # u"""點選第一個頁面的跳過按鈕""" # self.welcome.welcome_jumnp(1) # self.app.AssertAcitity(self,".login.activity.LoginActivity") # pass # # def test_welcome_jump_second(self): # u"""點選第二個頁面的跳過按鈕""" # # # 點選跳過按鈕的封裝,點選第一個頁面 # self.welcome.welcome_jumnp(2) # # 進行斷言 # self.app.AssertAcitity(self, ".login.activity.LoginActivity") # # pass # # def test_welcome_jump_thrid(self): # u"""點選第三個頁面的跳過按鈕""" # # # 點選跳過按鈕的封裝,點選第一個頁面 # self.welcome.welcome_jumnp(3) # # 進行斷言 # self.app.AssertAcitity(self, ".login.activity.LoginActivity") # # pass # # 在第四個頁面,驗證跳過按鈕有沒有隱藏掉,同時立即體驗按鈕是不是顯示出來了 def test_welcome_jump_hide(self): u"""驗證在第四個頁面,跳過按鈕是不是已經隱藏掉,同時立即體驗按鈕是不是能夠點選""" self.welcome.welcome_next_hide() self.app.AssertAcitity(self,".login.activity.LoginActivity") pass註釋很詳細,自己看吧。
我們第二個模組同樣也得封裝c
我們建立loginc包,包下我們建立clogin包
包下我們定義logincontrol.py方法
#-*-coding:utf-8-*- from util import apputil class LoginControl(object): def __init__(self,app): # self.app=apputil.Apputil() self.app=app pass def logn_us_pw(self): # 輸入賬號和密碼 self.app.SendkeysID("com.qiezzi.eggplant:id/edt_frist_login_accout", "18410178656") self.app.SendkeysID("com.qiezzi.eggplant:id/edt_frist_login_password", "123456") # 點選登入 self.app.ClickID("com.qiezzi.eggplant:id/btn_frist_login_immediately") passpass
對登入進行c封裝
單元測試:unit包下我們建立login.py
#-*- coding:utf-8 -*- import unittest # 倒包 from util import apputil from welcomec.control import welcomcontrol from loginc.clogin import logincontrol # 定義類繼承 class Login(unittest.TestCase): @classmethod def setUpClass(self): # 例項化工具類 和 控制類 self.app = apputil.Apputil() # 例項化welcome類 self.welcome = welcomcontrol.WelcomeControl(self.app) # 例項化登陸 self.login = logincontrol.LoginControl(self.app) pass # 開啟瀏覽器 def setUp(self): # 開啟瀏覽器 self.app.app_start() # 點選跳過 self.welcome.welcome_jumnp(1) pass # 關閉瀏覽器 def tearDown(self): self.app.app_quit() pass def test_login_us_pw(self): u"""屬於正確的使用者名稱和密碼""" self.login.logn_us_pw() # 進行斷言 self.app.AssertAcitity(self,'.main.activity.MainActivity') pass if __name__ == '__main__': unittest.main()判斷是否能夠承購跳轉
第三條:建立meetc包,包下我們建立meetc,在meetc裡我們建立meetcontrol.py
#-*- coding:utf-8 -*- from util import apputil class MeetControl(object): def __init__(self,app): # self.app=apputil.Apputil() self.app=app pass #點選我的 def meet_click_tody(self): #通過內容查詢 self.app.ClickXpath("//android.widget.FrameLayout[@resource-id='com.qiezzi.eggplant:id/fl_mian_frag']/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[2]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.view.ViewGroup[5]/android.widget.TextView[6]") #因為有網路請求時間所以設定休眠、 self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) #查詢listview控制元件 items=self.app.driver.find_elements_by_id("com.qiezzi.eggplant:id/ll_appointment_item") return len(items) pass單元測試:meet.py
#-*- coding:utf-8 -*- import unittest from util import apputil from welcomec.control import welcomcontrol from loginc.clogin import logincontrol from meetc.meetc import meetcontrol #定義類 class Meet(unittest.TestCase): @classmethod def setUpClass(self): #例項化工具類 self.app=apputil.Apputil() self.welcome=welcomcontrol.WelcomeControl(self.app) self.login=logincontrol.LoginControl(self.app) #例項化預約控制類 self.meet=meetcontrol.MeetControl(self.app) pass def setUp(self): self.app.app_start() self.welcome.welcome_jumnp(1) self.login.logn_us_pw() pass def tearDown(self): self.app.app_quit() pass def test_click_clander(self): u"""點選今天看看數量能不能對上""" count = self.meet.meet_click_tody(); #點選今天進行斷言 self.app.AssertCount(self,count,0) passpass
這條用例我們通過查詢預約條數,來斷言,一般到這裡我們都會出現一些問題,斷言可能有點問題
第四條,我們通過預約流程來搞
直接搞單元測試啦累死了
addpatient.py
#-*- coding:utf-8 -*- import unittest from util import apputil from welcomec.control import welcomcontrol from loginc.clogin import logincontrol from meetc.meetc import meetcontrol #宣告類繼承單元測試 class AddPatient(unittest.TestCase): @classmethod def setUpClass(self): self.app=apputil.Apputil() self.welcome=welcomcontrol.WelcomeControl(self.app) self.login=logincontrol.LoginControl(self.app) self.meet=meetcontrol.MeetControl(self.app) pass def setUp(self): #開啟app self.app.app_start() #點選跳過 self.welcome.welcome_jumnp(1) #點選登入 self.login.logn_us_pw() pass def tearDown(self): self.app.app_quit() pass # 新建預約測試用例 def test_new_add_patient(self): u"""新建患者功能""" tv_current_mouth = self.app.ClickID("com.qiezzi.eggplant:id/tv_current_mouth") # 設定休眠 因為這裡需要調整頁面,載入資料 self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) # 查詢一組控制元件,點選第一個元素 self.app.ClickIDs("com.qiezzi.eggplant:id/ll_adapter_group", 0) # 設定患者為1: 複診 2:設定預約事項為: 根管預備 3: 設定日期為當天 4: 設定時間為當前實際多半個小時 5: # 設定休眠 self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) # 點選複診 self.app.ClickID("com.qiezzi.eggplant:id/btn_add_new_appoint_sencod") # 點選預約事項為根管預備 self.app.ClickID("com.qiezzi.eggplant:id/ll_activity_add_new_appoint_times") # 設定休眠 self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) # 查詢一組,點選第一個根管預備 self.app.ClickIDs("com.qiezzi.eggplant:id/rl_adapter_see_doctor", 0) # 點選儲存按鈕 self.app.ClickID("com.qiezzi.eggplant:id/tv_main_title_setting") # 點選預約日期,選擇今天 self.app.ClickID("com.qiezzi.eggplant:id/ll_activity_add_new_appoint_data") # 直接點選完成 self.app.ClickID("android:id/button1") # 點選預約時間 self.app.ClickID("com.qiezzi.eggplant:id/ll_activity_add_new_appoint_time") e2 = self.app.FindXpath( "//android.widget.EditText[@resource-id='android:id/numberpicker_input' and @text='00']") self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) e1 = self.app.FindXpath("//android.widget.EditText[@resource-id='android:id/numberpicker_input' and @text='01']") # 點選日期選擇 self.app.swith_to_element(e1, e2) # 點選 完成按鈕 self.app.ClickID("android:id/button1") # 點選儲存 tv_main_title_setting = self.app.ClickID("com.qiezzi.eggplant:id/tv_main_title_setting") # 加入休眠 self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) # 點選返回按鈕 self.app.driver.keyevent(4) # 休眠 在這裡activity執行onResume 方法載入資料,這樣才能確保資料的準確行 self.app.TimeSleep(apputil.ENUMS.FIVE_TIME) # 查詢控制元件,斷言 count = self.meet.meet_click_tody( "//android.widget.FrameLayout[@resource-id='com.qiezzi.eggplant:id/fl_mian_frag']/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[2]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.view.View[4]/android.widget.TextView[1]"); # 點選今天進行斷言 self.app.AssertCount(self, count / 2, 2) passpass
這裡問題將就出現了,比如點選預約事項,預約時間啊等等,我發現這款app跟模擬器的版本很有關係。你們慢慢研究
最後附上測試報告
建立suit包,suit.py
#-*- coding:utf-8 -*- import unittest # 匯入單元測試 from unit import login,meet,welcome,addpatient import HTMLTestRunner # 匯入os import os import sys reload(sys) sys.setdefaultencoding('UTF-8') # 例項化suit suit = unittest.TestSuite() # suit.addTest(unittest.makeSuite(welcome.Welcome)) # suit.addTest(unittest.makeSuite(login.Login)) # suit.addTest(unittest.makeSuite(meet.Meet)) suit.addTest(unittest.makeSuite(addpatient.AddPatient)) # 事例 files = os.getcwd() +"/qiezi.html" # 指定讀寫方式 filename = open(files,"wb") # 執行自動化測試 runner = HTMLTestRunner.HTMLTestRunner(stream=filename,title=u"茄子",description=u"茄子醫生") runner.run(suit)