一、用户登录与游客登录的区别:
用户登录有登录模块、天气模块显示天气等
二、登录模块分析与用例设计:
sheet1:手机号测试用例
sheet2:邮箱测试用例
三、脚本实现
登录模块思维导图:
其他模块与游客登录差不多,注意不需要权限的获取,代码参考:python3+appnium1.10+Uiautomator2过程化脚本遍历测试(1)游客登录-CSDN博客
import os
import time
from appium import webdriver
from appium.webdriver.webdriver import By
from selenium.webdriver.support.wait import WebDriverWait
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
import pytest
from xToolkit import xfile
import shutil
from pathlib import Path
# import test_ykLogin
#表格测试用例
phone_list = xfile.read("userLoginData1.xls").excel_to_dict(sheet=0)
email_list = xfile.read("userLoginData1.xls").excel_to_dict(sheet=1)
#正确手机账号
phone_num = 15***492
password_num = "***"
class TestClass:
def setup(self):
desi_caps = dict()
desi_caps['platformName'] = 'Android'
desi_caps['platformVersion'] = '9'
desi_caps['deviceName'] = '19052315134267'
desi_caps['unicodeKeyboard'] = True
desi_caps['resetKeyboard'] = True
desi_caps['automationName'] = 'UIAutomator2'
desi_caps['noReset'] = True
print("11111111111111")
os.system("adb shell svc wifi enable")
# 包名
desi_caps['appPackage'] = 'com.waterworld.haifit'
# 界面名
desi_caps['appActivity'] = 'com.waterworld.haifit.ui.module.account.SplashActivity'
global driver
driver = webdriver.Remote('http://localhost:4723/wd/hub', desi_caps)
time.sleep(8)
print("appnium已加载完毕")
def find_el_by_id_click(self,id,time =10,frequency=1):
WebDriverWait(driver,time,frequency).until(
lambda x: x.find_element(By.ID, id) ).click()
def find_el_by_id_sendkeys(self,id,data,time =10,frequency=1):
WebDriverWait(driver,time,frequency).until(
lambda x: x.find_element(By.ID, id) ).send_keys(data)
def get_screenshot_as_file(self,path,png_name):
driver.get_screenshot_as_file(
path % (time.strftime("%Y_%m_%d %H_%M_%S"), png_name))
#-----2、进入账号登录环节
def input_testdata(self,data_list,user_id,password_id):
# 可见密码
print("开始测了--11")
self.find_el_by_id_click("com.waterworld.haifit:id/cb_login_password_is_visible")
print("密码已经设置为可见--")
for i in data_list:
text_result = i.get("预期结果")
print("1`1```1")
# user = WebDriverWait(driver, 15).until(
# lambda x: x.find_element(By.ID, user_id))
self.find_el_by_id_sendkeys(user_id, i.get("账号") )
print("123")
time.sleep(1)
print("--账号已输入--")
# password = WebDriverWait(driver, 15).until(
# lambda x: x.find_element(By.ID, password_id))
self.find_el_by_id_sendkeys(password_id, i.get("密码") )
time.sleep(1)
print("--密码已输入--")
if i.get("预期结果") == "不可点" or i.get("预期结果")== "登录成功":
print("是不可点或者登录成功")
# WebDriverWait(driver, 15).until(
# lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"登录\")")).click()
self.find_el_by_id_click("com.waterworld.haifit:id/mbtn_login")
time.sleep(4)
# driver.get_screenshot_as_file(
# "../image_user/%s%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S"), text_result ))
self.get_screenshot_as_file("../image_user/%s%s.png",text_result)
time.sleep(2)
else:
# text模糊定位
print("-----------------登录错误提示:")
# WebDriverWait(driver, 8, 0.01).until(
# lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"登录\")")).click()
self.find_el_by_id_click("com.waterworld.haifit:id/mbtn_login", 18, 0.01)
element = WebDriverWait(driver, 6, 0.01).until(
lambda x: x.find_element(By.XPATH, '//*[contains(@text, "%s")]'%text_result))
# driver.find_element_by_xpath('//*[contains(@text, "%s")]'%text)
self.get_screenshot_as_file("../image_user/%s%s .png",element.text)
# driver.get_screenshot_as_file( "../image_user/%s%s .png" % (time.strftime("%Y_%m_%d %H_%M_%S"), element.text))
if element.text == text_result:
print("%s,结果一致"%i.get("预期结果"))
time.sleep(2)
def loginoff(self):
print("进入退出登录--")
self.find_el_by_id_click("com.waterworld.haifit:id/rb_main_mine",15)
self.find_el_by_id_click("com.waterworld.haifit:id/mbtn_login_out", 15)
self.find_el_by_id_click("com.waterworld.haifit:id/tv_dialog_confirm", 15)
print("---登录状态退出")
def test_case_login(self):
# try:
print("开始test了")
self.find_el_by_id_click("com.waterworld.haifit:id/tv_title_left")
# WebDriverWait(driver, 15).until(
# lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/tv_title_left")).click()
print("已切换到手机登录-------------")
self.input_testdata(phone_list, "com.waterworld.haifit:id/et_account_phone",
"com.waterworld.haifit:id/medt_input_psw")
self.loginoff()
print("$$$$$$切换到邮箱$$$$$$$$")
self.find_el_by_id_click("com.waterworld.haifit:id/tv_title_right", 15)
# WebDriverWait(driver, 8,0.01).until(
# lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/tv_title_right")).click()
print("-----------进入邮箱登录")
self.input_testdata(email_list, "com.waterworld.haifit:id/et_account_email",
"com.waterworld.haifit:id/medt_input_psw")
self.loginoff()
print("+++==============登录模块测试完毕==============+++")
# except Exception as result:
# print("发现错误 %s" %result)
def test_case_loggedIn(self):
#登录界面:手机
self.find_el_by_id_click("com.waterworld.haifit:id/tv_title_left")
print("已切换到正式功能测试-------------")
#登录
self.find_el_by_id_sendkeys("com.waterworld.haifit:id/et_account_phone",phone_num,8,0.01)
self.find_el_by_id_sendkeys("com.waterworld.haifit:id/medt_input_psw",password_num,8,0.01)
self.find_el_by_id_click("com.waterworld.haifit:id/mbtn_login")
print("已登录")
time.sleep(8)
print("已切换到“健康”页面:")
WebDriverWait(driver, 20).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"健康习惯\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().textContains(\"勤喝水\")"))
print("找到了 勤喝水")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().textContains(\"久坐提醒\")"))
print("找到了 久坐提醒")
driver.press_keycode(4) # 点击返回键
print("切换到'我的'页面:")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"我的\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/iv_edt_info")).click() # 右上角编辑
el_nichen = WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/lrtv_name"))
el_nichen.click() # 昵称
print("点击昵称")
test_nichen = "phone_test"
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/et_dialog_edit_content")).send_keys(test_nichen) # 改昵称
print("######1、修改昵称成功")
confirm = WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().textContains(\"确认\")"))
confirm.click() # 确认
# 改性别 :女 "com.waterworld.haifit:id/tv_lrtv_right"
win_width = driver.get_window_size()['width']
win_height = driver.get_window_size()['height']
print("~~~~~~~~~~~~获取到分辨率了~~~~~~~~~~~~~~")
def swipe_select(id):
WebDriverWait(driver, 15).until(lambda x: x.find_element(By.ID, id)).click()
time.sleep(2)
print("找到元素了,要开始滑动了::::")
driver.swipe(win_width * 0.5, win_height * 0.57, win_width * 0.5, win_height * 0.39) # 比例:元素/屏幕
time.sleep(1)
confirm.click() # 含确认
swipe_select("com.waterworld.haifit:id/lrtv_sex")
print("######1、修改sex成功")
# 改出生年 :1995 com.waterworld.haifit:id/tv_lrtv_right
swipe_select("com.waterworld.haifit:id/lrtv_birth_year")
print("######1、修改出生年成功")
# 改身高
swipe_select("com.waterworld.haifit:id/lrtv_height")
print("######1、修改身高成功")
# 改体重 62
swipe_select("com.waterworld.haifit:id/lrtv_weight")
print("######1、修改体重成功")
# 改头像
print("开始改头像了!!!")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/head_img")).click() # 头像
# 拍照
print("进入相机")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"拍照\")")).click()
print("进入相机:--")
time.sleep(3)
WebDriverWait(driver, 15).until(lambda x: x.find_element(By.ID, "com.android.camera2:id/camera_toggle_button_dream")).click() # 翻转相机
print("翻转相机")
time.sleep(2)
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.android.camera2:id/shutter_button")).click() # 拍照按钮
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.android.camera2:id/done_button")).click() # 照片确认
def back_screen(model):
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"保存副本\")")).click()
print("已保存副本")
time.sleep(4)
driver.press_keycode(4) # 点击返回键
print("已返回")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/iv_edt_info")).click() # 右上角编辑
print("找到编辑了11111")
time.sleep(2)
driver.get_screenshot_as_file("../image_loggedtest/%s%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S"), model))
print("更新之后存的个人信息的截图已保存")
print("拍照获取头像完成-----")
back_screen("用户--拍照")
# 相册获取
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/head_img")).click() # 头像
print("已重新获取个人头像")
WebDriverWait(driver, 15,0.01).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"从手机相册获取\")")).click()
WebDriverWait(driver, 15,0.01).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"相机\")")).click()
print("已进入系统相册")
time.sleep(2)
print("从相册获取头像完成-----")
# 从坐标获取系统相册图片
# driver.tap( [(126 ,465)] ,1000)
# TouchAction(driver).press( x= int(win_height * 0.17) , y = int(win_width * 0.30) ).release().perform()
TouchAction(driver).press(x=126, y=465).release().perform()
back_screen("用户--从相册获取照片")
# 我的 页面 每日目标、使用说明、关于 无网状态
# 一些信息判断
def contains_hafit():
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().textContains(\"HaFit\")"))
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().textContains(\"沃特沃德\")"))
def my_tag_about():
# 每日目标
driver.press_keycode(4) # 点击返回键
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"每日目标\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"步数目标\")")).click()
driver.swipe(win_width * 0.5, win_height * 0.57, win_width * 0.5, win_height * 0.39) # 比例:元素/屏幕
confirm.click() # 包含确认
driver.press_keycode(4) # 点击返回键
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"每日目标\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"12000步\")"))
print("每日目标没问题======")
driver.press_keycode(4) # 点击返回键
# 使用说明
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"使用说明\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"手表防水吗?\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"手表防水吗?\")"))
print("使用说明没问题======")
driver.press_keycode(4) # 点击返回键
driver.press_keycode(4) # 点击返回键
# 关于 无网
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"关于\")")).click()
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"用户协议\")")).click()
time.sleep(2)
print("用户协议没问题======")
contains_hafit()
driver.press_keycode(4) # 点击返回键
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"隐私政策\")")).click()
contains_hafit()
driver.press_keycode(4) # 点击返回键
driver.press_keycode(4) # 点击返回键
# 判断 我的 中昵称
print("判断“我的”中的昵称----")
driver.press_keycode(4) # 点击返回键
username = WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/tv_mine_name")).text
defult_nichen = "phone"
test_nichen = defult_nichen + "_test"
if username == test_nichen:
print("昵称修改成功!")
# 运动模块
print("进入运动模块-----")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"运动\")")).click()
# WebDriverWait(driver, 15).until(
# lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/iv_sport_start")).click()
print("开始运动了!!!")
# permit.click()
def sport(xingshi):
print("进入GO---")
time.sleep(3)
WebDriverWait(driver, 18).until(lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/iv_sport_start")).click() # GO
print("长按:")
# 长按 跑步
long_pause = WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/view_start_sport_pause"))
print("已暂停")
TouchAction(driver).long_press(long_pause, duration=5000).release().perform()
print("已暂停")
print("进入地图====")
time.sleep(3)
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/iv_start_sport_map")).click()
WebDriverWait(driver, 30).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"时长\")"))
time.sleep(5)
driver.get_screenshot_as_file("../image_loggedtest/%s%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S"), xingshi))
print("运动地图已截图%%%%")
WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/iv_start_sport_close")).click() # 叉掉
long_stop = WebDriverWait(driver, 15).until(
lambda x: x.find_element(By.ID, "com.waterworld.haifit:id/view_start_sport_stop"))
TouchAction(driver).long_press(long_stop, duration=5000).release().perform()
WebDriverWait(driver, 30).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"结束运动\")")).click()
print("开始跑步-----")
sport("跑步")
# 健走
print("开始健走-----")
WebDriverWait(driver, 30).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"健走\")")).click()
sport("健走")
# 登山
print("开始登山-----")
WebDriverWait(driver, 30).until(
lambda x: x.find_element(By.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"登山\")")).click()
sport("登山")
self.loginoff()
print("-------------*******----------------")
print("++++游客——模块已全部测试通过+++++++++++++++————————————————————————")
def del_file(path):
for elm in Path(path).glob('*'):
elm.unlink() if elm.is_file() else shutil.rmtree(elm)
#默认:手机登录
if __name__ =='__main__':
path_user = r'D:\AppniumPro1\image_user' # 输入文件夹地址
path_loggedtest = r'D:\AppniumPro1\image_loggedtest' # 输入文件夹地址
del_file(path_user)
del_file(path_loggedtest)
pytest.main(['-s','-v','--capture=sys','test_user.py'])
# files = os.listdir(path) # 读入文件夹
# num_png = len(files) # 统计文件夹中的文件个数
四、一些遇到的问题和解决思路
4.1为什么大量使用ID定位?
4.2如何进行弹窗toast定位?
建议弹窗截图前的步骤节约运行时间,所以我将“登录按钮”放入每个条件内执行;由于弹窗弹出时间短,定位弹窗时,一定要大频率;定位弹窗建议用路径或ID
4.3截图很难手动删咋办?
每次启动前删除指定文件夹下的文件,传入的文件路径要绝对路径比较好。
4.4查找元素方法很长,如何变简洁?
咱们直接就是在类里写一个方法
4.5两部分有很多重复代码,为啥不直接调用模块的方法 ?
1、因为引用游客登录模块(应用重置)会导致appnium重新连接,需要重新获取重置,并且会自动执行游客登录的代码。
2、分开模块有利于游客身份和用户身份不同代码的运行。