测试一款安卓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
创建一个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
最后附上测试报告
创建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)